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

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

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

  it('renders pagination with page numbers', () => {
    render(
      <Pagination
        currentPage={1}
        totalPages={5}
        onPageChange={mockOnPageChange}
      />,
    );

    expect(screen.getByText('1')).toBeInTheDocument();
    expect(screen.getByText('2')).toBeInTheDocument();
    expect(screen.getByText('3')).toBeInTheDocument();
    expect(screen.getByText('4')).toBeInTheDocument();
    expect(screen.getByText('5')).toBeInTheDocument();
  });

  it('renders previous and next buttons', () => {
    render(
      <Pagination
        currentPage={2}
        totalPages={5}
        onPageChange={mockOnPageChange}
      />,
    );

    const previousButton = screen.getByLabelText('Previous page');
    const nextButton = screen.getByLabelText('Next page');

    expect(previousButton).toBeInTheDocument();
    expect(nextButton).toBeInTheDocument();
  });

  it('disables previous button on first page', () => {
    render(
      <Pagination
        currentPage={1}
        totalPages={5}
        onPageChange={mockOnPageChange}
      />,
    );

    const previousButton = screen.getByLabelText('Previous page');
    expect(previousButton).toBeDisabled();
  });

  it('disables next button on last page', () => {
    render(
      <Pagination
        currentPage={5}
        totalPages={5}
        onPageChange={mockOnPageChange}
      />,
    );

    const nextButton = screen.getByLabelText('Next page');
    expect(nextButton).toBeDisabled();
  });

  it('calls onPageChange when page number is clicked', async () => {
    const user = userEvent.setup();
    render(
      <Pagination
        currentPage={1}
        totalPages={5}
        onPageChange={mockOnPageChange}
      />,
    );

    const page3 = screen.getByText('3');
    await user.click(page3);

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

  it('calls onPageChange when previous button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <Pagination
        currentPage={3}
        totalPages={5}
        onPageChange={mockOnPageChange}
      />,
    );

    const previousButton = screen.getByLabelText('Previous page');
    await user.click(previousButton);

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

  it('calls onPageChange when next button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <Pagination
        currentPage={3}
        totalPages={5}
        onPageChange={mockOnPageChange}
      />,
    );

    const nextButton = screen.getByLabelText('Next page');
    await user.click(nextButton);

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

  it('highlights current page', () => {
    render(
      <Pagination
        currentPage={3}
        totalPages={5}
        onPageChange={mockOnPageChange}
      />,
    );

    const currentPageButton = screen.getByText('3');
    expect(currentPageButton).toHaveClass('bg-primary');
    expect(currentPageButton).toHaveAttribute('aria-current', 'page');
  });

  it('shows ellipsis for large page counts', () => {
    const { container } = render(
      <Pagination
        currentPage={10}
        totalPages={20}
        onPageChange={mockOnPageChange}
        maxVisiblePages={5}
      />,
    );

    // Devrait afficher des ellipsis (MoreHorizontal icons)
    const ellipsisIcons = container.querySelectorAll('svg');
    Array.from(ellipsisIcons).some((icon) => {
      const parent = icon.closest('div');
      return (
        parent &&
        parent.classList.contains('flex') &&
        parent.classList.contains('items-center')
      );
    });

    // Vérifier que la première et dernière page sont affichées (indiquant ellipsis)
    expect(screen.getByText('1')).toBeInTheDocument();
    expect(screen.getByText('20')).toBeInTheDocument();
  });

  it('shows first and last page when showFirstLast is true', () => {
    render(
      <Pagination
        currentPage={10}
        totalPages={20}
        onPageChange={mockOnPageChange}
        showFirstLast={true}
      />,
    );

    const firstButton = screen.getByLabelText('First page');
    const lastButton = screen.getByLabelText('Last page');

    expect(firstButton).toBeInTheDocument();
    expect(lastButton).toBeInTheDocument();
  });

  it('calls onPageChange when first button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <Pagination
        currentPage={10}
        totalPages={20}
        onPageChange={mockOnPageChange}
        showFirstLast={true}
      />,
    );

    const firstButton = screen.getByLabelText('First page');
    await user.click(firstButton);

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

  it('calls onPageChange when last button is clicked', async () => {
    const user = userEvent.setup();
    render(
      <Pagination
        currentPage={10}
        totalPages={20}
        onPageChange={mockOnPageChange}
        showFirstLast={true}
      />,
    );

    const lastButton = screen.getByLabelText('Last page');
    await user.click(lastButton);

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

  it('disables first button on first page when showFirstLast is true', () => {
    render(
      <Pagination
        currentPage={1}
        totalPages={10}
        onPageChange={mockOnPageChange}
        showFirstLast={true}
      />,
    );

    const firstButton = screen.getByLabelText('First page');
    expect(firstButton).toBeDisabled();
  });

  it('disables last button on last page when showFirstLast is true', () => {
    render(
      <Pagination
        currentPage={10}
        totalPages={10}
        onPageChange={mockOnPageChange}
        showFirstLast={true}
      />,
    );

    const lastButton = screen.getByLabelText('Last page');
    expect(lastButton).toBeDisabled();
  });

  it('limits visible pages based on maxVisiblePages', () => {
    render(
      <Pagination
        currentPage={5}
        totalPages={20}
        onPageChange={mockOnPageChange}
        maxVisiblePages={3}
      />,
    );

    // Devrait afficher seulement 3 pages visibles (plus première et dernière)
    const pageButtons = screen.getAllByRole('button').filter((btn) => {
      const text = btn.textContent;
      return text && /^\d+$/.test(text.trim());
    });

    // Au moins les pages visibles doivent être présentes
    expect(pageButtons.length).toBeGreaterThanOrEqual(3);
  });

  it('returns null when totalPages is 1', () => {
    const { container } = render(
      <Pagination
        currentPage={1}
        totalPages={1}
        onPageChange={mockOnPageChange}
      />,
    );

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

  it('returns null when totalPages is 0', () => {
    const { container } = render(
      <Pagination
        currentPage={1}
        totalPages={0}
        onPageChange={mockOnPageChange}
      />,
    );

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

  it('applies custom className', () => {
    const { container } = render(
      <Pagination
        currentPage={1}
        totalPages={5}
        onPageChange={mockOnPageChange}
        className="custom-class"
      />,
    );

    const nav = container.querySelector('nav');
    expect(nav).toHaveClass('custom-class');
  });

  it('has correct aria-label', () => {
    const { container } = render(
      <Pagination
        currentPage={1}
        totalPages={5}
        onPageChange={mockOnPageChange}
      />,
    );

    const nav = container.querySelector('nav');
    expect(nav).toHaveAttribute('aria-label', 'Pagination');
  });

  it('handles edge case when currentPage is at start', () => {
    render(
      <Pagination
        currentPage={1}
        totalPages={20}
        onPageChange={mockOnPageChange}
        maxVisiblePages={5}
      />,
    );

    expect(screen.getByText('1')).toBeInTheDocument();
  });

  it('handles edge case when currentPage is at end', () => {
    render(
      <Pagination
        currentPage={20}
        totalPages={20}
        onPageChange={mockOnPageChange}
        maxVisiblePages={5}
      />,
    );

    expect(screen.getByText('20')).toBeInTheDocument();
  });
});
