"use client";
// src/components/datatable/DataTable.tsx
import React, { useState, useMemo } from "react";
import {
  ColumnDef,
  flexRender,
  getCoreRowModel,
  getSortedRowModel,
  SortingState,
  useReactTable,
  VisibilityState,
  RowSelectionState,
} from "@tanstack/react-table";
import { cn } from "@/lib/utils";
import { useLanguage } from "@/i18n/LanguageContext";
import {
  ChevronUp,
  ChevronDown,
  ChevronsUpDown,
  ChevronLeft,
  ChevronRight,
  ChevronsLeft,
  ChevronsRight,
  Search,
  SlidersHorizontal,
  Eye,
  Trash2,
  Loader2,
  AlertCircle,
} from "lucide-react";

export interface DataTableProps<T> {
  data: T[];
  columns: ColumnDef<T, any>[];
  isLoading?: boolean;
  error?: string | null;
  // Server-side pagination
  pageCount?: number;
  page?: number;
  pageSize?: number;
  total?: number;
  onPageChange?: (page: number) => void;
  onPageSizeChange?: (size: number) => void;
  // Search & filters
  searchValue?: string;
  onSearchChange?: (value: string) => void;
  searchPlaceholder?: string;
  // Sorting
  sortBy?: string;
  sortOrder?: "asc" | "desc";
  onSortChange?: (sortBy: string, sortOrder: "asc" | "desc") => void;
  // Bulk actions
  onBulkDelete?: (ids: string[]) => void;
  getRowId?: (row: T) => string;
  // Toolbar extra content
  toolbarExtra?: React.ReactNode;
  /** e.g. raise z-index when a row dropdown is open so it paints above the next row */
  getRowClassName?: (row: T) => string | undefined;
  // Empty state
  emptyTitle?: string;
  emptyDescription?: string;
  emptyAction?: React.ReactNode;
}

const PAGE_SIZE_OPTIONS = [10, 20, 50, 100];

