import { Input, InputType } from '../../types';
import { checkboxFilterInputMapping } from './checkbox-filter-input.mapping';
import * as checkboxOptionMappingModule from './checkbox-option.mapping';
import * as schemaModule from '../schemas/checkbox-filter-input.schema';

describe('checkboxFilterInputMapping', () => {
  const mockCheckboxOptionMapping = jest.fn().mockImplementation((option) => ({
    label: option.label,
    value: option.value,
  }));

  const mockSchemaParser = jest.fn().mockImplementation((input) => input);

  beforeEach(() => {
    jest.clearAllMocks();
    jest
      .spyOn(checkboxOptionMappingModule, 'checkboxOptionMapping')
      .mockImplementation(mockCheckboxOptionMapping);

    // Mock the schema parse method to avoid validation errors in tests
    jest
      .spyOn(schemaModule.CheckboxFilterInputSchema, 'parse')
      .mockImplementation(mockSchemaParser);
  });

  it('should map minimal input correctly', () => {
    // Arrange
    const group = 'testGroup';
    const input: Input = {
      key: 'testKey',
      label: 'Test Label',
      type: InputType.Checkbox,
    };

    // Act
    const result = checkboxFilterInputMapping(group, input);

    // Assert
    expect(mockSchemaParser).toHaveBeenCalledWith({
      group: 'testGroup',
      key: 'testKey',
      label: 'Test Label',
      type: InputType.Checkbox,
      defaultValue: undefined,
      maxOptions: undefined,
      target: undefined,
      options: undefined,
      selected: [],
      description: undefined,
    });

    expect(result).toEqual({
      group: 'testGroup',
      key: 'testKey',
      label: 'Test Label',
      type: InputType.Checkbox,
      defaultValue: undefined,
      maxOptions: undefined,
      target: undefined,
      options: undefined,
      selected: [],
      description: undefined,
    });
  });

  it('should map complete input correctly', () => {
    // Arrange
    const group = 'testGroup';
    const input: Input = {
      key: 'testKey',
      label: 'Test Label',
      description: 'Test Description',
      type: InputType.Checkbox,
      value: 'defaultValue',
      options: {
        max: 3,
        values: [
          { label: 'Option 1', value: 'value1', selected: false },
          { label: 'Option 2', value: 'value2', selected: false },
        ],
      },
    };

    // Act
    const result = checkboxFilterInputMapping(group, input);

    // Assert
    expect(mockSchemaParser).toHaveBeenCalledWith({
      group: 'testGroup',
      key: 'testKey',
      label: 'Test Label',
      description: 'Test Description',
      type: InputType.Checkbox,
      defaultValue: 'defaultValue',
      maxOptions: 3,
      target: undefined,
      options: [
        { label: 'Option 1', value: 'value1' },
        { label: 'Option 2', value: 'value2' },
      ],
      selected: [],
    });

    expect(result).toEqual({
      group: 'testGroup',
      key: 'testKey',
      label: 'Test Label',
      description: 'Test Description',
      type: InputType.Checkbox,
      defaultValue: 'defaultValue',
      maxOptions: 3,
      target: undefined,
      options: [
        { label: 'Option 1', value: 'value1' },
        { label: 'Option 2', value: 'value2' },
      ],
      selected: [],
    });
    expect(mockCheckboxOptionMapping).toHaveBeenCalledTimes(2);
  });

  it('should map selected options correctly', () => {
    // Arrange
    const group = 'testGroup';
    const input: Input = {
      key: 'testKey',
      label: 'Test Label',
      type: InputType.Checkbox,
      options: {
        values: [
          { label: 'Option 1', value: 'value1', selected: true },
          { label: 'Option 2', value: 'value2', selected: false },
          { label: 'Option 3', value: 'value3', selected: true },
        ],
      },
    };

    // Act
    const result = checkboxFilterInputMapping(group, input);

    // Assert
    expect(mockSchemaParser).toHaveBeenCalledWith({
      group: 'testGroup',
      key: 'testKey',
      label: 'Test Label',
      type: InputType.Checkbox,
      defaultValue: undefined,
      maxOptions: undefined,
      target: undefined,
      options: [
        { label: 'Option 1', value: 'value1' },
        { label: 'Option 2', value: 'value2' },
        { label: 'Option 3', value: 'value3' },
      ],
      selected: ['value1', 'value3'],
      description: undefined,
    });

    expect(result.selected).toEqual(['value1', 'value3']);
    expect(mockCheckboxOptionMapping).toHaveBeenCalledTimes(3);
  });

  it('should handle empty options array', () => {
    // Arrange
    const group = 'testGroup';
    const input: Input = {
      key: 'testKey',
      label: 'Test Label',
      type: InputType.Checkbox,
      options: {
        values: [],
      },
    };

    // Act
    const result = checkboxFilterInputMapping(group, input);

    // Assert
    expect(mockSchemaParser).toHaveBeenCalledWith({
      group: 'testGroup',
      key: 'testKey',
      label: 'Test Label',
      type: InputType.Checkbox,
      defaultValue: undefined,
      maxOptions: undefined,
      target: undefined,
      options: [],
      selected: [],
      description: undefined,
    });

    expect(result.options).toEqual([]);
    expect(result.selected).toEqual([]);
    expect(mockCheckboxOptionMapping).not.toHaveBeenCalled();
  });

  it('should handle undefined options', () => {
    // Arrange
    const group = 'testGroup';
    const input: Input = {
      key: 'testKey',
      label: 'Test Label',
      type: InputType.Checkbox,
    };

    // Act
    const result = checkboxFilterInputMapping(group, input);

    // Assert
    expect(mockSchemaParser).toHaveBeenCalledWith({
      group: 'testGroup',
      key: 'testKey',
      label: 'Test Label',
      type: InputType.Checkbox,
      defaultValue: undefined,
      maxOptions: undefined,
      target: undefined,
      options: undefined,
      selected: [],
      description: undefined,
    });

    expect(result.options).toBeUndefined();
    expect(result.selected).toEqual([]);
    expect(mockCheckboxOptionMapping).not.toHaveBeenCalled();
  });
});
