import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { PreferenceSettings } from './PreferenceSettings';
import { PreferenceSettings as PreferenceSettingsType } from '../../types/settings';

// Mock ResizeObserver for tests
global.ResizeObserver = vi.fn().mockImplementation(() => ({
  observe: vi.fn(),
  unobserve: vi.fn(),
  disconnect: vi.fn(),
}));

// Mock Select component
vi.mock('@/components/ui/select', () => ({
  Select: ({ value, onChange, options, placeholder }: any) => (
    <div data-testid="select">
      <select
        value={typeof value === 'string' ? value : ''}
        onChange={(e) => onChange(e.target.value)}
        data-placeholder={placeholder}
      >
        <option value="">{placeholder}</option>
        {options.map((opt: any) => (
          <option key={opt.value} value={opt.value}>
            {opt.label}
          </option>
        ))}
      </select>
    </div>
  ),
}));

// Mock RadioGroup
vi.mock('@/components/ui/radio-group', () => ({
  RadioGroup: ({ children, value, onValueChange }: any) => (
    <div data-testid="radio-group" data-value={value}>
      {children}
      <button onClick={() => onValueChange('light')}>Select Light</button>
      <button onClick={() => onValueChange('dark')}>Select Dark</button>
      <button onClick={() => onValueChange('auto')}>Select Auto</button>
    </div>
  ),
  RadioGroupItem: ({ value, id }: any) => (
    <input type="radio" value={value} id={id} data-testid={`radio-${value}`} />
  ),
}));

// Mock Label
vi.mock('@/components/ui/label', () => ({
  Label: ({ children, htmlFor }: any) => (
    <label htmlFor={htmlFor}>{children}</label>
  ),
}));

describe('PreferenceSettings Component', () => {
  const mockPreferences: PreferenceSettingsType = {
    language: 'en',
    timezone: 'UTC',
    theme: 'auto',
  };

  const mockOnChange = vi.fn();

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

  it('should render all preference fields', () => {
    render(
      <PreferenceSettings
        preferences={mockPreferences}
        onChange={mockOnChange}
      />,
    );

    expect(screen.getByText('Langue')).toBeInTheDocument();
    expect(screen.getByText('Fuseau horaire')).toBeInTheDocument();
    expect(screen.getByText('Thème')).toBeInTheDocument();
    expect(screen.getByTestId('radio-group')).toBeInTheDocument();
  });

  it('should display current language value', () => {
    render(
      <PreferenceSettings
        preferences={mockPreferences}
        onChange={mockOnChange}
      />,
    );

    const selects = screen.getAllByTestId('select');
    const languageSelect = selects[0].querySelector('select');
    expect(languageSelect).toHaveValue('en');
  });

  it('should call onChange when language changes', () => {
    render(
      <PreferenceSettings
        preferences={mockPreferences}
        onChange={mockOnChange}
      />,
    );

    const selects = screen.getAllByTestId('select');
    const languageSelect = selects[0].querySelector('select');
    if (languageSelect) {
      fireEvent.change(languageSelect, { target: { value: 'fr' } });
      expect(mockOnChange).toHaveBeenCalledWith({
        ...mockPreferences,
        language: 'fr',
      });
    }
  });

  it('should display current timezone value', () => {
    render(
      <PreferenceSettings
        preferences={mockPreferences}
        onChange={mockOnChange}
      />,
    );

    const selects = screen.getAllByTestId('select');
    const timezoneSelect = selects[1].querySelector('select');
    expect(timezoneSelect).toHaveValue('UTC');
  });

  it('should call onChange when timezone changes', () => {
    render(
      <PreferenceSettings
        preferences={mockPreferences}
        onChange={mockOnChange}
      />,
    );

    const selects = screen.getAllByTestId('select');
    const timezoneSelect = selects[1].querySelector('select');
    if (timezoneSelect) {
      fireEvent.change(timezoneSelect, { target: { value: 'Europe/Paris' } });
      expect(mockOnChange).toHaveBeenCalledWith({
        ...mockPreferences,
        timezone: 'Europe/Paris',
      });
    }
  });

  it('should display current theme value', () => {
    render(
      <PreferenceSettings
        preferences={mockPreferences}
        onChange={mockOnChange}
      />,
    );

    const radioGroup = screen.getByTestId('radio-group');
    expect(radioGroup).toHaveAttribute('data-value', 'auto');
  });

  it('should call onChange when theme changes to light', () => {
    render(
      <PreferenceSettings
        preferences={mockPreferences}
        onChange={mockOnChange}
      />,
    );

    const lightButton = screen.getByText('Select Light');
    fireEvent.click(lightButton);

    expect(mockOnChange).toHaveBeenCalledWith({
      ...mockPreferences,
      theme: 'light',
    });
  });

  it('should call onChange when theme changes to dark', () => {
    render(
      <PreferenceSettings
        preferences={mockPreferences}
        onChange={mockOnChange}
      />,
    );

    const darkButton = screen.getByText('Select Dark');
    fireEvent.click(darkButton);

    expect(mockOnChange).toHaveBeenCalledWith({
      ...mockPreferences,
      theme: 'dark',
    });
  });

  it('should call onChange when theme changes to auto', () => {
    render(
      <PreferenceSettings
        preferences={{ ...mockPreferences, theme: 'light' }}
        onChange={mockOnChange}
      />,
    );

    const autoButton = screen.getByText('Select Auto');
    fireEvent.click(autoButton);

    expect(mockOnChange).toHaveBeenCalledWith({
      ...mockPreferences,
      theme: 'auto',
    });
  });

  it('should render all theme options', () => {
    render(
      <PreferenceSettings
        preferences={mockPreferences}
        onChange={mockOnChange}
      />,
    );

    expect(screen.getByTestId('radio-light')).toBeInTheDocument();
    expect(screen.getByTestId('radio-dark')).toBeInTheDocument();
    expect(screen.getByTestId('radio-auto')).toBeInTheDocument();
  });
});
