/**
 * DocumentTable - Tabla principal de documentos
 * 
 * Componente refactorizado que utiliza componentes modulares para:
 * - EditableCell: Celdas editables
 * - DetailModal: Modal para edición de valores complejos
 * - FilterComponent: Filtros por columna
 * - ActionsMenu: Acciones por fila
 * - ExportButton: Exportar a Excel
 */

"use client";

import { useState, useMemo, FC, useEffect } from "react";
import Link from "next/link";
import { Documento } from "@/types/document";
import { Prisma } from "@/generated/prisma/client";
import ColumnSelector from "./ColumnSelector";
import DetailsDrawer from "./DetailsDrawer";
import MobileDocumentCard from "./MobileDocumentCard";
import BotonEliminarTodoDev from "./BotonEliminarTodoDev";
import {
  EditableCell,
  DetailModal,
  FilterComponent,
  ActionsMenu,
  ExportButton,
  formatComplexValue,
  isComplexValue,
  isLongText,
  fuzzyFilter,
} from "./table";
import { updateDocument as updateDocumentApi } from "@/lib/api/documents";

import {
  ColumnDef,
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getSortedRowModel,
  getGroupedRowModel,
  useReactTable,
  ColumnFiltersState,
  SortingState,
  FilterFn,
  CellContext,
  RowData,
  GroupingState,
  Column,
  VisibilityState,
} from "@tanstack/react-table";
import { rankItem } from "@tanstack/match-sorter-utils";
import {
  LuSearch,
  LuArrowUpDown,
  LuArrowUp,
  LuArrowDown,
  LuEye,
  LuUser,
  LuFolderOpen,
  LuScanLine,
} from "react-icons/lu";

declare module "@tanstack/react-table" {
  interface TableMeta<TData extends RowData> {
    updateData: (rowIndex: number, columnId: string, value: string) => void;
  }
}

// Tipos de filtros de rango
type RangeFilterValue = [string, string] | null | undefined;

// Filtros personalizados
const dateRangeFilter: FilterFn<Documento> = (row, columnId, filterValue) => {
  const rangeValue = filterValue as RangeFilterValue;
  if (!rangeValue || !rangeValue[0] || !rangeValue[1]) return true;
  const cellValue = row.getValue<string>(columnId);
  if (!cellValue) return false;
  const cellDate = new Date(cellValue);
  const startDate = new Date(rangeValue[0]);
  const endDate = new Date(rangeValue[1]);
  return cellDate >= startDate && cellDate <= endDate;
};

const numberRangeFilter: FilterFn<Documento> = (row, columnId, filterValue) => {
  const rangeValue = filterValue as RangeFilterValue;
  if (!rangeValue || (!rangeValue[0] && !rangeValue[1])) return true;
  const cellValue = parseFloat(row.getValue<string>(columnId));
  if (isNaN(cellValue)) return false;
  const min = rangeValue[0] ? parseFloat(rangeValue[0]) : -Infinity;
  const max = rangeValue[1] ? parseFloat(rangeValue[1]) : Infinity;
  return cellValue >= min && cellValue <= max;
};

// Celda editable por defecto
const defaultColumn: Partial<ColumnDef<Documento>> = { 
  cell: (props) => <EditableCell {...props} /> 
};

interface DocumentTableProps {
  data: Documento[];
  onDelete: (doc: Documento) => void;
  empleados: { id: string; nombre: string }[];
  usuarioActual: { id: string; rol: string };
  categories: { id: string; name: string; icon: string | null; color: string | null }[];
  onUpdateDocument?: (id: string, extractedData: Record<string, unknown>) => Promise<void>;
}

