"use client"

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

import {
  Button,
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  TableBody,
  TableCell,
  Table as TableComp,
  TableFooter,
  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"

export type DataTableOps<TData> = {
  onAdd?: (table: Table<TData>) => void;
}

export type DataTableRowOps<TData> = {
  duplicate?(index: number, table: Table<TData>): void;
  remove?(index: number, table: Table<TData>): void;
  move?(from: number, to: number, table: Table<TData>): void;
  canMoveUp?(index: number, table: Table<TData>): boolean;
  canMoveDown?(index: number, lastIndex: number, table: Table<TData>): boolean;
};

export type DataTableBulkRowOps<TData> = {
  duplicateSelected?: (indexes: number[], table: Table<TData>) => void;
  removeSelected?: (indexes: number[], table: Table<TData>) => void;
  moveSelectedUp?: (indexes: number[], table: Table<TData>) => void;
  moveSelectedDown?: (indexes: number[], table: Table<TData>) => void;
};

export type DataTableMeta<TData> = TableMeta<TData> & {
  tableOps?: DataTableOps<TData>
  rowOps?: DataTableRowOps<TData>
  bulkOps?: DataTableBulkRowOps<TData>
}

export interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[]
  data: TData[]
  meta?: DataTableMeta<TData>

  // Configuración
  readOnly?: boolean
  enablePagination?: boolean
  pageSize?: number
  enableRowSelection?: boolean
  EditorComponent?: React.ComponentType<{ row: TData; index: number; onClose: () => void }>

  getRowId?: (row: Row<TData>, index: number) => string;
}

export function DataTable<TData, TValue>({
  columns,
  data,
  meta,
  readOnly = false,
  enablePagination = true,
  pageSize = 25,
  enableRowSelection = false,
  EditorComponent,
}: DataTableProps<TData, TValue>) {
  const { t } = useTranslation();
  const [rowSelection, setRowSelection] = React.useState({})
  const [sorting, setSorting] = React.useState<SortingState>([])
  const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({})
  const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
  const [colSizes, setColSizes] = React.useState<ColumnSizingState>({})
  const [editIndex, setEditIndex] = React.useState<number | null>(null)

  const table = useReactTable({
    data,
    columns,
    columnResizeMode: "onChange",
    onColumnSizingChange: setColSizes,
    getRowId: (row: any, i) => row.id ?? String(i),
    meta,
    state: {
      columnSizing: colSizes,
      sorting,
      columnVisibility,
      rowSelection,
      columnFilters,
    },
    initialState: {
      pagination: { pageSize },
    },
    enableRowSelection,
    onRowSelectionChange: setRowSelection,
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    onColumnVisibilityChange: setColumnVisibility,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFacetedRowModel: getFacetedRowModel(),
    getFacetedUniqueValues: getFacetedUniqueValues(),
  })

  const handleCloseEditor = React.useCallback(() => setEditIndex(null), [])

  return (
    <div className='flex flex-col gap-0'>
      <DataTableToolbar table={table} showViewOptions={false} />

      <div className="overflow-hidden rounded-md border">
        <TableComp 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, i) => (
                <TableRow key={row.id} data-state={row.getIsSelected() && "selected"} className='group'>
                  {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 text-muted-foreground'
                >
                  {t("components.datatable.empty")}
                </TableCell>
              </TableRow>
            )}
          </TableBody>
          <TableFooter>

          </TableFooter>
        </TableComp>
      </div>

      {enablePagination && <DataTablePagination table={table} />}

      {EditorComponent && editIndex !== null && (
        <Dialog open onOpenChange={handleCloseEditor}>
          <DialogContent className="max-w-3xl">
            <DialogHeader>
              <DialogTitle>{t("components.datatable.editor.title")}</DialogTitle>
              <DialogDescription>{t("components.datatable.editor.subtitle")}</DialogDescription>
            </DialogHeader>

            <div className="mt-4">
              <EditorComponent
                row={data[editIndex]}
                index={editIndex}
                onClose={handleCloseEditor}
              />
            </div>

            <DialogFooter>
              <Button type="button" variant="secondary" onClick={handleCloseEditor}>
                {t("common.close")}
              </Button>
            </DialogFooter>
          </DialogContent>
        </Dialog>
      )}
    </div>
  )
}