"use client";

import { useState, useMemo } from "react";
import {
  ArrowDownUp,
  Download,
  ChevronLeft,
  ChevronRight,
  Eye,
  FileSpreadsheet,
} from "lucide-react";

import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuCheckboxItem,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { JsonViewPopup } from "../json-view-popup";
import { Checkbox } from "ui/checkbox";

// Column configuration interface
interface Column {
  key: string;
  label: string;
  type?: "string" | "number" | "date" | "boolean";
}

// Table component props interface
export interface InteractiveTableProps {
  title: string;
  description?: string;
  columns: Column[];
  data: Array<Record<string, any>>;
}

// Sort direction type
type SortDirection = "asc" | "desc" | null;

// Lazy load XLSX library from CDN
const loadXLSX = async () => {
  if (typeof window === "undefined") {
    throw new Error("XLSX can only be loaded in browser environment");
  }

  // Check if XLSX is already loaded
  if ((window as any).XLSX) {
    return (window as any).XLSX;
  }

  // Load XLSX from CDN
  return new Promise((resolve, reject) => {
    const script = document.createElement("script");
    script.src =
      "https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js";
    script.onload = () => {
      if ((window as any).XLSX) {
        resolve((window as any).XLSX);
      } else {
        reject(new Error("Failed to load XLSX library"));
      }
    };
    script.onerror = () => reject(new Error("Failed to load XLSX script"));
    document.head.appendChild(script);
  });
};

