import { getAllCheckboxOptionsHelper } from './get-all-checkbox-options.helper';
import { CheckboxFilterInput, CheckboxFilterInputOption } from '../core';
import { InputType } from '../types';

describe('getAllCheckboxOptionsHelper', () => {
  const createCheckboxOption = (
    key: string,
    label: string,
    path: string[],
    values?: CheckboxFilterInputOption[],
  ): CheckboxFilterInputOption => ({
    path,
    key,
    label,
    values,
  });

  const mockOptions: CheckboxFilterInputOption[] = [
    createCheckboxOption(
      'electronics',
      'Electronics',
      ['category', 'electronics'],
      [
        createCheckboxOption('laptops', 'Laptops', [
          'category',
          'electronics',
          'laptops',
        ]),
        createCheckboxOption(
          'phones',
          'Mobile Phones',
          ['category', 'electronics', 'phones'],
          [
            createCheckboxOption('smartphone', 'Smartphones', [
              'category',
              'electronics',
              'phones',
              'smartphone',
            ]),
            createCheckboxOption('feature', 'Feature Phones', [
              'category',
              'electronics',
              'phones',
              'feature',
            ]),
          ],
        ),
      ],
    ),
    createCheckboxOption(
      'clothing',
      'Clothing',
      ['category', 'clothing'],
      [
        createCheckboxOption('shirts', 'Shirts', [
          'category',
          'clothing',
          'shirts',
        ]),
        createCheckboxOption('pants', 'Pants', [
          'category',
          'clothing',
          'pants',
        ]),
      ],
    ),
    createCheckboxOption('books', 'Books', ['category', 'books']),
  ];

  const createMockInput = (
    options: CheckboxFilterInputOption[],
  ): CheckboxFilterInput => ({
    group: 'category',
    key: 'test-checkbox',
    label: 'Test Checkbox',
    type: InputType.Checkbox,
    target: 'input',
    options,
    selected: [],
  });

  it('should return all options in a flat array', () => {
    // Arrange
    const mockInput = createMockInput(mockOptions);

    // Act
    const result = getAllCheckboxOptionsHelper(mockInput);

    // Assert
    expect(result).toHaveLength(9); // 3 top-level + 2 electronics children + 2 phones children + 2 clothing children + 1 books
    expect(result.map((option) => option.key)).toEqual([
      'electronics',
      'laptops',
      'phones',
      'smartphone',
      'feature',
      'clothing',
      'shirts',
      'pants',
      'books',
    ]);
  });

  it('should handle options without children', () => {
    // Arrange
    const simpleOptions = [
      createCheckboxOption('option1', 'Option 1', ['simple', 'option1']),
      createCheckboxOption('option2', 'Option 2', ['simple', 'option2']),
    ];
    const mockInput = createMockInput(simpleOptions);

    // Act
    const result = getAllCheckboxOptionsHelper(mockInput);

    // Assert
    expect(result).toHaveLength(2);
    expect(result.map((option) => option.key)).toEqual(['option1', 'option2']);
  });

  it('should handle empty options array', () => {
    // Arrange
    const mockInput = createMockInput([]);

    // Act
    const result = getAllCheckboxOptionsHelper(mockInput);

    // Assert
    expect(result).toEqual([]);
  });

  it('should preserve option order in flattening', () => {
    // Arrange
    const orderedOptions = [
      createCheckboxOption(
        'first',
        'First',
        ['first'],
        [createCheckboxOption('child1', 'Child 1', ['first', 'child1'])],
      ),
      createCheckboxOption('second', 'Second', ['second']),
      createCheckboxOption(
        'third',
        'Third',
        ['third'],
        [createCheckboxOption('child2', 'Child 2', ['third', 'child2'])],
      ),
    ];
    const mockInput = createMockInput(orderedOptions);

    // Act
    const result = getAllCheckboxOptionsHelper(mockInput);

    // Assert
    expect(result.map((option) => option.key)).toEqual([
      'first',
      'child1',
      'second',
      'third',
      'child2',
    ]);
  });

  it('should handle deeply nested options', () => {
    // Arrange
    const deeplyNestedOptions = [
      createCheckboxOption(
        'level1',
        'Level 1',
        ['level1'],
        [
          createCheckboxOption(
            'level2',
            'Level 2',
            ['level1', 'level2'],
            [
              createCheckboxOption(
                'level3',
                'Level 3',
                ['level1', 'level2', 'level3'],
                [
                  createCheckboxOption('level4', 'Level 4', [
                    'level1',
                    'level2',
                    'level3',
                    'level4',
                  ]),
                ],
              ),
            ],
          ),
        ],
      ),
    ];
    const mockInput = createMockInput(deeplyNestedOptions);

    // Act
    const result = getAllCheckboxOptionsHelper(mockInput);

    // Assert
    expect(result).toHaveLength(4);
    expect(result.map((option) => option.key)).toEqual([
      'level1',
      'level2',
      'level3',
      'level4',
    ]);
  });

  it('should handle input with undefined options', () => {
    // Arrange
    const mockInput: CheckboxFilterInput = {
      group: 'test',
      key: 'test-checkbox',
      label: 'Test Checkbox',
      type: InputType.Checkbox,
      target: 'input',
      options: undefined as unknown as CheckboxFilterInputOption[], // Simulating potential undefined scenario
      selected: [],
    };

    // Act
    const result = getAllCheckboxOptionsHelper(mockInput);

    // Assert
    expect(result).toEqual([]);
  });
});
