/**
 * Pagination Component
 *
 * Reusable pagination component with page navigation, page size selector,
 * and keyboard navigation support.
 *
 * Features:
 * - Previous/Next buttons (disabled at boundaries)
 * - Page numbers with ellipsis for large page counts
 * - Page size selector dropdown
 * - "Showing X-Y of Z results" text
 * - Keyboard navigation (arrow keys)
 * - WCAG AA accessibility
 *
 * @layer UI
 */

import * as React from 'react';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import { Button } from './button';
import { cn } from '@/lib/utils';

export interface PaginationProps {
  currentPage: number;
  pageSize: number;
  totalItems: number;
  onPageChange: (page: number) => void;
  onPageSizeChange: (size: number) => void;
  className?: string;
}

const PAGE_SIZE_OPTIONS = [10, 20, 50, 100];
const MAX_VISIBLE_PAGES = 5;

/**
 * Calculates visible page numbers with ellipsis logic
 *
 * Examples:
 * - 1-5 pages: [1, 2, 3, 4, 5]
 * - Current page 1 of 10: [1, 2, 3, ..., 10]
 * - Current page 5 of 10: [1, ..., 4, 5, 6, ..., 10]
 * - Current page 10 of 10: [1, ..., 8, 9, 10]
 */
function calculateVisiblePages(currentPage: number, totalPages: number): (number | 'ellipsis')[] {
  if (totalPages <= MAX_VISIBLE_PAGES) {
    return Array.from({ length: totalPages }, (_, i) => i + 1);
  }

  const pages: (number | 'ellipsis')[] = [];

  // Always show first page
  pages.push(1);

  // Calculate range around current page
  const rangeStart = Math.max(2, currentPage - 1);
  const rangeEnd = Math.min(totalPages - 1, currentPage + 1);

  // Add ellipsis after first page if needed
  if (rangeStart > 2) {
    pages.push('ellipsis');
  }

  // Add pages in range
  for (let i = rangeStart; i <= rangeEnd; i++) {
    pages.push(i);
  }

  // Add ellipsis before last page if needed
  if (rangeEnd < totalPages - 1) {
    pages.push('ellipsis');
  }

  // Always show last page
  if (totalPages > 1) {
    pages.push(totalPages);
  }

  return pages;
}

export const Pagination = React.forwardRef<HTMLDivElement, PaginationProps>(
  ({ currentPage, pageSize, totalItems, onPageChange, onPageSizeChange, className }, ref) => {
    const totalPages = Math.ceil(totalItems / pageSize);
    const startItem = totalItems === 0 ? 0 : (currentPage - 1) * pageSize + 1;
    const endItem = Math.min(currentPage * pageSize, totalItems);
    const hasPrevious = currentPage > 1;
    const hasNext = currentPage < totalPages;

    // Keyboard navigation
    React.useEffect(() => {
      const handleKeyDown = (event: KeyboardEvent) => {
        if (event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement) {
          return; // Don't handle keyboard events in input fields
        }

        if (event.key === 'ArrowLeft' && hasPrevious) {
          event.preventDefault();
          onPageChange(currentPage - 1);
        } else if (event.key === 'ArrowRight' && hasNext) {
          event.preventDefault();
          onPageChange(currentPage + 1);
        }
      };

      window.addEventListener('keydown', handleKeyDown);
      return () => window.removeEventListener('keydown', handleKeyDown);
    }, [currentPage, hasPrevious, hasNext, onPageChange]);

    const visiblePages = calculateVisiblePages(currentPage, totalPages);

    return (
      <div
        ref={ref}
        className={cn('flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between', className)}
        role="navigation"
        aria-label="Pagination"
      >
        {/* Results text */}
        <div className="text-sm text-muted-foreground" aria-live="polite">
          Showing <span className="font-medium">{startItem}</span> to{' '}
          <span className="font-medium">{endItem}</span> of{' '}
          <span className="font-medium">{totalItems}</span> results
        </div>

        {/* Pagination controls */}
        <div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:gap-6">
          {/* Page size selector */}
          <div className="flex items-center gap-2">
            <label htmlFor="page-size-select" className="text-sm text-muted-foreground whitespace-nowrap">
              Items per page:
            </label>
            <select
              id="page-size-select"
              value={pageSize}
              onChange={(e) => {
                const newPageSize = Number(e.target.value);
                onPageSizeChange(newPageSize);
                // Adjust current page if needed to stay within bounds
                const newTotalPages = Math.ceil(totalItems / newPageSize);
                if (currentPage > newTotalPages) {
                  onPageChange(Math.max(1, newTotalPages));
                }
              }}
              className="h-9 rounded-md border border-input bg-background px-3 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
              aria-label="Select page size"
            >
              {PAGE_SIZE_OPTIONS.map((size) => (
                <option key={size} value={size}>
                  {size}
                </option>
              ))}
            </select>
          </div>

          {/* Page navigation */}
          <div className="flex items-center gap-1">
            {/* Previous button */}
            <Button
              variant="outline"
              size="icon"
              onClick={() => onPageChange(currentPage - 1)}
              disabled={!hasPrevious}
              aria-label="Go to previous page"
              title="Previous page (Left arrow)"
            >
              <ChevronLeft className="h-4 w-4" />
            </Button>

            {/* Page numbers */}
            <div className="flex items-center gap-1" role="list" aria-label="Pagination pages">
              {visiblePages.map((page, index) => {
                if (page === 'ellipsis') {
                  return (
                    <span
                      key={`ellipsis-${index}`}
                      className="flex h-9 w-9 items-center justify-center text-sm text-muted-foreground"
                      aria-hidden="true"
                    >
                      ...
                    </span>
                  );
                }

                const isCurrentPage = page === currentPage;
                return (
                  <Button
                    key={page}
                    variant={isCurrentPage ? 'default' : 'outline'}
                    size="icon"
                    onClick={() => onPageChange(page)}
                    aria-label={`Go to page ${page}`}
                    aria-current={isCurrentPage ? 'page' : undefined}
                    className={cn('h-9 w-9', isCurrentPage && 'pointer-events-none')}
                  >
                    {page}
                  </Button>
                );
              })}
            </div>

            {/* Next button */}
            <Button
              variant="outline"
              size="icon"
              onClick={() => onPageChange(currentPage + 1)}
              disabled={!hasNext}
              aria-label="Go to next page"
              title="Next page (Right arrow)"
            >
              <ChevronRight className="h-4 w-4" />
            </Button>
          </div>
        </div>
      </div>
    );
  }
);

Pagination.displayName = 'Pagination';