export function InteractiveTable(props: InteractiveTableProps) {
  const { title, data, columns, description } = props;

  // Fixed settings for simplicity
  const pageSize = 20;
  const searchable = true;
  const exportable = true;

  // State management
  const [searchTerm, setSearchTerm] = useState("");
  const [sortColumn, setSortColumn] = useState<string | null>(null);
  const [sortDirection, setSortDirection] = useState<SortDirection>(null);

  const [currentPage, setCurrentPage] = useState(1);
  const [visibleColumns, setVisibleColumns] = useState<Set<string>>(
    new Set(columns.map((col) => col.key)),
  );

  // Helper function to format cell values based on column type
  const formatCellValue = (value: any, columnType: string = "string") => {
    if (value === null || value === undefined) return "";

    switch (columnType) {
      case "number":
        return typeof value === "number" ? value.toLocaleString() : value;
      case "boolean":
        return value ? "Yes" : "No";
      case "date":
        try {
          return new Date(value).toLocaleDateString();
        } catch {
          return value;
        }
      default:
        return String(value);
    }
  };

  // Highlight search terms in text
  const highlightText = (text: string, searchTerm: string) => {
    if (!searchTerm || !text) return text;

    const regex = new RegExp(`(${searchTerm})`, "gi");
    const parts = String(text).split(regex);

    return parts.map((part, index) =>
      regex.test(part) ? (
        <mark key={index} className="bg-yellow-200 dark:bg-yellow-800">
          {part}
        </mark>
      ) : (
        part
      ),
    );
  };

  // Filter and sort data
  const processedData = useMemo(() => {
    let filtered = [...data];

    // Apply global search
    if (searchTerm && searchable) {
      filtered = filtered.filter((row) =>
        Object.values(row).some((value) =>
          String(value).toLowerCase().includes(searchTerm.toLowerCase()),
        ),
      );
    }

    // Apply sorting based on column type
    if (sortColumn && sortDirection) {
      filtered.sort((a, b) => {
        const aValue = a[sortColumn];
        const bValue = b[sortColumn];
        const column = columns.find((col) => col.key === sortColumn);
        const columnType = column?.type || "string";

        let comparison = 0;

        switch (columnType) {
          case "number":
            comparison = Number(aValue || 0) - Number(bValue || 0);
            break;
          case "date":
            comparison =
              new Date(aValue || 0).getTime() - new Date(bValue || 0).getTime();
            break;
          case "boolean":
            comparison = (aValue ? 1 : 0) - (bValue ? 1 : 0);
            break;
          default:
            comparison = String(aValue || "").localeCompare(
              String(bValue || ""),
            );
        }

        return sortDirection === "asc" ? comparison : -comparison;
      });
    }

    return filtered;
  }, [data, searchTerm, sortColumn, sortDirection]);

  // Pagination
  const totalPages =
    pageSize > 0 ? Math.ceil(processedData.length / pageSize) : 1;
  const paginatedData =
    pageSize > 0
      ? processedData.slice(
          (currentPage - 1) * pageSize,
          currentPage * pageSize,
        )
      : processedData;

  // Handle sorting (all columns are sortable by default)
  const handleSort = (columnKey: string) => {
    if (sortColumn === columnKey) {
      setSortDirection(
        sortDirection === "asc"
          ? "desc"
          : sortDirection === "desc"
            ? null
            : "asc",
      );
      if (sortDirection === "desc") {
        setSortColumn(null);
      }
    } else {
      setSortColumn(columnKey);
      setSortDirection("asc");
    }
  };

  // Export to CSV
  const exportToCSV = () => {
    const visibleCols = columns.filter((col) => visibleColumns.has(col.key));
    const csvContent = [
      // Header
      visibleCols
        .map((col) => col.label)
        .join(","),
      // Data rows
      ...processedData.map((row) =>
        visibleCols
          .map((col) => `"${formatCellValue(row[col.key], col.type)}"`)
          .join(","),
      ),
    ].join("\n");

    const blob = new Blob([csvContent], { type: "text/csv" });
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = `${title.replace(/\s+/g, "_")}.csv`;
    link.click();
    URL.revokeObjectURL(url);
  };

  // Export to Excel (lazy load XLSX library)
  const exportToExcel = async () => {
    try {
      // Dynamically load XLSX from CDN
      const XLSX = await loadXLSX();

      const visibleCols = columns.filter((col) => visibleColumns.has(col.key));

      // Prepare data for Excel
      const excelData = [
        // Header row
        visibleCols.map((col) => col.label),
        // Data rows
        ...processedData.map((row) =>
          visibleCols.map((col) => {
            const value = row[col.key];
            // Convert formatted values back to raw values for Excel
            switch (col.type) {
              case "number":
                return typeof value === "number"
                  ? value
                  : Number(value) || value;
              case "date":
                return value instanceof Date ? value : new Date(value);
              case "boolean":
                return typeof value === "boolean" ? value : value;
              default:
                return value;
            }
          }),
        ),
      ];

      // Create workbook and worksheet
      const workbook = XLSX.utils.book_new();
      const worksheet = XLSX.utils.aoa_to_sheet(excelData);

      // Auto-size columns
      const colWidths = visibleCols.map((col) => {
        const maxLength = Math.max(
          col.label.length,
          ...processedData.map(
            (row) =>
              String(formatCellValue(row[col.key], col.type) || "").length,
          ),
        );
        return { wch: Math.min(Math.max(maxLength + 2, 10), 50) };
      });
      worksheet["!cols"] = colWidths;

      // Add worksheet to workbook
      XLSX.utils.book_append_sheet(workbook, worksheet, "Data");

      // Save file
      XLSX.writeFile(workbook, `${title.replace(/\s+/g, "_")}.xlsx`);
    } catch (error) {
      console.error("Failed to export Excel:", error);
      // Fallback to CSV if Excel export fails
      exportToCSV();
    }
  };

  const visibleColumnsArray = columns.filter((col) =>
    visibleColumns.has(col.key),
  );

  return (
    <div className="px-6">
      <Card className="w-full px-0">
        <CardHeader>
          <div className="flex flex-col">
            <CardTitle className="w-full flex items-center gap-2 justify-between">
              Interactive Table - {title}
              <JsonViewPopup data={props} />
            </CardTitle>
            {description && (
              <CardDescription className="mt-2 ">{description}</CardDescription>
            )}
          </div>

          {/* Search and Export */}
          <div className="flex items-center gap-2 mt-4">
            {searchable && (
              <div className="flex-1">
                <Input
                  placeholder="Search across all columns..."
                  value={searchTerm}
                  onChange={(e) => {
                    setSearchTerm(e.target.value);
                    setCurrentPage(1);
                  }}
                  className="hover:bg-input bg-secondary/40 transition-colors border-transparent border-none! focus-visible:bg-input! ring-0!"
                />
              </div>
            )}
            <DropdownMenu>
              <DropdownMenuTrigger asChild>
                <Button variant="ghost" className="data-[state=open]:bg-accent">
                  <Eye className="size-3.5" />
                  Columns
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent>
                {columns.map((column) => (
                  <DropdownMenuCheckboxItem
                    key={column.key}
                    checked={visibleColumns.has(column.key)}
                    onClick={(e) => {
                      e.stopPropagation();
                      e.preventDefault();
                      const newVisible = new Set(visibleColumns);
                      const checked = !newVisible.has(column.key);
                      if (checked) {
                        newVisible.add(column.key);
                      } else {
                        newVisible.delete(column.key);
                      }
                      setVisibleColumns(newVisible);
                    }}
                  >
                    {column.label}
                  </DropdownMenuCheckboxItem>
                ))}
              </DropdownMenuContent>
            </DropdownMenu>

            {exportable && (
              <DropdownMenu>
                <DropdownMenuTrigger asChild>
                  <Button
                    variant="ghost"
                    className="data-[state=open]:bg-accent"
                  >
                    <Download className="size-3.5" />
                    Export
                  </Button>
                </DropdownMenuTrigger>
                <DropdownMenuContent>
                  <DropdownMenuItem onClick={exportToCSV}>
                    <Download className="h-4 w-4 mr-2" />
                    CSV
                  </DropdownMenuItem>
                  <DropdownMenuItem onClick={exportToExcel}>
                    <FileSpreadsheet className="h-4 w-4 mr-2" />
                    Excel
                  </DropdownMenuItem>
                </DropdownMenuContent>
              </DropdownMenu>
            )}
          </div>
        </CardHeader>

        <CardContent className="px-0 relative">
          <Table>
            <TableHeader className="bg-secondary border-t">
              <TableRow>
                {visibleColumnsArray.map((column, index) => {
                  return (
                    <TableHead
                      key={column.key}
                      className={`relative select-none ${index === 0 ? "pl-6" : index === visibleColumnsArray.length - 1 ? "pr-6" : ""} ${
                        column.type === "number" ||
                        column.type === "date" ||
                        column.type === "boolean"
                          ? "text-center"
                          : ""
                      }`}
                    >
                      {/* Column header with sorting */}
                      <div
                        className={`flex items-center gap-2 cursor-pointer ${
                          column.type === "number" || column.type === "date"
                            ? "justify-center"
                            : ""
                        }`}
                        onClick={() => handleSort(column.key)}
                      >
                        <span className="hover:text-primary">
                          {column.label}
                        </span>

                        <ArrowDownUp
                          className={`h-3 w-3 ${
                            sortColumn === column.key
                              ? ""
                              : "text-muted-foreground/30"
                          }`}
                        />
                      </div>
                    </TableHead>
                  );
                })}
              </TableRow>
            </TableHeader>

            <TableBody className="min-h-[24rem]">
              {paginatedData.length === 0 ? (
                <TableRow>
                  <TableCell
                    colSpan={visibleColumnsArray.length}
                    className="text-center h-48"
                  >
                    No data found
                  </TableCell>
                </TableRow>
              ) : (
                paginatedData.map((row, index) => {
                  return (
                    <TableRow key={index} className={`border-b!`}>
                      {visibleColumnsArray.map((column, index) => (
                        <TableCell
                          key={column.key}
                          className={`py-3 ${index === 0 ? "pl-6" : index === visibleColumnsArray.length - 1 ? "pr-6" : ""} ${
                            column.type === "number" || column.type === "date"
                              ? "text-center"
                              : column.type == "boolean"
                                ? "flex items-center justify-center"
                                : ""
                          }`}
                        >
                          {column.type == "boolean" ? (
                            <>
                              <Checkbox checked={row[column.key]} />
                            </>
                          ) : searchTerm && searchable ? (
                            highlightText(
                              formatCellValue(row[column.key], column.type),
                              searchTerm,
                            )
                          ) : (
                            formatCellValue(row[column.key], column.type)
                          )}
                        </TableCell>
                      ))}
                    </TableRow>
                  );
                })
              )}
            </TableBody>
          </Table>

          {/* Pagination */}
          <div className="flex items-center justify-between pt-4 px-6">
            <div className="text-xs text-muted-foreground">
              Total rows: {data.length}
            </div>
            {pageSize > 0 && totalPages > 1 && (
              <div className="flex items-center gap-2">
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() =>
                    setCurrentPage((prev) => Math.max(1, prev - 1))
                  }
                  disabled={currentPage === 1}
                >
                  <ChevronLeft className="h-4 w-4" />
                  Previous
                </Button>

                <span className="text-sm px-2">
                  Page {currentPage} of {totalPages}
                </span>

                <Button
                  variant="ghost"
                  size="sm"
                  onClick={() =>
                    setCurrentPage((prev) => Math.min(totalPages, prev + 1))
                  }
                  disabled={currentPage === totalPages}
                >
                  Next
                  <ChevronRight className="h-4 w-4" />
                </Button>
              </div>
            )}
          </div>
        </CardContent>
      </Card>
    </div>
  );
}
