import { useId, useMemo } from "react";
import { PaginationNavButton, PaginationPageButton } from "./button";
import { IconChevronDown, IconChevronLeft, IconChevronRight } from "./icons";

type DataPaginationProps = {
  page: number;
  totalItems: number;
  pageSize: number;
  onPageChange: (page: number) => void;
  pageSizeOptions?: readonly number[];
  defaultPageSize?: number;
  onPageSizeChange?: (pageSize: number) => void;
};

type PaginationItem = number | "ellipsis";

function getPaginationItems(
  currentPage: number,
  totalPages: number,
): PaginationItem[] {
  if (totalPages <= 7) {
    return Array.from({ length: totalPages }, (_, index) => index + 1);
  }

  if (currentPage <= 3) {
    return [1, 2, 3, 4, 5, "ellipsis", totalPages];
  }

  if (currentPage >= totalPages - 2) {
    return [
      1,
      "ellipsis",
      totalPages - 4,
      totalPages - 3,
      totalPages - 2,
      totalPages - 1,
      totalPages,
    ];
  }

  return [
    1,
    "ellipsis",
    currentPage - 1,
    currentPage,
    currentPage + 1,
    "ellipsis",
    totalPages,
  ];
}

export function DataPagination({
  page,
  totalItems,
  pageSize,
  onPageChange,
  pageSizeOptions,
  defaultPageSize,
  onPageSizeChange,
}: DataPaginationProps) {
  const pageSizeSelectId = useId();
  const showPageSizeSelect =
    pageSizeOptions !== undefined && onPageSizeChange !== undefined;
  const totalPages = Math.max(1, Math.ceil(totalItems / pageSize));
  const currentPage = Math.min(page, totalPages);
  const start = totalItems === 0 ? 0 : (currentPage - 1) * pageSize + 1;
  const end = Math.min(currentPage * pageSize, totalItems);

  const paginationItems = useMemo(
    () => getPaginationItems(currentPage, totalPages),
    [currentPage, totalPages],
  );

  return (
    <div className="flex flex-col gap-4 border-t border-neutral-40 pt-4 lg:flex-row lg:items-center lg:justify-between">
      <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:gap-6">
        {showPageSizeSelect && (
          <div className="flex items-center gap-2">
            <label
              htmlFor={pageSizeSelectId}
              className="text-m-regular whitespace-nowrap text-neutral-80"
            >
              Baris per halaman
            </label>
            <div className="relative">
              <select
                id={pageSizeSelectId}
                value={pageSize}
                onChange={(event) =>
                  onPageSizeChange(Number(event.target.value))
                }
                className="text-m-regular h-9 w-fit appearance-none rounded-lg border border-neutral-40 bg-neutral-10 py-2 pr-7 pl-2.5 text-neutral-100 outline-none focus:border-primary-500"
              >
                {pageSizeOptions.map((size) => (
                  <option key={size} value={size}>
                    {size === defaultPageSize ? `${size}` : size}
                  </option>
                ))}
              </select>
              <IconChevronDown className="pointer-events-none absolute top-1/2 right-2.5 size-4 -translate-y-1/2 text-neutral-80" />
            </div>
          </div>
        )}

        <p className="text-m-regular text-neutral-80">
          Menampilkan{" "}
          <span className="text-m-medium tabular-nums text-neutral-100">
            {start}–{end}
          </span>{" "}
          dari{" "}
          <span className="text-m-medium tabular-nums text-neutral-100">
            {totalItems}
          </span>{" "}
          data
        </p>
      </div>

      <nav
        className="flex items-center justify-center gap-2 lg:justify-end"
        aria-label="Paginasi"
      >
        <PaginationNavButton
          icon={<IconChevronLeft />}
          onClick={() => onPageChange(currentPage - 1)}
          disabled={currentPage <= 1}
          aria-label="Halaman sebelumnya"
          className="px-2"
        >
          <span className="sr-only">Sebelumnya</span>
        </PaginationNavButton>

        <div className="flex items-center gap-1">
          {paginationItems.map((item, index) =>
            item === "ellipsis" ? (
              <span
                key={`ellipsis-${index}`}
                aria-hidden="true"
                className="text-s-regular px-1 text-neutral-70"
              >
                …
              </span>
            ) : (
              <PaginationPageButton
                key={item}
                active={item === currentPage}
                onClick={() => onPageChange(item)}
                aria-label={`Halaman ${item}`}
                aria-current={item === currentPage ? "page" : undefined}
              >
                {item}
              </PaginationPageButton>
            ),
          )}
        </div>

        <PaginationNavButton
          icon={<IconChevronRight />}
          iconPosition="end"
          onClick={() => onPageChange(currentPage + 1)}
          disabled={currentPage >= totalPages}
          aria-label="Halaman selanjutnya"
          className="px-2"
        >
          <span className="sr-only">Selanjutnya</span>
        </PaginationNavButton>
      </nav>
    </div>
  );
}
