import {
  type ColumnDef,
  flexRender,
  getCoreRowModel,
  useReactTable,
} from "@tanstack/react-table"
import { Loader } from "lucide-react"
import { useMemo } from "react"
import { Checkbox } from "@/components/ui/checkbox"
import { Pagination, type PaginationProps } from "@/components/ui/pagination"
import {
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  Table as TableRoot,
  TableRow,
} from "@/components/ui/table"
import { cn } from "@/lib/utils"

export type DataTableProps<T> = {
  data: T[]
  status: "load" | "done" | "fail"
  columns: ColumnDef<T>[]
  pagination?: PaginationProps
  classNames?: {
    headRow?: string
    dataRow?: string
  }
  enableSelection?: boolean
  rowSelection?: Record<string, boolean>
  onSelectionChange?: (selection: Record<string, boolean>) => void
  getRowId?: (row: T, index: number) => string
  stickyHeader?: boolean
  maxHeight?: string
}

export default function DataTable<T extends Record<string, unknown>>(
  props: DataTableProps<T>,
) {
  // 动态注入复选框列
  const finalColumns = useMemo<ColumnDef<T>[]>(() => {
    if (!props.enableSelection) return props.columns

    const selectColumn: ColumnDef<T> = {
      id: "select",
      size: 40,
      enableSorting: false,
      enableHiding: false,
      header: ({ table }) => (
        <Checkbox
          checked={
            table.getIsAllPageRowsSelected()
              ? true
              : table.getIsSomePageRowsSelected()
                ? "indeterminate"
                : false
          }
          onCheckedChange={value => table.toggleAllPageRowsSelected(!!value)}
          aria-label="全选当前页"
          className="rounded-none translate-y-0.5"
        />
      ),
      cell: ({ row }) => (
        <Checkbox
          checked={row.getIsSelected()}
          onCheckedChange={value => row.toggleSelected(!!value)}
          aria-label="选择行"
          className="rounded-none translate-y-0.5"
        />
      ),
    }

    return [selectColumn, ...props.columns]
  }, [props.enableSelection, props.columns])

  const table = useReactTable({
    data: props.data,
    columns: finalColumns,
    getCoreRowModel: getCoreRowModel(),
    manualPagination: true,
    rowCount: props.pagination?.total ?? props.data.length,
    // 行选择核心配置
    enableRowSelection: props.enableSelection ?? false,
    getRowId: props.getRowId,
    onRowSelectionChange: updaterOrValue => {
      if (!props.onSelectionChange) return

      const newSelection =
        typeof updaterOrValue === "function"
          ? updaterOrValue(props.rowSelection ?? {})
          : updaterOrValue

      props.onSelectionChange(newSelection)
    },
    state: {
      pagination: {
        pageIndex: props.pagination?.page ?? 0,
        pageSize: props.pagination?.size ?? props.data.length,
      },
      columnFilters: [],
      ...(props.rowSelection !== undefined && {
        rowSelection: props.rowSelection,
      }),
    },
    autoResetPageIndex: false,
  })

  return (
    <>
      {/* 数据表 */}
      <div className="rounded-md relative bg-card">
        <TableRoot
          containerClassName={
            props.stickyHeader
              ? cn("overflow-y-auto", props.maxHeight ?? "max-h-[600px]")
              : undefined
          }
        >
          <TableHeader
            className={
              props.stickyHeader ? "sticky top-0 z-10 bg-card" : undefined
            }
          >
            {table.getHeaderGroups().map(group => (
              <TableRow key={group.id} className={props.classNames?.headRow}>
                {group.headers.map(header => (
                  <TableHead key={header.id} colSpan={header.colSpan}>
                    {header.isPlaceholder
                      ? null
                      : flexRender(
                          header.column.columnDef.header,
                          header.getContext(),
                        )}
                  </TableHead>
                ))}
              </TableRow>
            ))}
          </TableHeader>
          <TableBody>
            {props.status === "fail" ? (
              <TableRow>
                <TableCell
                  colSpan={finalColumns.length}
                  className="text-center text-fail"
                >
                  加载失败
                </TableCell>
              </TableRow>
            ) : !props.data?.length ? (
              <TableRow>
                <TableCell
                  colSpan={finalColumns.length}
                  className="text-center"
                >
                  暂无数据
                </TableCell>
              </TableRow>
            ) : (
              table.getRowModel().rows.map(row => (
                <TableRow
                  key={row.id}
                  data-state={row.getIsSelected() && "selected"}
                  className={cn("h-14", props.classNames?.dataRow)}
                >
                  {row.getVisibleCells().map(cell => (
                    <TableCell key={cell.id}>
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext(),
                      )}
                    </TableCell>
                  ))}
                </TableRow>
              ))
            )}
          </TableBody>
        </TableRoot>
        {props.status === "load" && (
          <div className="absolute inset-0 bg-white/10 backdrop-blur-xs flex items-center justify-center gap-2 transition">
            <Loader className="animate-spin" />
            <span>加载中</span>
          </div>
        )}
      </div>

      {/* 分页器 */}
      {props.pagination && <Pagination {...props.pagination} />}
    </>
  )
}
