"use client"

import {
  ColumnDef,
  ColumnFiltersState,
  ColumnSizingState,
  SortingState,
  VisibilityState,
  flexRender,
  getCoreRowModel,
  getFacetedRowModel,
  getFacetedUniqueValues,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useReactTable
} from "@tanstack/react-table"
import * as React from "react"

import {
  Dialog,
  DialogContent,
  Table, TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@repo/shadcn-ui/components'
import { DataTablePagination } from './data-table-pagination.tsx'
import { DataTableToolbar } from "./data-table-toolbar.tsx"

import { useTranslation } from "../../locales/i18n.ts"


type DataTableRowOps = {
  duplicate?(index: number): void;
  remove?(index: number): void;
  move?(from: number, to: number): void;
  canMoveUp?(index: number): boolean;
  canMoveDown?(index: number, lastIndex: number): boolean;
};

interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[]
  data: TData[],
  meta?: Record<string, any>,

  getRowId?: (row: TData, index: number) => string;
  pageSize?: number;
  enableRowSelection?: boolean;

  renderRowEditor?: (index: number, close: () => void) => React.ReactNode; // editor modal opcional. Se muestra dentro de un Dialog.
}

export function DataTable<TData, TValue>({
  columns,
  data,
  meta,
  getRowId,
  pageSize = 25,
  enableRowSelection = true,
  renderRowEditor,
}: DataTableProps<TData, TValue>) {
  const { t } = useTranslation();

  const [rowSelection, setRowSelection] = React.useState({});
  const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({});
  const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]);
  const [sorting, setSorting] = React.useState<SortingState>([]);
  const [colSizes, setColSizes] = React.useState<ColumnSizingState>({});
  const [editIndex, setEditIndex] = React.useState<number | null>(null);

  const openEditor = React.useCallback((i: number) => setEditIndex(i), []);
  const closeEditor = React.useCallback(() => setEditIndex(null), []);


  const table = useReactTable({
    data,
    columns,
    columnResizeMode: "onChange",
    onColumnSizingChange: setColSizes,
    getRowId: getRowId ?? ((row: any, idx) => (row?.id ? String(row.id) : String(idx))),
    state: {
      columnSizing: colSizes,
      sorting,
      columnVisibility,
      rowSelection,
      columnFilters,
    },
    initialState: { pagination: { pageSize } },
    meta: { ...meta, openEditor },

    enableRowSelection,
    getCoreRowModel: getCoreRowModel(),
    onRowSelectionChange: setRowSelection,
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    onColumnVisibilityChange: setColumnVisibility,
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFacetedRowModel: getFacetedRowModel(),
    getFacetedUniqueValues: getFacetedUniqueValues(),
  })

  return (
    <div className="flex flex-col gap-4">
      <DataTableToolbar table={table} />

      <div className="overflow-hidden rounded-md border">
        <Table className="w-full text-sm">
          <TableHeader className="sticky top-0 bg-muted hover:bg-muted z-10">
            {table.getHeaderGroups().map((hg) => (
              <TableRow key={hg.id}>
                {hg.headers.map((h) => {
                  const w = h.getSize(); // px
                  const minW = h.column.columnDef.minSize;
                  const maxW = h.column.columnDef.maxSize;
                  return (
                    <TableHead
                      key={h.id}
                      colSpan={h.colSpan}
                      style={{
                        width: w ? `${w}px` : undefined,
                        minWidth: typeof minW === "number" ? `${minW}px` : undefined,
                        maxWidth: typeof maxW === "number" ? `${maxW}px` : undefined,
                      }}
                    >
                      {h.isPlaceholder ? null : flexRender(h.column.columnDef.header, h.getContext())}
                    </TableHead>
                  );
                })}
              </TableRow>
            ))}
          </TableHeader>

          <TableBody>
            {table.getRowModel().rows.length ? (
              table.getRowModel().rows.map((row) => (
                <TableRow key={row.id} data-state={row.getIsSelected() && "selected"}>
                  {row.getVisibleCells().map((cell) => {
                    const w = cell.column.getSize();
                    const minW = cell.column.columnDef.minSize;
                    const maxW = cell.column.columnDef.maxSize;
                    return (
                      <TableCell
                        key={cell.id}
                        className="align-top"
                        style={{
                          width: w ? `${w}px` : undefined,
                          minWidth: typeof minW === "number" ? `${minW}px` : undefined,
                          maxWidth: typeof maxW === "number" ? `${maxW}px` : undefined,
                        }}
                      >
                        {flexRender(cell.column.columnDef.cell, cell.getContext())}
                      </TableCell>
                    );
                  })}
                </TableRow>
              ))
            ) : (
              <TableRow>
                <TableCell colSpan={columns.length} className="h-24 text-center">
                  {t("components.datatabla.empty")}
                </TableCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
      </div>

      <DataTablePagination table={table} />

      {!!renderRowEditor && editIndex !== null && (
        <Dialog open onOpenChange={(open) => (!open ? closeEditor() : null)}>
          <DialogContent className="max-w-xl">
            {renderRowEditor(editIndex, closeEditor)}
          </DialogContent>
        </Dialog>
      )}
    </div>
  );
}