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

describe('FormInput', () => {
  it('renders input element', () => {
    render(<FormInput />);
    expect(screen.getByRole('textbox')).toBeInTheDocument();
  });

  it('renders label when provided', () => {
    render(<FormInput label="Username" />);
    expect(screen.getByText('Username')).toBeInTheDocument();
  });

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

  it('displays error message', () => {
    render(<FormInput error="This field is required" />);
    expect(screen.getByText('This field is required')).toBeInTheDocument();
  });

  it('displays hint when provided', () => {
    render(<FormInput hint="Enter your username" />);
    expect(screen.getByText('Enter your username')).toBeInTheDocument();
  });

  it('hides hint when error is shown', () => {
    render(<FormInput hint="Enter your username" error="Required" />);
    expect(screen.queryByText('Enter your username')).not.toBeInTheDocument();
    expect(screen.getByText('Required')).toBeInTheDocument();
  });

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

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

  it('applies small size classes', () => {
    render(<FormInput inputSize="sm" />);
    expect(screen.getByRole('textbox')).toHaveClass('py-1');
  });

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

  it('applies large size classes', () => {
    render(<FormInput inputSize="lg" />);
    expect(screen.getByRole('textbox')).toHaveClass('py-3');
  });

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

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

  it('renders left icon', () => {
    render(<FormInput leftIcon={<span data-testid="left-icon">L</span>} />);
    expect(screen.getByTestId('left-icon')).toBeInTheDocument();
  });

  it('renders right icon', () => {
    render(<FormInput rightIcon={<span data-testid="right-icon">R</span>} />);
    expect(screen.getByTestId('right-icon')).toBeInTheDocument();
  });

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

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

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

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

  it('uses name as id fallback', () => {
    render(<FormInput name="username" label="Label" />);
    expect(screen.getByRole('textbox')).toHaveAttribute('id', 'username');
  });

  it('generates random id when none provided', () => {
    render(<FormInput label="Label" />);
    expect(screen.getByRole('textbox')).toHaveAttribute('id');
  });

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

  it('forwards ref to input element', () => {
    const ref = { current: null as HTMLInputElement | null };
    render(<FormInput ref={ref} />);
    expect(ref.current).toBeInstanceOf(HTMLInputElement);
  });

  it('passes through other input props', () => {
    render(<FormInput placeholder="Enter text" type="email" maxLength={50} />);
    const input = screen.getByRole('textbox');
    expect(input).toHaveAttribute('placeholder', 'Enter text');
    expect(input).toHaveAttribute('type', 'email');
    expect(input).toHaveAttribute('maxLength', '50');
  });
});
