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

describe('PlayPauseButton', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should render play button when not playing', () => {
    render(<PlayPauseButton isPlaying={false} />);

    const button = screen.getByRole('button');
    expect(button).toBeInTheDocument();
    expect(button).toHaveAttribute('aria-label', 'Lire');
  });

  it('should render pause button when playing', () => {
    render(<PlayPauseButton isPlaying={true} />);

    const button = screen.getByRole('button');
    expect(button).toBeInTheDocument();
    expect(button).toHaveAttribute('aria-label', 'Mettre en pause');
  });

  it('should show loading spinner when loading', () => {
    render(<PlayPauseButton isPlaying={false} isLoading={true} />);

    const button = screen.getByRole('button');
    expect(button).toHaveAttribute('aria-busy', 'true');
    expect(button).toBeDisabled();
  });

  it('should call onClick when clicked', async () => {
    const user = userEvent.setup();
    const handleClick = vi.fn();

    render(<PlayPauseButton isPlaying={false} onClick={handleClick} />);

    const button = screen.getByRole('button');
    await user.click(button);

    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('should not call onClick when disabled', async () => {
    const user = userEvent.setup();
    const handleClick = vi.fn();

    render(
      <PlayPauseButton isPlaying={false} onClick={handleClick} disabled />,
    );

    const button = screen.getByRole('button');
    await user.click(button);

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

  it('should not call onClick when loading', async () => {
    const user = userEvent.setup();
    const handleClick = vi.fn();

    render(
      <PlayPauseButton isPlaying={false} onClick={handleClick} isLoading />,
    );

    const button = screen.getByRole('button');
    await user.click(button);

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

  it('should apply custom className', () => {
    const { container } = render(
      <PlayPauseButton isPlaying={false} className="custom-class" />,
    );

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

  it('should apply size classes', () => {
    const { container: smContainer } = render(
      <PlayPauseButton isPlaying={false} size="sm" />,
    );
    expect(smContainer.firstChild).toHaveClass('h-8', 'w-8');

    const { container: mdContainer } = render(
      <PlayPauseButton isPlaying={false} size="md" />,
    );
    expect(mdContainer.firstChild).toHaveClass('h-10', 'w-10');

    const { container: lgContainer } = render(
      <PlayPauseButton isPlaying={false} size="lg" />,
    );
    expect(lgContainer.firstChild).toHaveClass('h-12', 'w-12');
  });

  it('should apply variant classes', () => {
    const { container: defaultContainer } = render(
      <PlayPauseButton isPlaying={false} variant="default" />,
    );
    expect(defaultContainer.firstChild).toHaveClass('bg-blue-600');

    const { container: ghostContainer } = render(
      <PlayPauseButton isPlaying={false} variant="ghost" />,
    );
    expect(ghostContainer.firstChild).toHaveClass('bg-transparent');

    const { container: outlineContainer } = render(
      <PlayPauseButton isPlaying={false} variant="outline" />,
    );
    expect(outlineContainer.firstChild).toHaveClass('border');
  });

  it('should be disabled when disabled prop is true', () => {
    render(<PlayPauseButton isPlaying={false} disabled />);

    const button = screen.getByRole('button');
    expect(button).toBeDisabled();
  });

  it('should be disabled when loading', () => {
    render(<PlayPauseButton isPlaying={false} isLoading />);

    const button = screen.getByRole('button');
    expect(button).toBeDisabled();
  });

  it('should have accessible labels', () => {
    const { rerender } = render(<PlayPauseButton isPlaying={false} />);

    let button = screen.getByRole('button');
    expect(button).toHaveAttribute('aria-label', 'Lire');
    expect(
      screen.getByText('Lire', { selector: '.sr-only' }),
    ).toBeInTheDocument();

    rerender(<PlayPauseButton isPlaying={true} />);

    button = screen.getByRole('button');
    expect(button).toHaveAttribute('aria-label', 'Mettre en pause');
    expect(
      screen.getByText('Mettre en pause', { selector: '.sr-only' }),
    ).toBeInTheDocument();
  });

  it('should pass through additional props', () => {
    render(<PlayPauseButton isPlaying={false} data-testid="custom-testid" />);

    const button = screen.getByTestId('custom-testid');
    expect(button).toBeInTheDocument();
  });
});
