import { Fragment, useState } from 'react'
import {
  type ColumnDef,
  type Row,
  type RowData,
  flexRender,
  getCoreRowModel,
  useReactTable,
} from '@tanstack/react-table'
import { ChevronDown } from 'lucide-react'
import { cn } from '@/lib/utils'
import { Skeleton } from '@/components/ui/skeleton'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'

/* ────────────────────────────────────────────────────────────────
   Column meta para priority responsive
   ──────────────────────────────────────────────────────────────── */

declare module '@tanstack/react-table' {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  interface ColumnMeta<TData extends RowData, TValue> {
    /**
     * Visibility priority for responsive tables:
     * - 'high' (default): always visible
     * - 'medium': hidden < md (768px)
     * - 'low': hidden < lg (1024px)
     */
    priority?: 'high' | 'medium' | 'low'
    /** Right-align cell content (numbers, badges) */
    align?: 'left' | 'right' | 'center'
  }
}

function priorityClass(priority?: 'high' | 'medium' | 'low'): string {
  if (priority === 'low') return 'hidden lg:table-cell'
  if (priority === 'medium') return 'hidden md:table-cell'
  return ''
}

function alignClass(align?: 'left' | 'right' | 'center'): string {
  if (align === 'right') return 'text-right'
  if (align === 'center') return 'text-center'
  return ''
}

/* ────────────────────────────────────────────────────────────────
   DataTable
   ──────────────────────────────────────────────────────────────── */

export interface DataTableProps<TData> {
  columns: ColumnDef<TData>[]
  data: TData[]
  /** Row click handler — fires on row body click (NOT on expand chevron) */
  onRowClick?: (row: TData) => void
  isLoading?: boolean
  /** Empty state message */
  emptyMessage?: string
  /** Stable row ID extractor for React keys + expand state */
  getRowId?: (row: TData, index: number) => string
}

export function DataTable<TData>({
  columns,
  data,
  onRowClick,
  isLoading = false,
  emptyMessage = 'Sin resultados.',
  getRowId,
}: DataTableProps<TData>) {
  const [expandedId, setExpandedId] = useState<string | null>(null)

  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    getRowId: getRowId ?? ((_row, index) => String(index)),
  })

  // Hidden columns trigger the mobile expand-row affordance
  const hasHiddenCols = columns.some(
    (c) => c.meta?.priority === 'medium' || c.meta?.priority === 'low',
  )

  if (isLoading) {
    return <DataTableSkeleton columns={Math.max(columns.length, 4)} rows={5} />
  }

  if (data.length === 0) {
    return (
      <div className="surface py-12 text-center text-sm text-muted-foreground">
        {emptyMessage}
      </div>
    )
  }

  return (
    <div className="surface overflow-hidden">
      <Table>
        <TableHeader>
          {table.getHeaderGroups().map((headerGroup) => (
            <TableRow
              key={headerGroup.id}
              className="bg-muted/40 hover:bg-muted/40"
            >
              {hasHiddenCols && (
                <TableHead className="w-10 md:hidden" aria-hidden="true" />
              )}
              {headerGroup.headers.map((header) => {
                const meta = header.column.columnDef.meta
                return (
                  <TableHead
                    key={header.id}
                    className={cn(
                      'h-10 text-xs font-medium uppercase tracking-wider text-muted-foreground/80',
                      priorityClass(meta?.priority),
                      alignClass(meta?.align),
                    )}
                  >
                    {header.isPlaceholder
                      ? null
                      : flexRender(
                          header.column.columnDef.header,
                          header.getContext(),
                        )}
                  </TableHead>
                )
              })}
            </TableRow>
          ))}
        </TableHeader>
        <TableBody>
          {table.getRowModel().rows.map((row) => (
            <DataTableRow
              key={row.id}
              row={row}
              expanded={expandedId === row.id}
              onToggleExpand={() =>
                setExpandedId((prev) => (prev === row.id ? null : row.id))
              }
              onRowClick={onRowClick}
              hasHiddenCols={hasHiddenCols}
            />
          ))}
        </TableBody>
      </Table>
    </div>
  )
}

