import { ChevronLeft, ChevronRight } from "lucide-react";
import { Button } from "@/shared/common/ui/button";
import { cn } from "@/shared/lib/utils";
import { useMemo } from "react";

interface DataTablePaginationProps {
  pageIndex: number; // current page index (0-based)
  pageSize?: number; // items per page
  itemCount: number; // total number of items
  onPageChange: (page: number) => void;
  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[] {
  // Always show first, last, current, and `siblingCount` pages around current.
  // Insert ellipsis where there are gaps.
  const totalNumbers = siblingCount * 2 + 5; // first + last + current + 2*siblings + 2 ellipses

  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 DataTablePagination({
  pageIndex,
  pageSize = 10,
  itemCount,
  onPageChange,
  nextFunction,
  prevFunction,
  siblingCount = 1,
}: DataTablePaginationProps) {
  const totalPages = Math.max(1, Math.ceil(itemCount / pageSize));
  const currentPage = pageIndex + 1; // 1-based for display

  const canGoNext = pageIndex < totalPages - 1;
  const canGoPrev = pageIndex > 0;

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

  // Edge case: hide entirely when there's nothing to paginate.
  if (totalPages <= 1 || itemCount === 0) return null;

  const handleNext = () => {
    if (canGoNext) {
      onPageChange(pageIndex + 1);
      nextFunction();
    }
  };

  const handlePrev = () => {
    if (canGoPrev) {
      onPageChange(pageIndex - 1);
      prevFunction();
    }
  };

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

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

  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"
    >
      <p className="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">
          {itemCount}
        </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-100 text-primary-800 font-bold hover:bg-primary-200 dark:bg-primary-900 dark:text-primary-300 dark:hover:bg-primary-800"
                      : "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>
  );
}
