import { type ReactNode, useMemo, useState } from 'react'

export interface Column<T> {
  header: string
  accessor: (row: T) => ReactNode
  className?: string
  sortKey?: (row: T) => string | number
}

type SortDir = 'asc' | 'desc'

interface AdminTableProps<T> {
  columns: Column<T>[]
  data: T[]
  isLoading?: boolean
  emptyMessage?: string
  onRowClick?: (row: T) => void
  keyFn: (row: T) => string | number
}

export function AdminTable<T>({
  columns,
  data,
  isLoading,
  emptyMessage = 'No data found.',
  onRowClick,
  keyFn,
}: AdminTableProps<T>) {
  const [sortCol, setSortCol] = useState<string | null>(null)
  const [sortDir, setSortDir] = useState<SortDir>('asc')

  const handleSort = (header: string) => {
    if (sortCol === header) {
      if (sortDir === 'asc') {
        setSortDir('desc')
      } else {
        // Third click: clear sort
        setSortCol(null)
        setSortDir('asc')
      }
    } else {
      setSortCol(header)
      setSortDir('asc')
    }
  }

  const sortedData = useMemo(() => {
    if (!sortCol) return data
    const col = columns.find((c) => c.header === sortCol)
    if (!col?.sortKey) return data
    const key = col.sortKey
    const sorted = [...data].sort((a, b) => {
      const va = key(a)
      const vb = key(b)
      if (va < vb) return -1
      if (va > vb) return 1
      return 0
    })
    return sortDir === 'desc' ? sorted.reverse() : sorted
  }, [data, sortCol, sortDir, columns])

  if (isLoading) {
    return (
      <div className="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
        <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
          <thead className="bg-gray-50 dark:bg-gray-800">
            <tr>
              {columns.map((col) => (
                <th
                  key={col.header}
                  className={`px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider ${col.className ?? ''}`}
                >
                  {col.header}
                </th>
              ))}
            </tr>
          </thead>
          <tbody className="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700">
            {Array.from({ length: 5 }).map((_, i) => (
              <tr key={i}>
                {columns.map((col) => (
                  <td
                    key={col.header}
                    className={`px-4 py-3 ${col.className ?? ''}`}
                  >
                    <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded animate-pulse" />
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    )
  }

  if (data.length === 0) {
    return (
      <div className="text-center py-8 text-gray-500 dark:text-gray-400 border border-gray-200 dark:border-gray-700 rounded-lg">
        {emptyMessage}
      </div>
    )
  }

  return (
    <div className="border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden">
      <div className="overflow-x-auto">
        <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
          <thead className="bg-gray-50 dark:bg-gray-800">
            <tr>
              {columns.map((col) => {
                const sortable = !!col.sortKey
                const active = sortCol === col.header
                return (
                  <th
                    key={col.header}
                    onClick={
                      sortable ? () => handleSort(col.header) : undefined
                    }
                    className={`px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider ${col.className ?? ''} ${sortable ? 'cursor-pointer select-none hover:text-gray-700 dark:hover:text-gray-200' : ''}`}
                  >
                    <span className="inline-flex items-center gap-1">
                      {col.header}
                      {sortable && active && (
                        <span className="text-blue-500">
                          {sortDir === 'asc' ? '\u2191' : '\u2193'}
                        </span>
                      )}
                    </span>
                  </th>
                )
              })}
            </tr>
          </thead>
          <tbody className="bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700">
            {sortedData.map((row) => (
              <tr
                key={keyFn(row)}
                onClick={onRowClick ? () => onRowClick(row) : undefined}
                className={
                  onRowClick
                    ? 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800'
                    : ''
                }
              >
                {columns.map((col) => (
                  <td
                    key={col.header}
                    className={`px-4 py-3 text-sm whitespace-nowrap ${col.className ?? ''}`}
                  >
                    {col.accessor(row)}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  )
}
