import { useMemo } from 'react';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import { cn } from '@/lib/cn';

/**
 * Generic client-side pagination control.
 *
 * Renders:  «  1 … 4 [5] 6 … 20  »   showing 41–50 of 200   [25 / page ▾]
 *
 * Caller owns the data — this component is purely a controlled UI for
 * picking a page number + page size. Compute the visible slice as:
 *   items.slice((page - 1) * perPage, page * perPage)
 *
 * Hidden when there's only one page AND no per-page selector requested.
 */
export interface PaginationProps {
  totalItems: number;
  page: number;
  perPage: number;
  onPageChange: (page: number) => void;
  onPerPageChange?: (perPage: number) => void;
  /** Choices for the per-page select. Defaults to [10, 25, 50]. */
  perPageOptions?: number[];
  /** Label used in "showing X–Y of N {label}". Defaults to "items". */
  itemLabel?: string;
  className?: string;
}

export function Pagination({
  totalItems,
  page,
  perPage,
  onPageChange,
  onPerPageChange,
  perPageOptions = [10, 25, 50],
  itemLabel = 'items',
  className,
}: PaginationProps) {
  const totalPages = Math.max(1, Math.ceil(totalItems / perPage));
  const safePage   = Math.min(Math.max(1, page), totalPages);
  const start      = totalItems === 0 ? 0 : (safePage - 1) * perPage + 1;
  const end        = Math.min(safePage * perPage, totalItems);

  // Compute the sparse page list:  [1, '…', 4, 5, 6, '…', 20]
  // Always show first, last, current, and ±1 around current.
  const pages = useMemo<(number | 'ellipsis')[]>(() => {
    if (totalPages <= 7) {
      return Array.from({ length: totalPages }, (_, i) => i + 1);
    }
    const set = new Set<number>([1, totalPages, safePage, safePage - 1, safePage + 1]);
    const sorted = [...set].filter((n) => n >= 1 && n <= totalPages).sort((a, b) => a - b);

    const out: (number | 'ellipsis')[] = [];
    for (let i = 0; i < sorted.length; i++) {
      out.push(sorted[i]);
      if (i < sorted.length - 1 && sorted[i + 1] - sorted[i] > 1) out.push('ellipsis');
    }
    return out;
  }, [totalPages, safePage]);

  // Nothing to paginate, no per-page selector → render nothing.
  if (totalPages <= 1 && !onPerPageChange) return null;

  return (
    <div className={cn(
      'flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3',
      className,
    )}>
      <p className="text-xs text-ink-500">
        {totalItems === 0 ? (
          <>No {itemLabel}</>
        ) : (
          <>
            Showing <span className="font-medium text-ink-800">{start}</span>
            –<span className="font-medium text-ink-800">{end}</span>
            {' '}of <span className="font-medium text-ink-800">{totalItems}</span> {itemLabel}
          </>
        )}
      </p>

      <div className="flex items-center gap-2">
        {totalPages > 1 && (
          <div className="flex items-center gap-0.5">
            <NavBtn
              onClick={() => onPageChange(safePage - 1)}
              disabled={safePage <= 1}
              label="Previous page"
            >
              <ChevronLeft className="h-4 w-4" />
            </NavBtn>

            {pages.map((p, i) =>
              p === 'ellipsis' ? (
                <span key={`e${i}`} className="px-1.5 text-ink-400 text-xs select-none">…</span>
              ) : (
                <button
                  key={p}
                  onClick={() => onPageChange(p)}
                  aria-current={p === safePage ? 'page' : undefined}
                  className={cn(
                    'h-8 min-w-8 px-2 text-xs font-medium rounded-md transition-colors',
                    p === safePage
                      ? 'bg-ink-900 text-white'
                      : 'text-ink-700 hover:bg-ink-100',
                  )}
                >
                  {p}
                </button>
              ),
            )}

            <NavBtn
              onClick={() => onPageChange(safePage + 1)}
              disabled={safePage >= totalPages}
              label="Next page"
            >
              <ChevronRight className="h-4 w-4" />
            </NavBtn>
          </div>
        )}

        {onPerPageChange && (
          <select
            value={perPage}
            onChange={(e) => onPerPageChange(Number(e.target.value))}
            className="h-8 px-2 text-xs rounded-md border border-ink-200 bg-white text-ink-700 focus:outline-none focus:ring-2 focus:ring-brand-400 focus:border-brand-500"
            title="Items per page"
          >
            {perPageOptions.map((n) => (
              <option key={n} value={n}>{n} / page</option>
            ))}
          </select>
        )}
      </div>
    </div>
  );
}

function NavBtn({
  children, onClick, disabled, label,
}: { children: React.ReactNode; onClick: () => void; disabled?: boolean; label: string }) {
  return (
    <button
      type="button"
      onClick={onClick}
      disabled={disabled}
      title={label}
      aria-label={label}
      className="h-8 w-8 grid place-items-center rounded-md text-ink-600 hover:bg-ink-100 disabled:opacity-40 disabled:hover:bg-transparent disabled:cursor-not-allowed"
    >
      {children}
    </button>
  );
}
