import { Option } from '../../types';
import { checkboxOptionMapping } from './checkbox-option.mapping';
import * as schemaModule from '../schemas/checkbox-filter-input-option.schema';

describe('checkboxOptionMapping', () => {
  const mockSchemaParser = jest.fn().mockImplementation((input) => input);

  beforeEach(() => {
    jest.clearAllMocks();

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

  it('should map option correctly', () => {
    // Arrange
    const option: Option = {
      key: 'Option Key',
      label: 'Option Label',
      value: 'option-value',
    };

    // Act
    const result = checkboxOptionMapping(option);

    // Assert
    expect(result).toEqual({
      key: 'Option Key',
      label: 'Option Label',
      value: 'option-value',
      path: ['Option Key'],
    });
  });

  it('should map option with selected property', () => {
    // Arrange
    const option: Option = {
      label: 'Option Label',
      value: 'option-value',
      selected: true,
    };

    // Act
    const result = checkboxOptionMapping(option);

    // Assert
    expect(result).toEqual({
      key: 'option-value',
      label: 'Option Label',
      value: 'option-value',
      path: ['option-value'],
    });
    // The selected property should not be included in the mapped result
    expect(result).not.toHaveProperty('selected');
  });

  it('should use value as key when key is not provided', () => {
    // Arrange
    const option: Option = {
      label: 'Option Label',
      value: 'option-value',
    };

    // Act
    const result = checkboxOptionMapping(option);

    // Assert
    expect(result).toEqual({
      key: 'option-value',
      label: 'Option Label',
      value: 'option-value',
      path: ['option-value'],
    });
  });

  it('should handle custom path parameter', () => {
    // Arrange
    const option: Option = {
      key: 'child',
      label: 'Child Option',
      value: 'child-value',
    };
    const path = ['group', 'parent'];

    // Act
    const result = checkboxOptionMapping(option, path);

    // Assert
    expect(result).toEqual({
      key: 'child',
      label: 'Child Option',
      value: 'child-value',
      path: ['group', 'parent', 'child'],
    });
  });

  it('should map nested options with one level', () => {
    // Arrange
    const option: Option = {
      key: 'parent',
      label: 'Parent Option',
      value: 'parent-value',
      values: [
        {
          key: 'child1',
          label: 'Child 1',
          value: 'child1-value',
        },
        {
          key: 'child2',
          label: 'Child 2',
          value: 'child2-value',
        },
      ],
    };

    // Act
    const result = checkboxOptionMapping(option);

    // Assert
    expect(result).toEqual({
      key: 'parent',
      label: 'Parent Option',
      value: 'parent-value',
      path: ['parent'],
      values: [
        {
          key: 'child1',
          label: 'Child 1',
          value: 'child1-value',
          path: ['parent', 'child1'],
        },
        {
          key: 'child2',
          label: 'Child 2',
          value: 'child2-value',
          path: ['parent', 'child2'],
        },
      ],
    });
  });

  it('should handle options with undefined values array', () => {
    // Arrange
    const option: Option = {
      key: 'leaf',
      label: 'Leaf Option',
      value: 'leaf-value',
      values: undefined,
    };

    // Act
    const result = checkboxOptionMapping(option);

    // Assert
    expect(result).toEqual({
      key: 'leaf',
      label: 'Leaf Option',
      value: 'leaf-value',
      path: ['leaf'],
      values: undefined,
    });
    expect(result.values).toBeUndefined();
  });

  it('should handle options with empty values array', () => {
    // Arrange
    const option: Option = {
      key: 'empty-parent',
      label: 'Empty Parent',
      value: 'empty-parent-value',
      values: [],
    };

    // Act
    const result = checkboxOptionMapping(option);

    // Assert
    expect(result).toEqual({
      key: 'empty-parent',
      label: 'Empty Parent',
      value: 'empty-parent-value',
      path: ['empty-parent'],
      values: [],
    });
  });

  it('should call schema parse with correct data', () => {
    // Arrange
    const option: Option = {
      key: 'test',
      label: 'Test',
      value: 'test-value',
    };

    // Act
    checkboxOptionMapping(option);

    // Assert
    expect(mockSchemaParser).toHaveBeenCalledWith({
      path: ['test'],
      key: 'test',
      label: 'Test',
      value: 'test-value',
    });
  });

  it('should preserve path immutability when mapping nested options', () => {
    // Arrange
    const option: Option = {
      key: 'parent',
      label: 'Parent',
      value: 'parent-value',
      values: [
        {
          key: 'child',
          label: 'Child',
          value: 'child-value',
        },
      ],
    };
    const initialPath = ['root'];

    // Act
    checkboxOptionMapping(option, initialPath);

    // Assert
    expect(initialPath).toEqual(['root']); // Original path should not be modified
  });
});