export default function DocumentTable({
  data,
  onDelete,
  empleados,
  usuarioActual,
  categories,
  onUpdateDocument,
}: DocumentTableProps) {
  // Estados de la tabla
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
  const [globalFilter, setGlobalFilter] = useState("");
  const [sorting, setSorting] = useState<SortingState>([]);
  const [grouping, setGrouping] = useState<GroupingState>([]);
  const [filtroUsuario, setFiltroUsuario] = useState<string>("");
  const [filtroCategoria, setFiltroCategoria] = useState<string>("");
  const [selectedDocument, setSelectedDocument] = useState<Documento | null>(null);
  const [isDrawerOpen, setIsDrawerOpen] = useState(false);

  // Detectar campos principales automáticamente
  const mainFieldsDetected = useMemo(() => {
    const sample = data[0];
    if (!sample || !sample.extractedData || typeof sample.extractedData !== "object") {
      return { dateField: null, totalField: null };
    }

    const keys = Object.keys(sample.extractedData as Record<string, unknown>);
    const dateField = keys.find(k =>
      k.toLowerCase().includes("fecha") || k.toLowerCase().includes("date")
    );
    const totalField = keys.find(k =>
      k.toLowerCase().includes("total") || k.toLowerCase().includes("amount")
    );

    return { dateField, totalField };
  }, [data]);

  // Visibilidad inicial de columnas
  const initialVisibility = useMemo(() => {
    const visibility: VisibilityState = {
      empleado: true,
      categoria: true,
      NOMBRE: true,
      actions: true,
    };

    if (mainFieldsDetected.dateField) {
      visibility[mainFieldsDetected.dateField] = true;
    }

    if (mainFieldsDetected.totalField) {
      visibility[mainFieldsDetected.totalField] = true;
    }

    return visibility;
  }, [mainFieldsDetected]);

  // Persistencia de visibilidad en localStorage
  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>(() => {
    if (typeof window === "undefined") return initialVisibility;
    const saved = localStorage.getItem("documentTable_columnVisibility");
    if (saved) {
      try {
        return JSON.parse(saved) as VisibilityState;
      } catch {
        return initialVisibility;
      }
    }
    return initialVisibility;
  });

  useEffect(() => {
    if (typeof window !== "undefined") {
      localStorage.setItem("documentTable_columnVisibility", JSON.stringify(columnVisibility));
    }
  }, [columnVisibility]);

  // Datos filtrados por usuario y categoría
  const datosFiltrados = useMemo(() => {
    let filtered = data;
    if (filtroUsuario) {
      filtered = filtered.filter((doc) => doc.ownerId === filtroUsuario);
    }
    if (filtroCategoria) {
      filtered = filtered.filter((doc) => doc.categoryId === filtroCategoria);
    }
    return filtered;
  }, [data, filtroUsuario, filtroCategoria]);

  // Definición de columnas
  const columns = useMemo<ColumnDef<Documento>[]>(
    () => [
      // Columna de Empleado
      {
        id: "empleado",
        accessorFn: (row) => row.owner?.name || row.owner?.username || "Desconocido",
        header: "EMPLEADO",
        cell: ({ getValue }) => (
          <div className="flex items-center gap-2">
            <span className="text-sm font-medium text-text">
              {getValue() as string}
            </span>
          </div>
        ),
        enableSorting: true,
        enableColumnFilter: true,
      },
      // Columna de Categoría
      {
        id: "categoria",
        accessorFn: (row) => row.category?.name || "Sin categoría",
        header: "CATEGORÍA",
        cell: ({ row }) => {
          const category = row.original.category;
          if (!category) {
            return (
              <span className="inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium bg-background-alt text-text-muted">
                📋 Sin categoría
              </span>
            );
          }
          return (
            <span
              className="inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium"
              style={{
                backgroundColor: `${category.color}20`,
                color: category.color || '#3B82F6',
                border: `1px solid ${category.color || '#3B82F6'}40`
              }}
            >
              <span>{category.icon || '📁'}</span>
              <span>{category.name}</span>
            </span>
          );
        },
        enableSorting: true,
        enableColumnFilter: true,
      },
      // Columna NOMBRE
      {
        id: "NOMBRE",
        accessorFn: (row) => {
          const extractData = row.extractedData as Record<string, unknown>;
          return (extractData as any)?.["NOMBRE"] || (extractData as any)?.["nombre"] || "";
        },
        header: "NOMBRE",
        cell: (props) => <EditableCell {...props} />,
        enableSorting: true,
        enableColumnFilter: true,
      },
      // Columnas dinámicas de extractedData
      ...Array.from(
        data.reduce((acc, doc) => {
          if (
            doc.extractedData &&
            typeof doc.extractedData === "object" &&
            !Array.isArray(doc.extractedData)
          ) {
            Object.keys(doc.extractedData).forEach((key) => {
              if (key.toUpperCase() !== "NOMBRE") {
                acc.add(key);
              }
            });
          }
          return acc;
        }, new Set<string>())
      ).map((key) => {
        const isDate = key.toLowerCase().includes("fecha") || key.toLowerCase().includes("date");
        const isNumeric = data.some(
          (row) =>
            row.extractedData &&
            typeof row.extractedData === "object" &&
            !Array.isArray(row.extractedData) &&
            key in row.extractedData &&
            !isNaN(parseFloat(String((row.extractedData as Record<string, unknown>)[key]))) &&
            isFinite(parseFloat(String((row.extractedData as Record<string, unknown>)[key])))
        );

        return {
          id: key,
          accessorFn: (row) => {
            const value =
              row.extractedData &&
                typeof row.extractedData === "object" &&
                !Array.isArray(row.extractedData)
                ? (row.extractedData as Record<string, unknown>)[key]
                : "";
            return value ?? "";
          },
          header: key.toUpperCase().replace(/_/g, " "),
          filterFn: isDate ? dateRangeFilter : isNumeric ? numberRangeFilter : "fuzzy",
          aggregationFn: isNumeric ? "sum" : undefined,
          aggregatedCell: isNumeric
            ? ({ getValue }) => `Total: ${parseFloat(getValue() as string).toFixed(2)}`
            : undefined,
          enableHiding: true,
        } as ColumnDef<Documento>;
      }),
      // Columna de Acciones
      {
        id: "actions",
        header: "ACCIONES",
        enableSorting: false,
        enableColumnFilter: false,
        enableHiding: false,
        cell: ({ row }) => (
          <button
            onClick={() => {
              setSelectedDocument(row.original);
              setIsDrawerOpen(true);
            }}
            className="flex items-center gap-2 px-3 py-1.5 bg-primary text-primary-foreground rounded-lg hover:bg-primary-hover transition-colors text-sm font-medium"
          >
            <LuEye className="h-4 w-4" />
            Ver Detalles
          </button>
        ),
      },
    ],
    [data]
  );

  // Configurar tabla
  const table = useReactTable({
    data: datosFiltrados,
    columns,
    defaultColumn,
    filterFns: {
      fuzzy: fuzzyFilter,
      dateRange: dateRangeFilter,
      numberRange: numberRangeFilter,
    },
    state: {
      sorting,
      columnFilters,
      globalFilter,
      grouping,
      columnVisibility,
    },
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    onGlobalFilterChange: setGlobalFilter,
    onGroupingChange: setGrouping,
    onColumnVisibilityChange: setColumnVisibility,
    globalFilterFn: fuzzyFilter,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getGroupedRowModel: getGroupedRowModel(),
    enableMultiSort: true,
    meta: {
      updateData: async (rowIndex, columnId, value) => {
        const updatedDoc = datosFiltrados[rowIndex];
        if (!updatedDoc) return;

        if (columnId === "fileName") {
          console.warn("Se necesita una API endpoint para actualizar 'fileName' en la BD.");
          return;
        }

        let parsedValue: unknown = value;
        try {
          if (value.trim().startsWith("{") || value.trim().startsWith("[")) {
            parsedValue = JSON.parse(value);
          }
        } catch (e) {
          console.log(e);
        }

        const newExtractedData = {
          ...(typeof updatedDoc.extractedData === "object" &&
            updatedDoc.extractedData !== null &&
            !Array.isArray(updatedDoc.extractedData)
            ? (updatedDoc.extractedData as Record<string, unknown>)
            : {}),
          [columnId]: parsedValue,
        };

        const flatData: Record<string, string | undefined> = {};
        for (const key in newExtractedData) {
          const val = newExtractedData[key];
          flatData[key] =
            typeof val === "object" && val !== null
              ? JSON.stringify(val)
              : String(val ?? "");
        }

        if (onUpdateDocument) {
          await onUpdateDocument(updatedDoc.id, flatData);
        } else {
          updateDocumentApi(updatedDoc.id, flatData).catch((error) => {
            console.error("Error al actualizar documento:", error);
          });
        }
      },
    },
  });

  return (
    <div className="space-y-6 animate-fade-in">
      {/* Header */}
      <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
        <div>
          <h1 className="text-2xl font-bold text-text">Documentos Digitalizados</h1>
          <p className="text-sm text-text-muted mt-1">
            Gestiona y edita tus documentos digitalizados en tiempo real
          </p>
        </div>
      </div>

      {/* Barra de Herramientas */}
      <div className="space-y-4">
        {/* Buscador */}
        <div className="relative w-full">
          <LuSearch className="absolute left-4 top-1/2 -translate-y-1/2 h-5 w-5 text-text-subtle" />
          <input
            type="text"
            value={globalFilter ?? ""}
            onChange={(e) => setGlobalFilter(e.target.value)}
            placeholder="Busca por nombre, fecha, o cualquier campo..."
            className="w-full pl-11 pr-4 py-3 border border-border-subtle rounded-xl bg-background text-base focus:ring-2 focus:ring-primary focus:border-transparent shadow-sm outline-none transition-all hover:border-primary/50"
          />
        </div>

        {/* Filtros y Acciones */}
        <div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
          <div className="flex items-center gap-3 w-full sm:w-auto overflow-x-auto pb-1 sm:pb-0">
            {/* Filtro Usuarios */}
            {usuarioActual.rol === "ADMIN" && empleados.length > 0 && (
              <div className="relative group">
                <select
                  value={filtroUsuario}
                  onChange={(e) => setFiltroUsuario(e.target.value)}
                  className="appearance-none pl-10 pr-10 py-2.5 border border-border-subtle rounded-lg bg-background text-sm font-medium text-text hover:bg-background-alt focus:ring-2 focus:ring-primary outline-none cursor-pointer min-w-[200px] transition-all"
                >
                  <option value="">Todos los usuarios</option>
                  {empleados.map((empleado) => (
                    <option key={empleado.id} value={empleado.id}>
                      {empleado.nombre}
                    </option>
                  ))}
                </select>
                <LuUser className="absolute left-3.5 top-1/2 -translate-y-1/2 h-4 w-4 text-text-subtle pointer-events-none" />
                <LuArrowDown className="absolute right-3.5 top-1/2 -translate-y-1/2 h-4 w-4 text-text-subtle pointer-events-none" />
              </div>
            )}

            {/* Filtro Categorías */}
            {categories.length > 0 && (
              <div className="relative group">
                <select
                  value={filtroCategoria}
                  onChange={(e) => setFiltroCategoria(e.target.value)}
                  className="appearance-none pl-10 pr-10 py-2.5 border border-border-subtle rounded-lg bg-background text-sm font-medium text-text hover:bg-background-alt focus:ring-2 focus:ring-primary outline-none cursor-pointer min-w-[200px] transition-all"
                >
                  <option value="">Todas las categorías</option>
                  {categories.map((category) => (
                    <option key={category.id} value={category.id}>
                      {category.name}
                    </option>
                  ))}
                </select>
                <LuFolderOpen className="absolute left-3.5 top-1/2 -translate-y-1/2 h-4 w-4 text-text-subtle pointer-events-none" />
                <LuArrowDown className="absolute right-3.5 top-1/2 -translate-y-1/2 h-4 w-4 text-text-subtle pointer-events-none" />
              </div>
            )}
          </div>

          {/* Botones Derecha */}
          <div className="flex items-center gap-3 w-full sm:w-auto">
            <ColumnSelector columns={table.getAllColumns()} />
            <ExportButton
              table={table}
              empleados={empleados}
              filtroUsuario={filtroUsuario}
            />
            {process.env.NODE_ENV === "development" && <BotonEliminarTodoDev />}
          </div>
        </div>
      </div>

      {/* Indicadores de filtro */}
      {filtroUsuario && (
        <div className="bg-primary-subtle/50 border border-primary/30 rounded-xl px-4 py-3 flex items-center justify-between animate-slide-down">
          <div className="flex items-center gap-2 text-sm text-info-foreground">
            <div className="p-1.5 bg-primary/10 rounded-full">
              <LuUser className="h-4 w-4 text-primary" />
            </div>
            <span>
              Mostrando documentos de:{" "}
              <strong className="text-text">{empleados.find((e) => e.id === filtroUsuario)?.nombre}</strong>
            </span>
          </div>
          <button
            onClick={() => setFiltroUsuario("")}
            className="text-primary hover:text-primary-active text-sm font-medium px-3 py-1.5 rounded-lg hover:bg-primary/10 transition-colors"
          >
            Limpiar filtro
          </button>
        </div>
      )}

      {filtroCategoria && (
        <div className="bg-info-background border border-info-border rounded-xl px-4 py-3 flex items-center justify-between animate-slide-down">
          <div className="flex items-center gap-2 text-sm text-info-foreground">
            <div className="p-1.5 bg-info-border/30 rounded-full">
              <LuFolderOpen className="h-4 w-4 text-info" />
            </div>
            <span>
              Mostrando categoría:{" "}
              <strong className="text-text">{categories.find((c) => c.id === filtroCategoria)?.name}</strong>
            </span>
          </div>
          <button
            onClick={() => setFiltroCategoria("")}
            className="text-info hover:text-info-foreground text-sm font-medium px-3 py-1.5 rounded-lg hover:bg-info-border/30 transition-colors"
          >
            Limpiar filtro
          </button>
        </div>
      )}

      {/* Tabla Desktop / Cards Mobile */}
      <div className="bg-background border border-border-subtle rounded-xl shadow-sm overflow-hidden hover-card">
        {/* Desktop Table */}
        <div className="hidden lg:block overflow-x-auto">
          <table className="w-full text-sm text-left">
            <thead className="bg-background-alt border-b border-border-subtle">
              {table.getHeaderGroups().map((headerGroup) => (
                <tr key={headerGroup.id}>
                  {headerGroup.headers.map((header) => (
                    <th
                      key={header.id}
                      className="px-6 py-4 text-xs font-semibold text-text-muted uppercase tracking-wider align-top min-w-[150px]"
                    >
                      <div className="space-y-3">
                        <div
                          onClick={header.column.getToggleSortingHandler()}
                          className={`flex items-center justify-between gap-2 ${
                            header.column.getCanSort() ? "cursor-pointer select-none group" : ""
                          }`}
                        >
                          <span className="group-hover:text-text transition-colors">
                            {flexRender(header.column.columnDef.header, header.getContext())}
                          </span>
                          <span className="text-text-subtle group-hover:text-primary transition-colors">
                            {header.column.getIsSorted() === "asc" ? (
                              <LuArrowUp className="h-3.5 w-3.5 text-primary" />
                            ) : header.column.getIsSorted() === "desc" ? (
                              <LuArrowDown className="h-3.5 w-3.5 text-primary" />
                            ) : header.column.getCanSort() ? (
                              <LuArrowUpDown className="h-3.5 w-3.5 opacity-0 group-hover:opacity-100 transition-opacity" />
                            ) : null}
                          </span>
                        </div>
                        {header.column.getCanFilter() && (
                          <div className="mt-2">
                            <FilterComponent column={header.column} tableData={datosFiltrados} />
                          </div>
                        )}
                      </div>
                    </th>
                  ))}
                </tr>
              ))}
            </thead>
            <tbody className="divide-y divide-border-light">
              {table.getRowModel().rows.map((row) => (
                <tr key={row.id} className="hover:bg-primary-faint/50 transition-colors group">
                  {row.getVisibleCells().map((cell) => (
                    <td key={cell.id} className="px-6 py-4 text-text align-middle">
                      {flexRender(cell.column.columnDef.cell, cell.getContext())}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        {/* Mobile Cards */}
        <div className="lg:hidden p-4 space-y-4 bg-background-subtle">
          {table.getRowModel().rows.map((row) => (
            <MobileDocumentCard
              key={row.id}
              row={row}
              onView={(doc) => {
                setSelectedDocument(doc);
                setIsDrawerOpen(true);
              }}
              onDelete={onDelete}
            />
          ))}
        </div>

        {/* Empty State */}
        {table.getRowModel().rows.length === 0 && (
          <div className="p-12 text-center bg-background animate-fade-in">
            <div className="inline-flex items-center justify-center p-5 bg-primary-faint rounded-full mb-4">
              <LuSearch className="h-10 w-10 text-primary" />
            </div>
            <h3 className="text-lg font-semibold text-text mb-2">
              No se encontraron documentos
            </h3>
            <p className="text-text-muted text-sm max-w-md mx-auto">
              {filtroUsuario || filtroCategoria || globalFilter
                ? "Intenta ajustar los filtros de búsqueda o limpia los filtros aplicados."
                : "Comienza subiendo tu primer documento para digitalizar y extraer información automáticamente."}
            </p>
            {!filtroUsuario && !filtroCategoria && !globalFilter && (
              <a
                href="/upload"
                className="inline-flex items-center gap-2 mt-6 px-5 py-2.5 bg-primary text-primary-foreground rounded-lg hover:bg-primary-hover transition-colors font-medium shadow-sm"
              >
                <LuScanLine className="h-4 w-4" />
                Subir Documento
              </a>
            )}
          </div>
        )}
      </div>

      {/* Estadísticas */}
      <div className="flex items-center justify-between text-sm text-text-muted bg-background border border-border-subtle rounded-xl px-4 py-3">
        <span className="flex items-center gap-2">
          <span className="inline-flex items-center justify-center w-6 h-6 rounded-full bg-primary-faint text-primary font-semibold text-xs">
            {table.getFilteredRowModel().rows.length}
          </span>
          <span>
            documentos mostrados de <strong className="text-text">{data.length}</strong> total(es)
          </span>
        </span>
        {table.getFilteredRowModel().rows.length < data.length && (
          <button
            onClick={() => {
              setGlobalFilter("");
              setFiltroUsuario("");
              setFiltroCategoria("");
              setColumnFilters([]);
            }}
            className="text-primary hover:text-primary-active font-medium px-3 py-1.5 rounded-lg hover:bg-primary-faint transition-colors"
          >
            Ver todos
          </button>
        )}
      </div>

      {/* Details Drawer */}
      <DetailsDrawer
        document={selectedDocument}
        isOpen={isDrawerOpen}
        onClose={() => {
          setIsDrawerOpen(false);
          setSelectedDocument(null);
        }}
        onDelete={(doc) => {
          setIsDrawerOpen(false);
          setSelectedDocument(null);
          onDelete(doc);
        }}
      />
    </div>
  );
}
