"use client";

import { useState } from "react";
import { ArrowUpDown, ArrowUp, ArrowDown } from "lucide-react";
import type { LucideIcon } from "lucide-react";
import Skeleton from "./Skeleton";
import EmptyState from "./EmptyState";
import Pagination from "./Pagination";
import styles from "./DataTable.module.css";

export interface Column<T> {
  key: string;
  label: string;
  sortable?: boolean;
  align?: "left" | "center" | "right";
  render?: (row: T, index: number) => React.ReactNode;
}

type SortDir = "asc" | "desc" | null;

interface DataTableProps<T> {
  columns: Column<T>[];
  data: T[];
  isLoading?: boolean;
  skeletonRows?: number;
  pageSize?: number;
  searchable?: boolean;
  emptyTitle?: string;
  emptyDescription?: string;
  emptyIcon?: LucideIcon;
  emptyAction?: React.ReactNode;
  keyExtractor: (row: T, index: number) => string | number;
  onRowClick?: (row: T) => void;
}

export default function DataTable<T extends object>({
  columns,
  data,
  isLoading = false,
  skeletonRows = 6,
  emptyTitle,
  emptyDescription,
  emptyIcon,
  emptyAction,
  keyExtractor,
  onRowClick,
  pageSize,
  searchable = false,
}: DataTableProps<T>) {
  const [sortKey, setSortKey] = useState<string | null>(null);
  const [sortDir, setSortDir] = useState<SortDir>(null);
  const [page, setPage] = useState(1);
  const [searchQuery, setSearchQuery] = useState("");

  const handleSort = (key: string) => {
    setPage(1);
    if (sortKey !== key) {
      setSortKey(key);
      setSortDir("asc");
    } else if (sortDir === "asc") {
      setSortDir("desc");
    } else {
      setSortKey(null);
      setSortDir(null);
    }
  };

  const filtered = data.filter((row) => {
    if (!searchQuery) return true;
    const q = searchQuery.toLowerCase();
    return Object.values(row).some((val) => String(val ?? "").toLowerCase().includes(q));
  });

  const sorted = [...filtered].sort((a, b) => {
    if (!sortKey || !sortDir) return 0;
    const va = (a as Record<string, unknown>)[sortKey];
    const vb = (b as Record<string, unknown>)[sortKey];
    if (va === vb) return 0;
    const dir = sortDir === "asc" ? 1 : -1;
    return va! > vb! ? dir : -dir;
  });

  const isPaginated = pageSize !== undefined;
  const finalData = isPaginated ? sorted.slice((page - 1) * pageSize, page * pageSize) : sorted;
  const totalPages = isPaginated ? Math.ceil(sorted.length / pageSize) : 1;

  const SortIcon = ({ col }: { col: Column<T> }) => {
    if (!col.sortable) return null;
    if (sortKey !== col.key) return <ArrowUpDown className={styles.sortIcon} />;
    return sortDir === "asc" ? (
      <ArrowUp className={`${styles.sortIcon} ${styles.active}`} />
    ) : (
      <ArrowDown className={`${styles.sortIcon} ${styles.active}`} />
    );
  };

  return (
    <div className={styles.wrapper}>
      {searchable && (
        <div className={styles.searchBar}>
          <input
            type="text"
            placeholder="Rechercher..."
            value={searchQuery}
            onChange={(e) => {
              setSearchQuery(e.target.value);
              setPage(1);
            }}
            className={styles.searchInput}
          />
        </div>
      )}
      <div className={styles.scroll}>
        <table className={styles.table}>
          <thead className={styles.thead}>
            <tr>
              {columns.map((col) => (
                <th
                  key={col.key}
                  className={`${styles.th} ${col.sortable ? styles.sortable : ""}`}
                  onClick={col.sortable ? () => handleSort(col.key) : undefined}
                >
                  <span
                    className={`${styles.thInner} ${
                      col.align === "right" ? styles.alignRight : col.align === "center" ? styles.alignCenter : ""
                    }`}
                  >
                    {col.label}
                    <SortIcon col={col} />
                  </span>
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {isLoading &&
              Array.from({ length: skeletonRows }).map((_, i) => (
                <tr key={i}>
                  {columns.map((col) => (
                    <td key={col.key} className={styles.td}>
                      <Skeleton height={16} width={col.align === "right" ? "60%" : "80%"} />
                    </td>
                  ))}
                </tr>
              ))}

            {!isLoading &&
              finalData.map((row, rowIndex) => (
                <tr
                  key={keyExtractor(row, rowIndex)}
                  className={onRowClick ? styles.clickableRow : ""}
                  onClick={onRowClick ? () => onRowClick(row) : undefined}
                >
                  {columns.map((col) => (
                    <td
                      key={col.key}
                      data-label={col.label}
                      className={`${styles.td} ${
                        col.align === "right" ? styles.alignRight : col.align === "center" ? styles.alignCenter : ""
                      }`}
                    >
                      {col.render ? col.render(row, rowIndex) : String((row as Record<string, unknown>)[col.key] ?? "—")}
                    </td>
                  ))}
                </tr>
              ))}
          </tbody>
        </table>
      </div>

      {!isLoading && data.length === 0 && (
        <EmptyState title={emptyTitle} description={emptyDescription} icon={emptyIcon} action={emptyAction} />
      )}

      {isPaginated && totalPages > 1 && (
        <Pagination currentPage={page} totalPages={totalPages} onPageChange={setPage} />
      )}
    </div>
  );
}
