"use client";

import { useState, useMemo } from "react";
import { Search, ChevronLeft, ChevronRight, FileSpreadsheet, FileText, Download } from "lucide-react";

type Column<T> = {
  key: string;
  label: string;
  render?: (row: T) => React.ReactNode;
  exportValue?: (row: T) => string;
  sortable?: boolean;
};

type DataTableProps<T> = {
  data: T[];
  columns: Column<T>[];
  pageSize?: number;
  title?: string;
  exportFilename?: string;
  searchPlaceholder?: string;
  searchKeys?: string[];
  actions?: (row: T) => React.ReactNode;
  defaultSearch?: string;
};

export default function DataTable<T extends Record<string, any>>({
  data, columns, pageSize = 10, title, exportFilename = "datos",
  searchPlaceholder = "Buscar...", searchKeys, actions, defaultSearch = ""
}: DataTableProps<T>) {
  const [page, setPage] = useState(0);
  const [search, setSearch] = useState(defaultSearch);
  const [sortKey, setSortKey] = useState<string | null>(null);
  const [sortDir, setSortDir] = useState<"asc" | "desc">("asc");

  // Filter
  const filtered = useMemo(() => {
    if (!search.trim()) return data;
    const q = search.toLowerCase();
    return data.filter(row => {
      const keys = searchKeys || columns.map(c => c.key);
      return keys.some(k => {
        const val = row[k];
        if (val == null) return false;
        return String(val).toLowerCase().includes(q);
      });
    });
  }, [data, search, searchKeys, columns]);

  // Sort
  const sorted = useMemo(() => {
    if (!sortKey) return filtered;
    return [...filtered].sort((a, b) => {
      const va = a[sortKey] ?? "";
      const vb = b[sortKey] ?? "";
      if (va < vb) return sortDir === "asc" ? -1 : 1;
      if (va > vb) return sortDir === "asc" ? 1 : -1;
      return 0;
    });
  }, [filtered, sortKey, sortDir]);

  const totalPages = Math.ceil(sorted.length / pageSize) || 1;
  const paged = sorted.slice(page * pageSize, (page + 1) * pageSize);

  const handleSort = (key: string) => {
    if (sortKey === key) setSortDir(d => d === "asc" ? "desc" : "asc");
    else { setSortKey(key); setSortDir("asc"); }
  };

  // Export Excel
  const exportExcel = async () => {
    const XLSX = await import("xlsx");
    const rows = sorted.map(row =>
      Object.fromEntries(columns.map(col => [
        col.label,
        col.exportValue ? col.exportValue(row) : String(row[col.key] ?? "")
      ]))
    );
    const ws = XLSX.utils.json_to_sheet(rows);
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "Datos");
    XLSX.writeFile(wb, `${exportFilename}.xlsx`);
  };

  // Export PDF
  const exportPDF = async () => {
    const jsPDF = (await import("jspdf")).default;
    const autoTable = (await import("jspdf-autotable")).default;
    const doc = new jsPDF("l", "mm", "a4");
    doc.setFontSize(16);
    doc.text(title || exportFilename, 14, 15);
    doc.setFontSize(10);
    doc.text(`Generado: ${new Date().toLocaleString("es-VE")}`, 14, 22);

    const head = [columns.map(c => c.label)];
    const body = sorted.map(row =>
      columns.map(col => col.exportValue ? col.exportValue(row) : String(row[col.key] ?? ""))
    );

    autoTable(doc, {
      head, body, startY: 28,
      styles: { fontSize: 8, cellPadding: 2 },
      headStyles: { fillColor: [30, 42, 71], textColor: 255, fontStyle: "bold" },
      alternateRowStyles: { fillColor: [245, 247, 250] },
    });
    doc.save(`${exportFilename}.pdf`);
  };

  return (
    <div className="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
      {/* Toolbar */}
      <div className="flex flex-wrap items-center justify-between gap-3 px-5 py-4 border-b border-gray-100">
        <div className="flex items-center gap-3">
          {title && <h3 className="font-bold text-gray-700 text-sm">{title}</h3>}
          <div className="relative">
            <Search className="w-4 h-4 text-gray-400 absolute left-3 top-1/2 -translate-y-1/2" />
            <input
              type="text" value={search} onChange={e => { setSearch(e.target.value); setPage(0); }}
              placeholder={searchPlaceholder}
              className="pl-9 pr-4 py-2 text-sm border border-gray-200 rounded-lg focus:ring-2 focus:ring-[#0066ff] outline-none w-56"
            />
          </div>
        </div>
        <div className="flex items-center gap-2">
          <button onClick={exportExcel}
            className="flex items-center gap-1.5 px-3 py-2 text-xs font-semibold text-green-700 bg-green-50 hover:bg-green-100 rounded-lg transition-colors">
            <FileSpreadsheet className="w-3.5 h-3.5" /> Excel
          </button>
          <button onClick={exportPDF}
            className="flex items-center gap-1.5 px-3 py-2 text-xs font-semibold text-red-700 bg-red-50 hover:bg-red-100 rounded-lg transition-colors">
            <FileText className="w-3.5 h-3.5" /> PDF
          </button>
        </div>
      </div>

      {/* Table */}
      <div className="overflow-x-auto">
        <table className="w-full text-sm text-left min-w-[600px]">
          <thead className="bg-gray-50/80 text-gray-500 text-xs uppercase font-bold tracking-wider">
            <tr>
              {columns.map(col => (
                <th key={col.key} className="px-5 py-3.5">
                  {col.sortable !== false ? (
                    <button onClick={() => handleSort(col.key)}
                      className="flex items-center gap-1 hover:text-gray-800 transition-colors">
                      {col.label}
                      {sortKey === col.key && (
                        <span className="text-[10px]">{sortDir === "asc" ? "▲" : "▼"}</span>
                      )}
                    </button>
                  ) : col.label}
                </th>
              ))}
              {actions && <th className="px-5 py-3.5 text-right">Acciones</th>}
            </tr>
          </thead>
          <tbody className="divide-y divide-gray-50">
            {paged.map((row, idx) => (
              <tr key={(row as any).id || idx} className="hover:bg-gray-50/50 transition-colors">
                {columns.map(col => (
                  <td key={col.key} className="px-5 py-4">
                    {col.render ? col.render(row) : String(row[col.key] ?? "")}
                  </td>
                ))}
                {actions && <td className="px-5 py-4 text-right">{actions(row)}</td>}
              </tr>
            ))}
            {paged.length === 0 && (
              <tr>
                <td colSpan={columns.length + (actions ? 1 : 0)}
                  className="px-5 py-12 text-center text-gray-400">
                  {search ? "Sin resultados para esta búsqueda." : "No hay datos."}
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>

      {/* Pagination */}
      <div className="flex items-center justify-between px-5 py-3 border-t border-gray-100 text-xs text-gray-500">
        <span>
          Mostrando {paged.length > 0 ? page * pageSize + 1 : 0}–{Math.min((page + 1) * pageSize, sorted.length)} de {sorted.length}
        </span>
        <div className="flex items-center gap-1">
          <button onClick={() => setPage(p => Math.max(0, p - 1))} disabled={page === 0}
            className="p-2 rounded hover:bg-gray-100 disabled:opacity-30 transition-colors">
            <ChevronLeft className="w-4 h-4" />
          </button>
          {Array.from({ length: Math.min(totalPages, 5) }, (_, i) => {
            let pageNum: number;
            if (totalPages <= 5) pageNum = i;
            else if (page < 3) pageNum = i;
            else if (page > totalPages - 4) pageNum = totalPages - 5 + i;
            else pageNum = page - 2 + i;
            return (
              <button key={pageNum} onClick={() => setPage(pageNum)}
                className={`w-8 h-8 rounded font-semibold transition-colors ${
                  page === pageNum ? "bg-[#1e2a47] text-white" : "hover:bg-gray-100"
                }`}>
                {pageNum + 1}
              </button>
            );
          })}
          <button onClick={() => setPage(p => Math.min(totalPages - 1, p + 1))} disabled={page >= totalPages - 1}
            className="p-2 rounded hover:bg-gray-100 disabled:opacity-30 transition-colors">
            <ChevronRight className="w-4 h-4" />
          </button>
        </div>
      </div>
    </div>
  );
}
