"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> & {
  totalItems?: number;  // para paginación server-side
  readOnly?: boolean;

  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?: (originalRow: TData, index: number, parent?: Row<TData>) => string;

  // Soporte para paginación server-side
  manualPagination?: boolean;
  pageIndex?: number; // 0-based
  totalItems?: number;
  onPageChange?: (pageIndex: number) => void;
  onPageSizeChange?: (pageSize: number) => void;

  // Acción al hacer click en una fila
  onRowClick?: (row: TData, index: number, event: React.MouseEvent<HTMLTableRowElement>) => void;
}

export function DataTable<TData, TValue>({
  columns,
  data,
  meta,

  readOnly = false,
  enablePagination = true,
  pageSize = 10,
  enableRowSelection = false,
  EditorComponent,

  getRowId,

  manualPagination,
  pageIndex = 0,
  totalItems,
  onPageChange,
  onPageSizeChange,

  onRowClick,
}: 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);

  // Configuración TanStack
  const table = useReactTable({
    data,
    columns,
    columnResizeMode: "onChange",
    onColumnSizingChange: setColSizes,
    meta: { ...meta, totalItems, readOnly },

    getRowId:
      getRowId ??
      ((originalRow: TData, i: number) =>
        typeof (originalRow as any).id !== "undefined"
          ? String((originalRow as any).id)
          : String(i)),

    state: {
      columnSizing: colSizes,
      sorting,
      columnVisibility,
      rowSelection,
      columnFilters,
      pagination: { pageIndex, pageSize },
    },

    manualPagination,
    pageCount: manualPagination
      ? Math.ceil((totalItems ?? data.length) / (pageSize ?? 25))
      : undefined,

    // Propagar cambios al padre
    onPaginationChange: (updater) => {
      const next = typeof updater === "function"
        ? updater({ pageIndex, pageSize })
        : updater;

      if (typeof next.pageIndex === "number") onPageChange?.(next.pageIndex);
      if (typeof next.pageSize === "number") onPageSizeChange?.(next.pageSize);
    },

    enableRowSelection,
    onRowSelectionChange: setRowSelection,
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    onColumnVisibilityChange: setColumnVisibility,

    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: manualPagination ? undefined : getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFacetedRowModel: getFacetedRowModel(),
    getFacetedUniqueValues: getFacetedUniqueValues(),
  })

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

  // Render principal
  return (
    <div
      className="transition-[max-height] duration-300 ease-in-out"
    >
      <div className="flex flex-col gap-0">
        <DataTableToolbar table={table} showViewOptions={!readOnly} />

        <div className="overflow-hidden rounded-md border">
          <TableComp className="w-full text-sm">
            {/* CABECERA */}
            <TableHeader className="sticky top-0 z-10 bg-muted">
              {table.getHeaderGroups().map((hg) => (
                <TableRow key={hg.id}>
                  {hg.headers.map((h) => {
                    const w = h.getSize();
                    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,
                        }}
                      >
                        <div className={"text-xs text-muted-foreground text-nowrap cursor-default"}>
                          {h.isPlaceholder
                            ? null
                            : flexRender(h.column.columnDef.header, h.getContext())}
                        </div>
                      </TableHead>
                    );
                  })}
                </TableRow>
              ))}
            </TableHeader>

            {/* CUERPO */}
            <TableBody>
              {table.getRowModel().rows.length ? (
                table.getRowModel().rows.map((row, rowIndex) => (
                  <TableRow
                    key={row.id}
                    role="button"
                    tabIndex={0}
                    data-state={row.getIsSelected() && "selected"}
                    className={`group bg-background ${readOnly ? "cursor-default" : "cursor-pointer"}`}
                    onKeyDown={(e) => {
                      if (e.key === "Enter" || e.key === " ") onRowClick?.(row.original, rowIndex, e as any);
                    }}
                    onClick={(e) => onRowClick?.(row.original, rowIndex, e)}
                    onDoubleClick={
                      !readOnly && !onRowClick ? () => setEditIndex(rowIndex) : undefined
                    }                >
                    {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>
            {/* Paginación */}
            {enablePagination && (
              <TableFooter>
                <TableRow>
                  <TableCell colSpan={100}>
                    <DataTablePagination table={table} onPageChange={onPageChange} onPageSizeChange={onPageSizeChange} />
                  </TableCell>
                </TableRow>
              </TableFooter>)
            }

          </TableComp>
        </div>

        {/* Editor modal */}
        {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>
    </div>
  )
}