export function DataTable<T>({
  data,
  columns,
  isLoading = false,
  error = null,
  pageCount = 1,
  page = 1,
  pageSize = 10,
  total = 0,
  onPageChange,
  onPageSizeChange,
  searchValue = "",
  onSearchChange,
  searchPlaceholder,
  sortBy,
  sortOrder,
  onSortChange,
  onBulkDelete,
  getRowId,
  toolbarExtra,
  getRowClassName,
  emptyTitle,
  emptyDescription,
  emptyAction,
}: DataTableProps<T>) {
  const { t, isRTL } = useLanguage();
  const resolvedSearchPlaceholder = searchPlaceholder ?? t("common.search");
  const resolvedEmptyTitle = emptyTitle ?? t("common.noResults");
  const resolvedEmptyDescription = emptyDescription ?? t("table.emptySearchHint");
  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
  const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
  const [showColumnToggle, setShowColumnToggle] = useState(false);

  const selectedIds = useMemo(() => {
    if (!getRowId) return [];
    return Object.keys(rowSelection)
      .filter((k) => rowSelection[k])
      .map((idx) => {
        const row = data[parseInt(idx)];
        return row ? getRowId(row) : "";
      })
      .filter(Boolean);
  }, [rowSelection, data, getRowId]);

  // Add selection column if bulk actions enabled
  const allColumns = useMemo<ColumnDef<T, any>[]>(() => {
    if (!onBulkDelete) return columns;
    const selectionCol: ColumnDef<T, any> = {
      id: "select",
      header: ({ table }) => (
        <input
          type="checkbox"
          className="rounded border-border w-4 h-4 cursor-pointer accent-primary"
          checked={table.getIsAllPageRowsSelected()}
          onChange={table.getToggleAllPageRowsSelectedHandler()}
        />
      ),
      cell: ({ row }) => (
        <input
          type="checkbox"
          className="rounded border-border w-4 h-4 cursor-pointer accent-primary"
          checked={row.getIsSelected()}
          onChange={row.getToggleSelectedHandler()}
          onClick={(e) => e.stopPropagation()}
        />
      ),
      enableSorting: false,
      size: 40,
    };
    return [selectionCol, ...columns];
  }, [columns, onBulkDelete]);

  const table = useReactTable({
    data,
    columns: allColumns,
    state: { columnVisibility, rowSelection },
    onColumnVisibilityChange: setColumnVisibility,
    onRowSelectionChange: setRowSelection,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    manualPagination: true,
    manualSorting: true,
    pageCount,
    enableRowSelection: !!onBulkDelete,
  });

  const handleSort = (columnId: string) => {
    if (!onSortChange) return;
    if (sortBy === columnId) {
      onSortChange(columnId, sortOrder === "asc" ? "desc" : "asc");
    } else {
      // First click on a column: newest-first (desc) — matches typical CRM list defaults
      onSortChange(columnId, "desc");
    }
  };

  const getSortIcon = (columnId: string) => {
    if (sortBy !== columnId) return <ChevronsUpDown className="w-3.5 h-3.5 text-muted-foreground/50" />;
    if (sortOrder === "asc") return <ChevronUp className="w-3.5 h-3.5 text-primary" />;
    return <ChevronDown className="w-3.5 h-3.5 text-primary" />;
  };

  const from = total === 0 ? 0 : (page - 1) * pageSize + 1;
  const to = Math.min(page * pageSize, total);

  return (
    <div className="space-y-4">
      {/* Toolbar */}
      <div className="flex flex-col sm:flex-row gap-3 items-start sm:items-center justify-between">
        <div className="flex items-center gap-3 flex-1 min-w-0">
          {/* Search */}
          {onSearchChange && (
            <div className="relative flex-1 max-w-sm">
              <Search className={cn(
                "absolute top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground pointer-events-none",
                isRTL ? "right-3" : "left-3"
              )} />
              <input
                value={searchValue}
                onChange={(e) => onSearchChange(e.target.value)}
                placeholder={resolvedSearchPlaceholder}
                className={cn(
                  "w-full h-9 rounded-lg border border-input bg-background text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring transition-all",
                  isRTL ? "pr-9 pl-4" : "pl-9 pr-4"
                )}
              />
            </div>
          )}

          {/* Bulk delete */}
          {selectedIds.length > 0 && onBulkDelete && (
            <button
              onClick={() => {
                onBulkDelete(selectedIds);
                setRowSelection({});
              }}
              className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-destructive/10 text-destructive text-sm font-medium hover:bg-destructive/20 transition-colors"
            >
              <Trash2 className="w-4 h-4" />
              {t("table.bulkDelete", { count: selectedIds.length })}
            </button>
          )}
        </div>

        <div className="flex items-center gap-2">
          {toolbarExtra}

          {/* Column visibility toggle */}
          <div className="relative">
            <button
              onClick={() => setShowColumnToggle(!showColumnToggle)}
              className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg border border-border text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-accent transition-colors"
            >
              <Eye className="w-4 h-4" />
              <span className="hidden sm:inline">{t("common.columns")}</span>
            </button>
            {showColumnToggle && (
              <div className={cn(
                "absolute top-full mt-1 bg-popover border border-border rounded-lg shadow-lg p-2 z-20 min-w-[160px] animate-fade-in",
                isRTL ? "left-0" : "right-0"
              )}>
                {table.getAllLeafColumns()
                  .filter((col) => col.id !== "select")
                  .map((col) => (
                    <label
                      key={col.id}
                      className="flex items-center gap-2 px-2 py-1.5 rounded hover:bg-accent cursor-pointer text-sm"
                    >
                      <input
                        type="checkbox"
                        checked={col.getIsVisible()}
                        onChange={col.getToggleVisibilityHandler()}
                        className="rounded accent-primary"
                      />
                      <span className="capitalize text-foreground">
                        {typeof col.columnDef.header === "string"
                          ? col.columnDef.header
                          : col.id}
                      </span>
                    </label>
                  ))}
              </div>
            )}
          </div>
        </div>
      </div>

      {/* Table — avoid overflow-hidden so row action dropdowns are not clipped */}
      <div className="rounded-xl border border-border bg-card shadow-sm">
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              {table.getHeaderGroups().map((headerGroup) => (
                <tr key={headerGroup.id} className="border-b border-border bg-muted/30">
                  {headerGroup.headers.map((header) => {
                    const canSort = header.column.columnDef.enableSorting !== false && !!onSortChange;
                    return (
                      <th
                        key={header.id}
                        className={cn(
                          "px-4 py-3 text-start text-xs font-semibold text-muted-foreground uppercase tracking-wider whitespace-nowrap",
                          canSort && "cursor-pointer hover:text-foreground select-none"
                        )}
                        style={{ width: header.column.columnDef.size }}
                        onClick={() => canSort && handleSort(header.column.id)}
                      >
                        <div className="flex items-center gap-1.5 justify-start">
                          {header.isPlaceholder
                            ? null
                            : flexRender(header.column.columnDef.header, header.getContext())}
                          {canSort && getSortIcon(header.column.id)}
                        </div>
                      </th>
                    );
                  })}
                </tr>
              ))}
            </thead>
            <tbody className="divide-y divide-border">
              {isLoading ? (
                // Skeleton rows
                Array.from({ length: pageSize > 5 ? 5 : pageSize }).map((_, i) => (
                  <tr key={i} className="animate-pulse">
                    {allColumns.map((_, j) => (
                      <td key={j} className="px-4 py-3">
                        <div className="h-4 bg-muted rounded w-full max-w-[120px]" />
                      </td>
                    ))}
                  </tr>
                ))
              ) : error ? (
                <tr>
                  <td colSpan={allColumns.length} className="px-4 py-12 text-center">
                    <div className="flex flex-col items-center gap-2 text-destructive">
                      <AlertCircle className="w-8 h-8" />
                      <p className="font-medium">{error}</p>
                    </div>
                  </td>
                </tr>
              ) : table.getRowModel().rows.length === 0 ? (
                <tr>
                  <td colSpan={allColumns.length} className="px-4 py-16 text-center">
                    <div className="flex flex-col items-center gap-3 text-muted-foreground">
                      <div className="w-12 h-12 rounded-full bg-muted flex items-center justify-center">
                        <SlidersHorizontal className="w-6 h-6" />
                      </div>
                      <div>
                        <p className="font-semibold text-foreground">{resolvedEmptyTitle}</p>
                        <p className="text-sm mt-1">{resolvedEmptyDescription}</p>
                      </div>
                      {emptyAction && <div className="mt-2">{emptyAction}</div>}
                    </div>
                  </td>
                </tr>
              ) : (
                table.getRowModel().rows.map((row) => (
                  <tr
                    key={row.id}
                    className={cn(
                      "hover:bg-muted/40 transition-colors",
                      row.getIsSelected() && "bg-primary/5",
                      getRowClassName?.(row.original)
                    )}
                  >
                    {row.getVisibleCells().map((cell) => (
                      <td
                        key={cell.id}
                        className="px-4 py-3 text-sm text-foreground text-start"
                      >
                        {flexRender(cell.column.columnDef.cell, cell.getContext())}
                      </td>
                    ))}
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </div>
      </div>

      {/* Pagination */}
      <div className={cn(
        "flex flex-col sm:flex-row items-center gap-4 justify-between text-sm text-muted-foreground",
        isRTL && "sm:flex-row-reverse"
      )}>
        <div className="flex items-center gap-4">
          <span>
            {total > 0
              ? t("table.paginationRange", { from, to, total })
              : t("table.noResultsShort")}
          </span>
          <div className="flex items-center gap-2">
            <span className="hidden sm:inline">{t("table.rowsLabel")}</span>
            <select
              value={pageSize}
              onChange={(e) => onPageSizeChange?.(Number(e.target.value))}
              className="h-8 rounded-lg border border-input bg-background text-sm px-2 focus:outline-none focus:ring-2 focus:ring-ring"
            >
              {PAGE_SIZE_OPTIONS.map((size) => (
                <option key={size} value={size}>{size}</option>
              ))}
            </select>
          </div>
        </div>

        <div className="flex items-center gap-1">
          <PaginationButton
            onClick={() => onPageChange?.(1)}
            disabled={page <= 1 || isLoading}
            title={t("table.firstPageAria")}
          >
            <ChevronsLeft className="w-4 h-4" />
          </PaginationButton>
          <PaginationButton
            onClick={() => onPageChange?.(page - 1)}
            disabled={page <= 1 || isLoading}
            title={t("table.prevPageAria")}
          >
            <ChevronLeft className="w-4 h-4" />
          </PaginationButton>

          {/* Page numbers */}
          {getPageNumbers(page, pageCount).map((p, i) =>
            p === "..." ? (
              <span key={`ellipsis-${i}`} className="px-2 text-muted-foreground">…</span>
            ) : (
              <button
                key={p}
                onClick={() => onPageChange?.(p as number)}
                disabled={isLoading}
                className={cn(
                  "w-8 h-8 rounded-lg text-sm font-medium transition-colors",
                  p === page
                    ? "bg-primary text-primary-foreground"
                    : "hover:bg-accent text-foreground"
                )}
              >
                {p}
              </button>
            )
          )}

          <PaginationButton
            onClick={() => onPageChange?.(page + 1)}
            disabled={page >= pageCount || isLoading}
            title={t("table.nextPageAria")}
          >
            <ChevronRight className="w-4 h-4" />
          </PaginationButton>
          <PaginationButton
            onClick={() => onPageChange?.(pageCount)}
            disabled={page >= pageCount || isLoading}
            title={t("table.lastPageAria")}
          >
            <ChevronsRight className="w-4 h-4" />
          </PaginationButton>
        </div>
      </div>
    </div>
  );
}

function PaginationButton({
  children,
  onClick,
  disabled,
  title,
}: {
  children: React.ReactNode;
  onClick: () => void;
  disabled?: boolean;
  title?: string;
}) {
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      title={title}
      className="w-8 h-8 rounded-lg flex items-center justify-center hover:bg-accent text-foreground disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
    >
      {children}
    </button>
  );
}

function getPageNumbers(current: number, total: number): (number | string)[] {
  if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1);
  const pages: (number | string)[] = [];
  if (current <= 4) {
    pages.push(1, 2, 3, 4, 5, "...", total);
  } else if (current >= total - 3) {
    pages.push(1, "...", total - 4, total - 3, total - 2, total - 1, total);
  } else {
    pages.push(1, "...", current - 1, current, current + 1, "...", total);
  }
  return pages;
}
