import { ChevronLeft, ChevronRight } from "lucide-react";
import { Button } from "@/shared/common/ui/button";
import { cn } from "@/shared/lib/utils";
import { useMemo } from "react";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/shared/common/ui/select";
import { Table } from "@tanstack/react-table";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
interface DataTablePaginationProps<TData = any> {
  table?: Table<TData>;
  pageIndex?: number;
  pageSize?: number;
  itemCount?: number;
  onPageChange?: (page: number) => void;
  onPageSizeChange?: (size: number) => void;
  pageCount?: number;
  nextFunction?: () => void;
  prevFunction?: () => void;
  /** Maximum number of numeric page buttons rendered before truncating with ellipsis. */
  siblingCount?: number;
}

const ELLIPSIS = "…" as const;

type PageItem = number | typeof ELLIPSIS;

function buildPageItems(
  currentPage: number,
  totalPages: number,
  siblingCount: number,
): PageItem[] {
  const totalNumbers = siblingCount * 2 + 5;

  if (totalPages <= totalNumbers) {
    return Array.from({ length: totalPages }, (_, i) => i + 1);
  }

  const leftSibling = Math.max(currentPage - siblingCount, 2);
  const rightSibling = Math.min(currentPage + siblingCount, totalPages - 1);
  const showLeftEllipsis = leftSibling > 2;
  const showRightEllipsis = rightSibling < totalPages - 1;

  const items: PageItem[] = [1];
  if (showLeftEllipsis) items.push(ELLIPSIS);
  for (let i = leftSibling; i <= rightSibling; i++) items.push(i);
  if (showRightEllipsis) items.push(ELLIPSIS);
  items.push(totalPages);
  return items;
}

export function DataTablePaginationFinal<TData>({
  table,
  pageIndex: pageIndexProp,
  pageSize: pageSizeProp,
  itemCount: itemCountProp,
  onPageChange,
  onPageSizeChange,
  nextFunction,
  prevFunction,
  pageCount: pageCountProp,
  siblingCount = 1,
}: DataTablePaginationProps<TData>) {
  // Derive page size
  const pageSize = table
    ? (table.getState().pagination?.pageSize ?? 10)
    : (pageSizeProp ?? 10);

  // Derive page index (0-based)
  const pageIndex = table
    ? (table.getState().pagination?.pageIndex ?? 0)
    : (pageIndexProp ?? 0);

  // Derive total pages
  const totalPages = table
    ? table.getPageCount()
    : (pageCountProp ?? Math.max(1, Math.ceil((itemCountProp ?? 0) / pageSize)));



  const currentPage = pageIndex + 1;

  const canGoNext = table ? table.getCanNextPage() : pageIndex < totalPages - 1;
  const canGoPrev = table ? table.getCanPreviousPage() : pageIndex > 0;

  const pageItems = useMemo(
    () => buildPageItems(currentPage, totalPages, siblingCount),
    [currentPage, totalPages, siblingCount],
  );

  // Safely determine if the table is completely empty
  const isEmpty = table
    ? table.getCoreRowModel().rows.length === 0 && (!itemCountProp || itemCountProp === 0)
    : (itemCountProp !== undefined && itemCountProp === 0);

  if (isEmpty) return null;

  // Hide pagination if there is at most 1 page and no way to change page size
  const hasPageSizeSelector = !!table || !!onPageSizeChange;
  if (totalPages <= 1 && !hasPageSizeSelector) return null;

  const handleNext = () => {
    if (canGoNext) {
      if (table) {
        table.nextPage();
      } else {
        onPageChange?.(pageIndex + 1);
      }
      nextFunction?.();
    }
  };

  const handlePrev = () => {
    if (canGoPrev) {
      if (table) {
        table.previousPage();
      } else {
        onPageChange?.(pageIndex - 1);
      }
      prevFunction?.();
    }
  };

  const goToPage = (page: number) => {
    const clamped = Math.min(Math.max(page, 1), totalPages);
    if (clamped - 1 === pageIndex) return;
    if (table) {
      table.setPageIndex(clamped - 1);
    } else {
      onPageChange?.(clamped - 1);
    }
  };

  const handlePageSizeChange = (size: number) => {
    if (table) {
      table.setPageSize(size);
    } else {
      onPageSizeChange?.(size);
    }
  };

  const rangeStart = pageIndex * pageSize + 1;
  const rangeEnd = Math.min(rangeStart + pageSize - 1, itemCountProp ?? 0);

  return (
    <nav
      role="navigation"
      aria-label="Pagination"
      className="flex flex-col gap-3 px-2 py-3 text-sm sm:flex-row sm:items-center sm:justify-between"
    >
      {hasPageSizeSelector ? (
        <div className="flex items-center space-x-2">
          <p className="text-xs sm:text-sm font-medium whitespace-nowrap">
            Rows per page
          </p>
          <Select
            value={`${pageSize}`}
            onValueChange={(value) => {
              handlePageSizeChange(Number(value));
            }}
          >
            <SelectTrigger className="h-9 sm:h-8 w-[70px] min-w-[70px] text-sm">
              <SelectValue placeholder={pageSize} />
            </SelectTrigger>
            <SelectContent side="top">
              {[10, 20, 30, 40, 50].map((size) => (
                <SelectItem key={size} value={`${size}`}>
                  {size}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
      ) : (
        <p className="text-xs sm:text-sm text-muted-foreground dark:text-gray-400">
          Showing{" "}
          <span className="font-medium text-gray-700 dark:text-gray-200">
            {rangeStart}
          </span>
          {"–"}
          <span className="font-medium text-gray-700 dark:text-gray-200">
            {rangeEnd}
          </span>{" "}
          of{" "}
          <span className="font-medium text-gray-700 dark:text-gray-200">
            {itemCountProp}
          </span>
        </p>
      )}

      <div className="flex flex-wrap items-center justify-end gap-1">
        <Button
          variant="outline"
          size="sm"
          onClick={handlePrev}
          disabled={!canGoPrev}
          aria-label="Previous page"
          className="h-8 gap-1 px-3 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
        >
          <ChevronLeft className="h-4 w-4" />
          <span className="hidden sm:inline">Previous</span>
        </Button>

        <ul className="flex items-center gap-1">
          {pageItems.map((item, idx) => {
            if (item === ELLIPSIS) {
              return (
                <li
                  key={`ellipsis-${idx}`}
                  aria-hidden="true"
                  className="flex h-8 w-8 items-center justify-center text-gray-400 dark:text-gray-500"
                >
                  {ELLIPSIS}
                </li>
              );
            }
            const isActive = item === currentPage;
            return (
              <li key={item}>
                <Button
                  type="button"
                  variant={isActive ? "default" : "ghost"}
                  size="sm"
                  onClick={() => goToPage(item)}
                  aria-current={isActive ? "page" : undefined}
                  aria-label={`Go to page ${item}`}
                  className={cn(
                    "h-8 min-w-8 px-2 text-sm transition-colors",
                    isActive
                      ? "bg-primary text-primary-foreground font-bold hover:bg-primary/90 dark:bg-primary dark:text-primary-foreground"
                      : "font-medium text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700",
                  )}
                >
                  {item}
                </Button>
              </li>
            );
          })}
        </ul>

        <Button
          variant="outline"
          size="sm"
          onClick={handleNext}
          disabled={!canGoNext}
          aria-label="Next page"
          className="h-8 gap-1 px-3 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
        >
          <span className="hidden sm:inline">Next</span>
          <ChevronRight className="h-4 w-4" />
        </Button>
      </div>
    </nav>
  );
}