import { render, fireEvent, screen } from '../../test-utils';
import TypeaheadInput, { TypeaheadInputProps } from './TypeaheadInput';
import { TypeaheadOption } from '../Typeahead';

const defaultProps: TypeaheadInputProps<number> = {
  id: 'test-id',
  name: 'test-name',
  typeaheadId: 'test-id',
  value: '',
  selected: [],
  onChange: jest.fn(),
  onKeyDown: jest.fn(),
  onFocus: jest.fn(),
  onPaste: jest.fn(),
  autoComplete: 'off',
  placeholder: 'Search...',
  renderChip: jest.fn(),
};

describe('TypeaheadInput', () => {
  afterEach(() => {
    jest.clearAllMocks();
  });

  it('renders input with placeholder', () => {
    render(<TypeaheadInput {...defaultProps} />);
    expect(screen.getByPlaceholderText('Search...')).toBeInTheDocument();
  });

  it('renders with given value', () => {
    render(<TypeaheadInput {...defaultProps} value="hello" />);
    expect(screen.getByDisplayValue('hello')).toBeInTheDocument();
  });

  it('calls onChange when input value changes', () => {
    const onChange = jest.fn();
    render(<TypeaheadInput {...defaultProps} onChange={onChange} />);
    const input = screen.getByPlaceholderText('Search...');
    fireEvent.change(input, { target: { value: 'test' } });
    expect(onChange).toHaveBeenCalled();
  });

  it('calls onFocus when input is focused', () => {
    const onFocus = jest.fn();
    render(<TypeaheadInput {...defaultProps} onFocus={onFocus} />);
    const input = screen.getByPlaceholderText('Search...');
    fireEvent.focus(input);
    expect(onFocus).toHaveBeenCalled();
  });

  it('calls onPaste when input is pasted into', () => {
    const onPaste = jest.fn();
    render(<TypeaheadInput {...defaultProps} onPaste={onPaste} />);
    const input = screen.getByPlaceholderText('Search...');
    fireEvent.paste(input, { clipboardData: { getData: () => 'pasted' } });
    expect(onPaste).toHaveBeenCalled();
  });

  it('calls onKeyDown when key is pressed', () => {
    const onKeyDown = jest.fn();
    render(<TypeaheadInput {...defaultProps} onKeyDown={onKeyDown} />);
    const input = screen.getByPlaceholderText('Search...');
    fireEvent.keyDown(input, { key: 'ArrowDown', code: 'ArrowDown' });
    expect(onKeyDown).toHaveBeenCalled();
  });

  it('renders chips when multiple is true and selected has items', () => {
    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
    const renderChip = jest.fn((chip, idx) => <span key={idx}>{chip.label}</span>);
    const selected = [
      { label: 'Chip 1', value: 1 },
      { label: 'Chip 2', value: 2 },
    ];
    render(
      <TypeaheadInput {...defaultProps} multiple selected={selected} renderChip={renderChip} />,
    );
    expect(screen.getByText('Chip 1')).toBeInTheDocument();
    expect(screen.getByText('Chip 2')).toBeInTheDocument();
  });

  it('does not show placeholder if multiple is true and selected has items', () => {
    const selected: TypeaheadOption<number>[] = [{ label: 'Chip', value: 1 }];
    render(<TypeaheadInput<number> {...defaultProps} multiple selected={selected} />);
    expect(screen.queryByPlaceholderText('Search...')).not.toBeInTheDocument();
  });

  it('applies input width style when multiple and selected has items', () => {
    const selected = [{ label: 'Chip', value: 1 }];
    const { container } = render(
      <TypeaheadInput {...defaultProps} multiple selected={selected} value="test" />,
    );
    const input = container.querySelector('input');
    expect(input?.style.width).not.toBe('');
  });

  it('sets aria attributes correctly', () => {
    render(<TypeaheadInput {...defaultProps} dropdownOpen ariaActivedescendant="option-1" />);
    const input = screen.getByRole('combobox');
    expect(input).toHaveAttribute('aria-expanded', 'true');
    expect(input).toHaveAttribute('aria-haspopup', 'listbox');
    expect(input).toHaveAttribute('aria-activedescendant', expect.stringContaining('option-1'));
  });
});
