import { ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react';
import type { VisibilityMode } from '@/hooks/useTableVisibility';

export interface ColumnDef<T> {
  key: string;
  label: string;
  render: (item: T) => React.ReactNode;
  sortable?: boolean;
  visibilityLevel: VisibilityMode;
}

interface EntityTableProps<T extends { id: number }> {
  columns: ColumnDef<T>[];
  rows: T[];
  pinnedRows: T[];
  pinnedLabel: string;
  showPinned: boolean;
  selectedId: number | null;
  onRowClick: (id: number) => void;
  sortKey: string;
  sortDir: 'asc' | 'desc';
  onSort: (key: string) => void;
  visibilityMode: VisibilityMode;
  loading?: boolean;
}

const LEVEL_ORDER: VisibilityMode[] = ['essential', 'filtered', 'all'];

function isVisible(colLevel: VisibilityMode, mode: VisibilityMode): boolean {
  return LEVEL_ORDER.indexOf(colLevel) <= LEVEL_ORDER.indexOf(mode);
}

function SkeletonRow({ colCount }: { colCount: number }) {
  return (
    <tr className="border-b border-border/50">
      {Array.from({ length: colCount }).map((_, i) => (
        <td key={i} className="px-3 py-2.5">
          <div className="animate-pulse rounded-md bg-muted h-4 w-full" />
        </td>
      ))}
    </tr>
  );
}

export function EntityTable<T extends { id: number }>({
  columns,
  rows,
  pinnedRows,
  pinnedLabel,
  showPinned,
  selectedId,
  onRowClick,
  sortKey,
  sortDir,
  onSort,
  visibilityMode,
  loading = false,
}: EntityTableProps<T>) {
  const visibleColumns = columns.filter((col) => isVisible(col.visibilityLevel, visibilityMode));
  const colCount = visibleColumns.length;
  const showPinnedSection = showPinned && pinnedRows.length > 0;

  const SortIcon = ({ colKey }: { colKey: string }) => {
    if (sortKey !== colKey) return <ArrowUpDown className="h-3.5 w-3.5 ml-1 opacity-40" />;
    return sortDir === 'asc' ? (
      <ArrowUp className="h-3.5 w-3.5 ml-1" />
    ) : (
      <ArrowDown className="h-3.5 w-3.5 ml-1" />
    );
  };

  const DataRow = ({ item }: { item: T }) => (
    <tr
      className={`border-b border-border/50 cursor-pointer hover:bg-card-elevated transition-colors duration-150 outline-none focus-visible:ring-1 focus-visible:ring-ring ${
        selectedId === item.id ? 'bg-accent/10' : ''
      }`}
      onClick={() => onRowClick(item.id)}
      onKeyDown={(e) => {
        if (e.key === 'Enter' || e.key === ' ') {
          e.preventDefault();
          onRowClick(item.id);
        }
      }}
      tabIndex={0}
      role="row"
      aria-selected={selectedId === item.id}
    >
      {visibleColumns.map((col) => (
        <td key={col.key} className="px-3 py-2.5 text-sm">
          {col.render(item)}
        </td>
      ))}
    </tr>
  );

  return (
    <div className="w-full">
      <table className="w-full border-collapse">
        <thead>
          <tr className="border-b border-border">
            {visibleColumns.map((col) => (
              <th
                key={col.key}
                className="px-3 py-2 text-left text-[11px] uppercase tracking-wider text-muted-foreground font-medium"
              >
                {col.sortable ? (
                  <button
                    type="button"
                    onClick={() => onSort(col.key)}
                    aria-label={`Sort by ${col.label}`}
                    className="flex items-center hover:text-foreground transition-colors duration-150"
                  >
                    {col.label}
                    <SortIcon colKey={col.key} />
                  </button>
                ) : (
                  col.label
                )}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {loading ? (
            Array.from({ length: 6 }).map((_, i) => <SkeletonRow key={i} colCount={colCount} />)
          ) : (
            <>
              {showPinnedSection && (
                <>
                  <tr>
                    <td
                      colSpan={colCount}
                      className="px-3 py-1.5 text-[11px] uppercase tracking-wider text-muted-foreground"
                    >
                      {pinnedLabel}
                    </td>
                  </tr>
                  {pinnedRows.map((item) => (
                    <DataRow key={item.id} item={item} />
                  ))}
                  <tr>
                    <td colSpan={colCount} className="border-b border-border/50" />
                  </tr>
                </>
              )}
              {rows.map((item) => (
                <DataRow key={item.id} item={item} />
              ))}
            </>
          )}
        </tbody>
      </table>
    </div>
  );
}
