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

// Mock du composant Select
vi.mock('@/components/ui/select', () => ({
  Select: ({
    options,
    value,
    onChange,
    placeholder,
    disabled,
    className,
  }: any) => {
    return (
      <div data-testid="bitrate-select" className={className}>
        <button
          data-testid="select-trigger"
          disabled={disabled}
          onClick={() => {
            // Simuler l'ouverture du dropdown
            const dropdown = document.getElementById('bitrate-dropdown');
            if (dropdown) {
              dropdown.style.display = 'block';
            }
          }}
        >
          {value ? `${value} kbps` : placeholder}
        </button>
        <div
          id="bitrate-dropdown"
          style={{ display: 'none' }}
          data-testid="select-dropdown"
        >
          {options.map((option: any) => (
            <div
              key={option.value}
              data-testid={`option-${option.value}`}
              onClick={() => onChange(option.value)}
            >
              {option.label}
            </div>
          ))}
        </div>
      </div>
    );
  },
}));

describe('BitrateSelector', () => {
  const mockOnBitrateChange = vi.fn();
  const defaultBitrates = [128, 192, 320];

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

  it('should render with current bitrate', () => {
    render(
      <BitrateSelector
        bitrates={defaultBitrates}
        currentBitrate={192}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    expect(screen.getByTestId('bitrate-select')).toBeInTheDocument();
    const trigger = screen.getByTestId('select-trigger');
    expect(trigger).toHaveTextContent('192 kbps');
  });

  it('should display placeholder when no current bitrate', () => {
    render(
      <BitrateSelector
        bitrates={defaultBitrates}
        currentBitrate={0}
        onBitrateChange={mockOnBitrateChange}
        placeholder="Select quality..."
      />,
    );

    const trigger = screen.getByTestId('select-trigger');
    expect(trigger).toHaveTextContent('Select quality...');
  });

  it('should sort bitrates in descending order', () => {
    const { container } = render(
      <BitrateSelector
        bitrates={[128, 320, 192]}
        currentBitrate={192}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    const dropdown = screen.getByTestId('select-dropdown');
    const options = dropdown.querySelectorAll('[data-testid^="option-"]');

    // Les options devraient être triées: 320, 192, 128
    expect(options[0]).toHaveAttribute('data-testid', 'option-320');
    expect(options[1]).toHaveAttribute('data-testid', 'option-192');
    expect(options[2]).toHaveAttribute('data-testid', 'option-128');
  });

  it('should call onBitrateChange when bitrate is selected', async () => {
    const user = userEvent.setup();
    render(
      <BitrateSelector
        bitrates={defaultBitrates}
        currentBitrate={128}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    const trigger = screen.getByTestId('select-trigger');
    await user.click(trigger);

    // Simuler l'ouverture du dropdown
    const dropdown = screen.getByTestId('select-dropdown');
    dropdown.style.display = 'block';

    await waitFor(() => {
      expect(dropdown).toBeInTheDocument();
    });

    const option320 = screen.getByTestId('option-320');
    await user.click(option320);

    expect(mockOnBitrateChange).toHaveBeenCalledWith(320);
  });

  it('should handle empty bitrates array', () => {
    render(
      <BitrateSelector
        bitrates={[]}
        currentBitrate={0}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    expect(screen.getByTestId('bitrate-select')).toBeInTheDocument();
    const dropdown = screen.getByTestId('select-dropdown');
    const options = dropdown.querySelectorAll('[data-testid^="option-"]');
    expect(options.length).toBe(0);
  });

  it('should handle single bitrate', () => {
    render(
      <BitrateSelector
        bitrates={[128]}
        currentBitrate={128}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    const trigger = screen.getByTestId('select-trigger');
    expect(trigger).toHaveTextContent('128 kbps');
    const dropdown = screen.getByTestId('select-dropdown');
    const options = dropdown.querySelectorAll('[data-testid^="option-"]');
    expect(options.length).toBe(1);
  });

  it('should apply custom className', () => {
    const { container } = render(
      <BitrateSelector
        bitrates={defaultBitrates}
        currentBitrate={192}
        onBitrateChange={mockOnBitrateChange}
        className="custom-class"
      />,
    );

    const select = screen.getByTestId('bitrate-select');
    expect(select).toHaveClass('custom-class');
  });

  it('should disable select when disabled prop is true', () => {
    render(
      <BitrateSelector
        bitrates={defaultBitrates}
        currentBitrate={192}
        onBitrateChange={mockOnBitrateChange}
        disabled={true}
      />,
    );

    const trigger = screen.getByTestId('select-trigger');
    expect(trigger).toBeDisabled();
  });

  it('should handle bitrate change to same value', async () => {
    const user = userEvent.setup();
    render(
      <BitrateSelector
        bitrates={defaultBitrates}
        currentBitrate={192}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    const trigger = screen.getByTestId('select-trigger');
    await user.click(trigger);

    const dropdown = screen.getByTestId('select-dropdown');
    dropdown.style.display = 'block';

    const option192 = screen.getByTestId('option-192');
    await user.click(option192);

    // Le callback devrait quand même être appelé
    expect(mockOnBitrateChange).toHaveBeenCalledWith(192);
  });

  it('should format bitrate labels correctly', () => {
    render(
      <BitrateSelector
        bitrates={[64, 128, 256, 512]}
        currentBitrate={128}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    const dropdown = screen.getByTestId('select-dropdown');
    const option64 = screen.getByTestId('option-64');
    const option128 = screen.getByTestId('option-128');
    const option256 = screen.getByTestId('option-256');
    const option512 = screen.getByTestId('option-512');

    expect(option64).toHaveTextContent('64 kbps');
    expect(option128).toHaveTextContent('128 kbps');
    expect(option256).toHaveTextContent('256 kbps');
    expect(option512).toHaveTextContent('512 kbps');
  });

  it('should handle large bitrate values', () => {
    render(
      <BitrateSelector
        bitrates={[1000, 2000, 5000]}
        currentBitrate={2000}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    const trigger = screen.getByTestId('select-trigger');
    expect(trigger).toHaveTextContent('2000 kbps');

    const option2000 = screen.getByTestId('option-2000');
    expect(option2000).toHaveTextContent('2000 kbps');
  });

  it('should update when currentBitrate prop changes', () => {
    const { rerender } = render(
      <BitrateSelector
        bitrates={defaultBitrates}
        currentBitrate={128}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    const trigger1 = screen.getByTestId('select-trigger');
    expect(trigger1).toHaveTextContent('128 kbps');

    rerender(
      <BitrateSelector
        bitrates={defaultBitrates}
        currentBitrate={320}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    const trigger2 = screen.getByTestId('select-trigger');
    expect(trigger2).toHaveTextContent('320 kbps');
  });

  it('should handle bitrates array change', () => {
    const { rerender } = render(
      <BitrateSelector
        bitrates={[128, 192]}
        currentBitrate={128}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    let dropdown = screen.getByTestId('select-dropdown');
    let options = dropdown.querySelectorAll('[data-testid^="option-"]');
    expect(options.length).toBe(2);

    rerender(
      <BitrateSelector
        bitrates={[128, 192, 320, 512]}
        currentBitrate={192}
        onBitrateChange={mockOnBitrateChange}
      />,
    );

    dropdown = screen.getByTestId('select-dropdown');
    options = dropdown.querySelectorAll('[data-testid^="option-"]');
    expect(options.length).toBe(4);
  });
});