/* ────────────────────────────────────────────────────────────────
   Row con expand para mobile
   ──────────────────────────────────────────────────────────────── */

interface DataTableRowProps<TData> {
  row: Row<TData>
  expanded: boolean
  onToggleExpand: () => void
  onRowClick?: (row: TData) => void
  hasHiddenCols: boolean
}

function DataTableRow<TData>({
  row,
  expanded,
  onToggleExpand,
  onRowClick,
  hasHiddenCols,
}: DataTableRowProps<TData>) {
  const cells = row.getVisibleCells()
  const visibleCellsCount = cells.length + (hasHiddenCols ? 1 : 0)

  // Cells that DO get hidden (medium/low priority) — needed for expanded panel
  const hiddenCells = cells.filter((cell) => {
    const p = cell.column.columnDef.meta?.priority
    return p === 'medium' || p === 'low'
  })

  return (
    <Fragment>
      <TableRow
        data-state={expanded ? 'selected' : undefined}
        className={cn(
          'border-b border-border last:border-0 transition-colors',
          onRowClick && 'cursor-pointer hover:bg-accent/40',
        )}
        onClick={onRowClick ? () => onRowClick(row.original) : undefined}
      >
        {hasHiddenCols && (
          <TableCell
            className="w-10 px-2 md:hidden"
            onClick={(e) => {
              e.stopPropagation()
              onToggleExpand()
            }}
          >
            <button
              type="button"
              aria-label={expanded ? 'Colapsar fila' : 'Expandir fila'}
              aria-expanded={expanded}
              className="flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
            >
              <ChevronDown
                className={cn(
                  'h-4 w-4 transition-transform duration-200',
                  expanded && 'rotate-180',
                )}
              />
            </button>
          </TableCell>
        )}
        {cells.map((cell) => {
          const meta = cell.column.columnDef.meta
          return (
            <TableCell
              key={cell.id}
              className={cn(
                'px-4 py-3 align-middle',
                priorityClass(meta?.priority),
                alignClass(meta?.align),
              )}
            >
              {flexRender(cell.column.columnDef.cell, cell.getContext())}
            </TableCell>
          )
        })}
      </TableRow>

      {/* Expanded panel — visible solo en mobile cuando hay cols ocultas */}
      {expanded && hiddenCells.length > 0 && (
        <TableRow className="md:hidden border-b border-border bg-muted/20 hover:bg-muted/20">
          <TableCell colSpan={visibleCellsCount} className="px-4 py-3">
            <dl className="grid grid-cols-[auto_1fr] gap-x-4 gap-y-2 text-sm">
              {hiddenCells.map((cell) => {
                const header = cell.column.columnDef.header
                return (
                  <Fragment key={cell.id}>
                    <dt className="text-xs font-medium uppercase tracking-wider text-muted-foreground/80">
                      {typeof header === 'string' ? header : cell.column.id}
                    </dt>
                    <dd className="text-foreground">
                      {flexRender(cell.column.columnDef.cell, cell.getContext())}
                    </dd>
                  </Fragment>
                )
              })}
            </dl>
          </TableCell>
        </TableRow>
      )}
    </Fragment>
  )
}

/* ────────────────────────────────────────────────────────────────
   Skeleton
   ──────────────────────────────────────────────────────────────── */

function DataTableSkeleton({ columns, rows }: { columns: number; rows: number }) {
  return (
    <div className="surface overflow-hidden">
      <div className="space-y-px">
        <div className="flex h-10 items-center gap-4 bg-muted/40 px-4">
          {Array.from({ length: columns }).map((_, i) => (
            <Skeleton key={i} className="h-3 flex-1 max-w-[120px]" />
          ))}
        </div>
        {Array.from({ length: rows }).map((_, i) => (
          <div key={i} className="flex h-12 items-center gap-4 px-4 border-b border-border last:border-0">
            {Array.from({ length: columns }).map((_, j) => (
              <Skeleton key={j} className="h-3 flex-1 max-w-[200px]" />
            ))}
          </div>
        ))}
      </div>
    </div>
  )
}
