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

describe('RepeatShuffleButtons', () => {
  const mockOnRepeatChange = vi.fn();
  const mockOnShuffleToggle = vi.fn();

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

  it('should render both buttons', () => {
    render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    expect(screen.getByLabelText('Répéter désactivé')).toBeInTheDocument();
    expect(screen.getByLabelText('Mélanger désactivé')).toBeInTheDocument();
  });

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

    render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    const repeatButton = screen.getByLabelText('Répéter désactivé');
    await user.click(repeatButton);

    expect(mockOnRepeatChange).toHaveBeenCalledWith('track');
    expect(mockOnShuffleToggle).not.toHaveBeenCalled();
  });

  it('should cycle through repeat modes: off -> track -> playlist -> off', async () => {
    const user = userEvent.setup();

    const { rerender } = render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    const repeatButton = screen.getByLabelText('Répéter désactivé');

    // off -> track
    await user.click(repeatButton);
    expect(mockOnRepeatChange).toHaveBeenCalledWith('track');

    // track -> playlist
    rerender(
      <RepeatShuffleButtons
        repeat="track"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );
    await user.click(screen.getByLabelText('Répéter la piste (actif)'));
    expect(mockOnRepeatChange).toHaveBeenCalledWith('playlist');

    // playlist -> off
    rerender(
      <RepeatShuffleButtons
        repeat="playlist"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );
    await user.click(screen.getByLabelText('Répéter la playlist (actif)'));
    expect(mockOnRepeatChange).toHaveBeenCalledWith('off');
  });

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

    render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    const shuffleButton = screen.getByLabelText('Mélanger désactivé');
    await user.click(shuffleButton);

    expect(mockOnShuffleToggle).toHaveBeenCalledTimes(1);
    expect(mockOnRepeatChange).not.toHaveBeenCalled();
  });

  it('should display active state for repeat when repeat is track', () => {
    render(
      <RepeatShuffleButtons
        repeat="track"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    const repeatButton = screen.getByLabelText('Répéter la piste (actif)');
    expect(repeatButton).toHaveAttribute('aria-pressed', 'true');
    expect(repeatButton).toHaveClass('bg-blue-600');
  });

  it('should display active state for repeat when repeat is playlist', () => {
    render(
      <RepeatShuffleButtons
        repeat="playlist"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    const repeatButton = screen.getByLabelText('Répéter la playlist (actif)');
    expect(repeatButton).toHaveAttribute('aria-pressed', 'true');
    expect(repeatButton).toHaveClass('bg-blue-600');
  });

  it('should display active state for shuffle when shuffle is true', () => {
    render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={true}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    const shuffleButton = screen.getByLabelText('Mélanger activé');
    expect(shuffleButton).toHaveAttribute('aria-pressed', 'true');
    expect(shuffleButton).toHaveClass('bg-blue-600');
  });

  it('should disable buttons when disabled prop is true', () => {
    render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
        disabled={true}
      />,
    );

    const repeatButton = screen.getByLabelText('Répéter désactivé');
    const shuffleButton = screen.getByLabelText('Mélanger désactivé');

    expect(repeatButton).toBeDisabled();
    expect(shuffleButton).toBeDisabled();
    expect(repeatButton).toHaveAttribute('aria-disabled', 'true');
    expect(shuffleButton).toHaveAttribute('aria-disabled', 'true');
  });

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

    render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
        disabled={true}
      />,
    );

    const repeatButton = screen.getByLabelText('Répéter désactivé');
    const shuffleButton = screen.getByLabelText('Mélanger désactivé');

    await user.click(repeatButton);
    await user.click(shuffleButton);

    expect(mockOnRepeatChange).not.toHaveBeenCalled();
    expect(mockOnShuffleToggle).not.toHaveBeenCalled();
  });

  it('should apply custom className', () => {
    const { container } = render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
        className="custom-class"
      />,
    );

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

  it('should apply size classes', () => {
    const { container: smContainer } = render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
        size="sm"
      />,
    );

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

    const { container: mdContainer } = render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
        size="md"
      />,
    );

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

    const { container: lgContainer } = render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
        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(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
        variant="default"
      />,
    );

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

    const { container: ghostContainer } = render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
        variant="ghost"
      />,
    );

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

  it('should have accessible labels', () => {
    render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    expect(screen.getByLabelText('Répéter désactivé')).toBeInTheDocument();
    expect(screen.getByLabelText('Mélanger désactivé')).toBeInTheDocument();
  });

  it('should show correct labels for different repeat states', () => {
    const { rerender } = render(
      <RepeatShuffleButtons
        repeat="off"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    expect(screen.getByLabelText('Répéter désactivé')).toBeInTheDocument();

    rerender(
      <RepeatShuffleButtons
        repeat="track"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    expect(
      screen.getByLabelText('Répéter la piste (actif)'),
    ).toBeInTheDocument();

    rerender(
      <RepeatShuffleButtons
        repeat="playlist"
        shuffle={false}
        onRepeatChange={mockOnRepeatChange}
        onShuffleToggle={mockOnShuffleToggle}
      />,
    );

    expect(
      screen.getByLabelText('Répéter la playlist (actif)'),
    ).toBeInTheDocument();
  });
});
