/**
 * MultiSelectField Tests
 */
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MultiSelectField } from './MultiSelectField';
import { ActionField } from '../../types/action';

describe('MultiSelectField', () => {
  const defaultField: ActionField = {
    type: 'multi_select',
    label: 'Tags',
    description: 'Select one or more tags',
    required: false,
    options: [
      { value: 'important', label: 'Important' },
      { value: 'urgent', label: 'Urgent' },
      { value: 'low', label: 'Low Priority' },
    ],
  };

  it('renders label and description', () => {
    render(
      <MultiSelectField
        fieldName="tags"
        field={defaultField}
        value={[]}
        onChange={vi.fn()}
      />,
    );
    expect(screen.getByText('Tags')).toBeInTheDocument();
    expect(screen.getByText('Select one or more tags')).toBeInTheDocument();
  });

  it('renders chips for selected values', () => {
    render(
      <MultiSelectField
        fieldName="tags"
        field={defaultField}
        value={['important', 'urgent']}
        onChange={vi.fn()}
      />,
    );
    expect(screen.getByText('Important')).toBeInTheDocument();
    expect(screen.getByText('Urgent')).toBeInTheDocument();
  });

  it('shows placeholder when no values selected', () => {
    render(
      <MultiSelectField
        fieldName="tags"
        field={defaultField}
        value={[]}
        onChange={vi.fn()}
      />,
    );
    expect(screen.getByText('Select tags...')).toBeInTheDocument();
  });

  it('opens popover and shows options when clicked', async () => {
    const user = userEvent.setup();
    render(
      <MultiSelectField
        fieldName="tags"
        field={defaultField}
        value={[]}
        onChange={vi.fn()}
      />,
    );
    await user.click(screen.getByRole('combobox'));
    expect(screen.getByText('Important')).toBeInTheDocument();
    expect(screen.getByText('Urgent')).toBeInTheDocument();
    expect(screen.getByText('Low Priority')).toBeInTheDocument();
  });

  it('calls onChange to add a value when option clicked', async () => {
    const user = userEvent.setup();
    const onChange = vi.fn();
    render(
      <MultiSelectField
        fieldName="tags"
        field={defaultField}
        value={['important']}
        onChange={onChange}
      />,
    );
    await user.click(screen.getByRole('combobox'));
    await user.click(screen.getByText('Urgent'));
    expect(onChange).toHaveBeenCalledWith(['important', 'urgent']);
  });

  it('calls onChange to remove a value when selected option clicked', async () => {
    const user = userEvent.setup();
    const onChange = vi.fn();
    render(
      <MultiSelectField
        fieldName="tags"
        field={defaultField}
        value={['important', 'urgent']}
        onChange={onChange}
      />,
    );
    await user.click(screen.getByRole('combobox'));
    // Click the option inside the command list (not the chip badge)
    const options = screen.getAllByText('Important');
    const commandOption = options.find((el) => el.closest('[cmdk-item]'));
    await user.click(commandOption!);
    expect(onChange).toHaveBeenCalledWith(['urgent']);
  });

  it('shows loading state', () => {
    render(
      <MultiSelectField
        fieldName="tags"
        field={defaultField}
        value={[]}
        onChange={vi.fn()}
        isLoading={true}
      />,
    );
    expect(screen.getByText('Loading options...')).toBeInTheDocument();
  });

  it('shows dependency message when dependency not met', () => {
    const dependentField: ActionField = {
      ...defaultField,
      depends_on: 'list_id',
    };
    render(
      <MultiSelectField
        fieldName="tags"
        field={dependentField}
        value={[]}
        onChange={vi.fn()}
        dependencyMet={false}
        dependencyLabel="List"
      />,
    );
    expect(screen.getByText('Select a List first.')).toBeInTheDocument();
  });

  it('shows field error', () => {
    render(
      <MultiSelectField
        fieldName="tags"
        field={defaultField}
        value={[]}
        onChange={vi.fn()}
        fieldError="Failed to load options"
      />,
    );
    expect(screen.getByText('Failed to load options')).toBeInTheDocument();
  });

  it('shows validation error', () => {
    render(
      <MultiSelectField
        fieldName="tags"
        field={defaultField}
        value={[]}
        onChange={vi.fn()}
        error="At least one tag is required"
      />,
    );
    expect(screen.getByText('At least one tag is required')).toBeInTheDocument();
  });

  it('shows required indicator', () => {
    const requiredField: ActionField = { ...defaultField, required: true };
    render(
      <MultiSelectField
        fieldName="tags"
        field={requiredField}
        value={[]}
        onChange={vi.fn()}
      />,
    );
    expect(screen.getByText('*')).toBeInTheDocument();
  });

  it('uses dynamic options when provided', () => {
    render(
      <MultiSelectField
        fieldName="tags"
        field={defaultField}
        value={['dyn1']}
        onChange={vi.fn()}
        options={[
          { value: 'dyn1', label: 'Dynamic 1' },
          { value: 'dyn2', label: 'Dynamic 2' },
        ]}
      />,
    );
    expect(screen.getByText('Dynamic 1')).toBeInTheDocument();
  });
});
