import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { FormSelect } from '../FormSelect';

const options = [
  { value: 'option1', label: 'Option 1' },
  { value: 'option2', label: 'Option 2' },
  { value: 'option3', label: 'Option 3', disabled: true },
];

describe('FormSelect', () => {
  it('renders select element', () => {
    render(<FormSelect options={options} />);
    expect(screen.getByRole('combobox')).toBeInTheDocument();
  });

  it('renders options', () => {
    render(<FormSelect options={options} />);
    expect(screen.getByText('Option 1')).toBeInTheDocument();
    expect(screen.getByText('Option 2')).toBeInTheDocument();
    expect(screen.getByText('Option 3')).toBeInTheDocument();
  });

  it('renders label when provided', () => {
    render(<FormSelect label="Select Option" options={options} />);
    expect(screen.getByText('Select Option')).toBeInTheDocument();
  });

  it('shows required indicator when required', () => {
    render(<FormSelect label="Category" options={options} required />);
    expect(screen.getByText('*')).toBeInTheDocument();
  });

  it('displays placeholder option', () => {
    render(<FormSelect options={options} placeholder="Choose one" />);
    expect(screen.getByText('Choose one')).toBeInTheDocument();
  });

  it('disables placeholder option', () => {
    render(<FormSelect options={options} placeholder="Choose one" />);
    const placeholder = screen.getByText('Choose one');
    expect(placeholder).toHaveAttribute('disabled');
  });

  it('displays error message', () => {
    render(<FormSelect options={options} error="Selection required" />);
    expect(screen.getByText('Selection required')).toBeInTheDocument();
  });

  it('displays hint when provided', () => {
    render(<FormSelect options={options} hint="Select your preference" />);
    expect(screen.getByText('Select your preference')).toBeInTheDocument();
  });

  it('hides hint when error is shown', () => {
    render(<FormSelect options={options} hint="Select option" error="Required" />);
    expect(screen.queryByText('Select option')).not.toBeInTheDocument();
    expect(screen.getByText('Required')).toBeInTheDocument();
  });

  it('applies error styling when error present', () => {
    render(<FormSelect options={options} error="Invalid" />);
    expect(screen.getByRole('combobox')).toHaveClass('border-red-500');
  });

  it('applies disabled styling', () => {
    render(<FormSelect options={options} disabled />);
    expect(screen.getByRole('combobox')).toBeDisabled();
    expect(screen.getByRole('combobox')).toHaveClass('cursor-not-allowed');
  });

  it('disables individual options', () => {
    render(<FormSelect options={options} />);
    const option3 = screen.getByText('Option 3');
    expect(option3).toHaveAttribute('disabled');
  });

  it('applies small size classes', () => {
    render(<FormSelect options={options} selectSize="sm" />);
    expect(screen.getByRole('combobox')).toHaveClass('py-1');
  });

  it('applies medium size classes by default', () => {
    render(<FormSelect options={options} />);
    expect(screen.getByRole('combobox')).toHaveClass('py-2');
  });

  it('applies large size classes', () => {
    render(<FormSelect options={options} selectSize="lg" />);
    expect(screen.getByRole('combobox')).toHaveClass('py-3');
  });

  it('applies full width by default', () => {
    render(<FormSelect options={options} />);
    expect(screen.getByRole('combobox')).toHaveClass('w-full');
  });

  it('can disable full width', () => {
    render(<FormSelect options={options} fullWidth={false} />);
    expect(screen.getByRole('combobox')).not.toHaveClass('w-full');
  });

  it('applies custom className', () => {
    render(<FormSelect options={options} className="custom-class" />);
    expect(screen.getByRole('combobox')).toHaveClass('custom-class');
  });

  it('applies custom containerClassName', () => {
    const { container } = render(<FormSelect options={options} containerClassName="container-class" />);
    expect(container.firstChild).toHaveClass('container-class');
  });

  it('handles value changes', () => {
    const handleChange = vi.fn();
    render(<FormSelect options={options} onChange={handleChange} />);
    fireEvent.change(screen.getByRole('combobox'), { target: { value: 'option2' } });
    expect(handleChange).toHaveBeenCalled();
  });

  it('uses provided id', () => {
    render(<FormSelect options={options} id="custom-id" label="Label" />);
    expect(screen.getByRole('combobox')).toHaveAttribute('id', 'custom-id');
  });

  it('uses name as id fallback', () => {
    render(<FormSelect options={options} name="category" label="Label" />);
    expect(screen.getByRole('combobox')).toHaveAttribute('id', 'category');
  });

  it('links label to select', () => {
    render(<FormSelect options={options} id="my-select" label="My Label" />);
    const select = screen.getByRole('combobox');
    const label = screen.getByText('My Label');
    expect(label).toHaveAttribute('for', 'my-select');
    expect(select).toHaveAttribute('id', 'my-select');
  });

  it('forwards ref to select element', () => {
    const ref = { current: null as HTMLSelectElement | null };
    render(<FormSelect options={options} ref={ref} />);
    expect(ref.current).toBeInstanceOf(HTMLSelectElement);
  });

  it('renders dropdown arrow icon', () => {
    const { container } = render(<FormSelect options={options} />);
    const svg = container.querySelector('svg');
    expect(svg).toBeInTheDocument();
  });
});
