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

describe('NextPreviousButtons', () => {
  const mockOnNext = vi.fn();
  const mockOnPrevious = vi.fn();

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

  it('should render both buttons', () => {
    render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
      />,
    );

    expect(screen.getByLabelText('Piste précédente')).toBeInTheDocument();
    expect(screen.getByLabelText('Piste suivante')).toBeInTheDocument();
  });

  it('should call onPrevious when previous button is clicked', async () => {
    const user = userEvent.setup();

    render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
      />,
    );

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

    expect(mockOnPrevious).toHaveBeenCalledTimes(1);
    expect(mockOnNext).not.toHaveBeenCalled();
  });

  it('should call onNext when next button is clicked', async () => {
    const user = userEvent.setup();

    render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
      />,
    );

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

    expect(mockOnNext).toHaveBeenCalledTimes(1);
    expect(mockOnPrevious).not.toHaveBeenCalled();
  });

  it('should disable previous button when canGoPrevious is false', () => {
    render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={false}
      />,
    );

    const previousButton = screen.getByLabelText('Piste précédente');
    expect(previousButton).toBeDisabled();
    expect(previousButton).toHaveAttribute('aria-disabled', 'true');
  });

  it('should disable next button when canGoNext is false', () => {
    render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={false}
        canGoPrevious={true}
      />,
    );

    const nextButton = screen.getByLabelText('Piste suivante');
    expect(nextButton).toBeDisabled();
    expect(nextButton).toHaveAttribute('aria-disabled', 'true');
  });

  it('should disable both buttons when disabled prop is true', () => {
    render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
        disabled={true}
      />,
    );

    const previousButton = screen.getByLabelText('Piste précédente');
    const nextButton = screen.getByLabelText('Piste suivante');

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

  it('should not call callbacks when buttons are disabled', async () => {
    const user = userEvent.setup();

    render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={false}
        canGoPrevious={false}
      />,
    );

    const previousButton = screen.getByLabelText('Piste précédente');
    const nextButton = screen.getByLabelText('Piste suivante');

    await user.click(previousButton);
    await user.click(nextButton);

    expect(mockOnPrevious).not.toHaveBeenCalled();
    expect(mockOnNext).not.toHaveBeenCalled();
  });

  it('should apply custom className', () => {
    const { container } = render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
        className="custom-class"
      />,
    );

    expect(container.firstChild).toHaveClass('custom-class');
  });

  it('should apply size classes', () => {
    const { container: smContainer } = render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
        size="sm"
      />,
    );

    const buttons = smContainer.querySelectorAll('button');
    buttons.forEach((button) => {
      expect(button).toHaveClass('h-8', 'w-8');
    });

    const { container: mdContainer } = render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
        size="md"
      />,
    );

    const mdButtons = mdContainer.querySelectorAll('button');
    mdButtons.forEach((button) => {
      expect(button).toHaveClass('h-10', 'w-10');
    });

    const { container: lgContainer } = render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
        size="lg"
      />,
    );

    const lgButtons = lgContainer.querySelectorAll('button');
    lgButtons.forEach((button) => {
      expect(button).toHaveClass('h-12', 'w-12');
    });
  });

  it('should apply variant classes', () => {
    const { container: defaultContainer } = render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
        variant="default"
      />,
    );

    const buttons = defaultContainer.querySelectorAll('button');
    buttons.forEach((button) => {
      expect(button).toHaveClass('bg-blue-600');
    });

    const { container: ghostContainer } = render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
        variant="ghost"
      />,
    );

    const ghostButtons = ghostContainer.querySelectorAll('button');
    ghostButtons.forEach((button) => {
      expect(button).toHaveClass('bg-transparent');
    });
  });

  it('should have accessible labels', () => {
    render(
      <NextPreviousButtons
        onNext={mockOnNext}
        onPrevious={mockOnPrevious}
        canGoNext={true}
        canGoPrevious={true}
      />,
    );

    expect(screen.getByLabelText('Piste précédente')).toBeInTheDocument();
    expect(screen.getByLabelText('Piste suivante')).toBeInTheDocument();
    expect(
      screen.getAllByText('Piste précédente', { selector: '.sr-only' }),
    ).toHaveLength(1);
    expect(
      screen.getAllByText('Piste suivante', { selector: '.sr-only' }),
    ).toHaveLength(1);
  });
});
