import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { TrackListPagination } from './TrackListPagination';

describe('TrackListPagination', () => {
  const mockOnPageChange = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should render pagination', () => {
    render(
      <TrackListPagination
        currentPage={1}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );
    expect(
      screen.getByRole('navigation', {
        name: 'Pagination de la liste de pistes',
      }),
    ).toBeInTheDocument();
  });

  it('should display current page information', () => {
    render(
      <TrackListPagination
        currentPage={2}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );
    expect(screen.getByText(/Affichage de/)).toBeInTheDocument();
    expect(screen.getByText(/11/)).toBeInTheDocument();
    expect(screen.getByText(/20/)).toBeInTheDocument();
    expect(screen.getByText(/50/)).toBeInTheDocument();
  });

  it('should display page numbers', () => {
    render(
      <TrackListPagination
        currentPage={1}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
        showPageNumbers={true}
      />,
    );
    expect(screen.getByLabelText('Aller à la page 1')).toBeInTheDocument();
    expect(screen.getByLabelText('Aller à la page 2')).toBeInTheDocument();
  });

  it('should highlight current page', () => {
    render(
      <TrackListPagination
        currentPage={3}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );
    const currentPageButton = screen.getByLabelText('Aller à la page 3');
    expect(currentPageButton).toHaveAttribute('aria-current', 'page');
    expect(currentPageButton).toHaveClass('bg-blue-600');
  });

  it('should call onPageChange when page number is clicked', async () => {
    const user = userEvent.setup();
    render(
      <TrackListPagination
        currentPage={1}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    const page2Button = screen.getByLabelText('Aller à la page 2');
    await user.click(page2Button);

    expect(mockOnPageChange).toHaveBeenCalledWith(2);
  });

  it('should call onPageChange when next button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <TrackListPagination
        currentPage={1}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    const nextButton = screen.getByLabelText('Page suivante');
    await user.click(nextButton);

    expect(mockOnPageChange).toHaveBeenCalledWith(2);
  });

  it('should call onPageChange when previous button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <TrackListPagination
        currentPage={2}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    const previousButton = screen.getByLabelText('Page précédente');
    await user.click(previousButton);

    expect(mockOnPageChange).toHaveBeenCalledWith(1);
  });

  it('should call onPageChange when first page button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <TrackListPagination
        currentPage={3}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    const firstButton = screen.getByLabelText('Aller à la première page');
    await user.click(firstButton);

    expect(mockOnPageChange).toHaveBeenCalledWith(1);
  });

  it('should call onPageChange when last page button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <TrackListPagination
        currentPage={1}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    const lastButton = screen.getByLabelText('Aller à la dernière page');
    await user.click(lastButton);

    expect(mockOnPageChange).toHaveBeenCalledWith(5);
  });

  it('should disable previous button on first page', () => {
    render(
      <TrackListPagination
        currentPage={1}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    const previousButton = screen.getByLabelText('Page précédente');
    const firstButton = screen.getByLabelText('Aller à la première page');

    expect(previousButton).toBeDisabled();
    expect(firstButton).toBeDisabled();
  });

  it('should disable next button on last page', () => {
    render(
      <TrackListPagination
        currentPage={5}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    const nextButton = screen.getByLabelText('Page suivante');
    const lastButton = screen.getByLabelText('Aller à la dernière page');

    expect(nextButton).toBeDisabled();
    expect(lastButton).toBeDisabled();
  });

  it('should show ellipsis when there are many pages', () => {
    render(
      <TrackListPagination
        currentPage={5}
        totalPages={10}
        totalItems={100}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
        maxVisiblePages={5}
      />,
    );

    const ellipsis = screen.queryAllByText('...');
    expect(ellipsis.length).toBeGreaterThan(0);
  });

  it('should limit visible page numbers based on maxVisiblePages', () => {
    render(
      <TrackListPagination
        currentPage={5}
        totalPages={20}
        totalItems={200}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
        maxVisiblePages={5}
      />,
    );

    // Should show around 5 pages centered on current page
    const pageButtons = screen.getAllByLabelText(/Aller à la page \d+/);
    expect(pageButtons.length).toBeLessThanOrEqual(7); // 5 visible + first + last potentially
  });

  it('should hide page numbers when showPageNumbers is false', () => {
    render(
      <TrackListPagination
        currentPage={1}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
        showPageNumbers={false}
      />,
    );

    const pageButtons = screen.queryAllByLabelText(/Aller à la page \d+/);
    expect(pageButtons.length).toBe(0);
  });

  it('should hide items info when showItemsInfo is false', () => {
    render(
      <TrackListPagination
        currentPage={1}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
        showItemsInfo={false}
      />,
    );

    expect(screen.queryByText(/Affichage de/)).not.toBeInTheDocument();
  });

  it('should return null when totalPages is 1 and showItemsInfo is false', () => {
    const { container } = render(
      <TrackListPagination
        currentPage={1}
        totalPages={1}
        totalItems={10}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
        showItemsInfo={false}
      />,
    );

    expect(container.firstChild).toBeNull();
  });

  it('should disable all buttons when disabled prop is true', () => {
    render(
      <TrackListPagination
        currentPage={3}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
        disabled={true}
      />,
    );

    const nextButton = screen.getByLabelText('Page suivante');
    const previousButton = screen.getByLabelText('Page précédente');
    const pageButton = screen.getByLabelText('Aller à la page 2');

    expect(nextButton).toBeDisabled();
    expect(previousButton).toBeDisabled();
    expect(pageButton).toBeDisabled();
  });

  it('should not call onPageChange when clicking disabled buttons', async () => {
    const user = userEvent.setup();
    render(
      <TrackListPagination
        currentPage={1}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    const previousButton = screen.getByLabelText('Page précédente');
    await user.click(previousButton);

    expect(mockOnPageChange).not.toHaveBeenCalled();
  });

  it('should not call onPageChange when clicking current page', async () => {
    const user = userEvent.setup();
    render(
      <TrackListPagination
        currentPage={2}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    const currentPageButton = screen.getByLabelText('Aller à la page 2');
    await user.click(currentPageButton);

    expect(mockOnPageChange).not.toHaveBeenCalled();
  });

  it('should apply custom className', () => {
    const { container } = render(
      <TrackListPagination
        currentPage={1}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
        className="custom-class"
      />,
    );

    const nav = container.querySelector('[role="navigation"]');
    expect(nav).toHaveClass('custom-class');
  });

  it('should calculate correct item range', () => {
    render(
      <TrackListPagination
        currentPage={3}
        totalPages={5}
        totalItems={47}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    // Page 3: items 21-30, but total is 47, so 21-30
    expect(screen.getByText(/21/)).toBeInTheDocument();
    expect(screen.getByText(/30/)).toBeInTheDocument();
  });

  it('should handle edge case with last page having fewer items', () => {
    render(
      <TrackListPagination
        currentPage={5}
        totalPages={5}
        totalItems={47}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    // Last page: items 41-47
    expect(screen.getByText(/41/)).toBeInTheDocument();
    // Check for "47" in the range display (not just anywhere)
    const infoText = screen.getByText(/Affichage de/);
    expect(infoText.textContent).toContain('47');
  });

  it('should have accessible attributes', () => {
    render(
      <TrackListPagination
        currentPage={2}
        totalPages={5}
        totalItems={50}
        itemsPerPage={10}
        onPageChange={mockOnPageChange}
      />,
    );

    const nav = screen.getByRole('navigation');
    expect(nav).toHaveAttribute(
      'aria-label',
      'Pagination de la liste de pistes',
    );

    const currentPageButton = screen.getByLabelText('Aller à la page 2');
    expect(currentPageButton).toHaveAttribute('aria-current', 'page');
  });
});
