import { checkboxSelectedHelper, checkboxSelectedHelperBoolean } from './checkbox-selected.helper';
import { FilterInput, CheckboxFilterInput, CheckboxFilterInputOption } from '../core';
import { InputType } from '../types';

describe('checkboxSelectedHelper', () => {
  const baseInput: CheckboxFilterInput = {
    group: 'group',
    key: 'key',
    type: InputType.Checkbox,
    options: [],
    selected: [],
    label: 'label',
    target: 'input',
  };

  it('should return "none" if input not found', () => {
    const option: CheckboxFilterInputOption = {
      path: ['group', 'key', 'opt'],
      key: 'opt',
      label: 'Option',
      value: 'opt',
    };
    expect(checkboxSelectedHelper([], option)).toBe('none');
  });

  it('should return "none" when input type is not checkbox', () => {
    const option: CheckboxFilterInputOption = {
      path: ['group', 'key', 'opt'],
      key: 'opt',
      label: 'Option',
      value: 'opt',
    };
    const input: FilterInput = {
      group: 'group',
      key: 'key',
      type: InputType.Text,
      value: 'test',
      target: 'input',
    };
    expect(checkboxSelectedHelper([input], option)).toBe('none');
  });

  it('should return "checked" for leaf if selected', () => {
    const input: CheckboxFilterInput = {
      ...baseInput,
      selected: ['opt'],
      options: [
        { path: ['group', 'key', 'opt'], key: 'opt', label: 'Option', value: 'opt' },
      ],
    };
    const option = input.options[0];
    expect(checkboxSelectedHelper([input], option)).toBe('checked');
  });

  it('should return "none" for leaf if not selected', () => {
    const input: CheckboxFilterInput = {
      ...baseInput,
      selected: [],
      options: [
        { path: ['group', 'key', 'opt'], key: 'opt', label: 'Option', value: 'opt' },
      ],
    };
    const option = input.options[0];
    expect(checkboxSelectedHelper([input], option)).toBe('none');
  });

  it('should return "checked" for parent if all children selected', () => {
    const input: CheckboxFilterInput = {
      ...baseInput,
      selected: ['parent.child1', 'parent.child2'],
      options: [
        {
          path: ['group', 'key', 'parent'],
          key: 'parent',
          label: 'Parent',
          values: [
            { path: ['group', 'key', 'parent', 'child1'], key: 'child1', label: 'Child1', value: 'child1' },
            { path: ['group', 'key', 'parent', 'child2'], key: 'child2', label: 'Child2', value: 'child2' },
          ],
        },
      ],
    };
    const option = input.options[0];
    expect(checkboxSelectedHelper([input], option)).toBe('checked');
  });

  it('should return "indeterminate" for parent if some children selected', () => {
    const input: CheckboxFilterInput = {
      ...baseInput,
      selected: ['parent.child1'],
      options: [
        {
          path: ['group', 'key', 'parent'],
          key: 'parent',
          label: 'Parent',
          values: [
            { path: ['group', 'key', 'parent', 'child1'], key: 'child1', label: 'Child1', value: 'child1' },
            { path: ['group', 'key', 'parent', 'child2'], key: 'child2', label: 'Child2', value: 'child2' },
          ],
        },
      ],
    };
    const option = input.options[0];
    expect(checkboxSelectedHelper([input], option)).toBe('indeterminate');
  });

  it('should return "none" for parent if no children selected', () => {
    const input: CheckboxFilterInput = {
      ...baseInput,
      selected: [],
      options: [
        {
          path: ['group', 'key', 'parent'],
          key: 'parent',
          label: 'Parent',
          values: [
            { path: ['group', 'key', 'parent', 'child1'], key: 'child1', label: 'Child1', value: 'child1' },
            { path: ['group', 'key', 'parent', 'child2'], key: 'child2', label: 'Child2', value: 'child2' },
          ],
        },
      ],
    };
    const option = input.options[0];
    expect(checkboxSelectedHelper([input], option)).toBe('none');
  });

  describe('multi-level hierarchies', () => {
    it('should handle 2-level deep hierarchies', () => {
      const input: CheckboxFilterInput = {
        ...baseInput,
        selected: ['parent.child1', 'parent.child2'],
        options: [
          {
            path: ['group', 'key', 'parent'],
            key: 'parent',
            label: 'Parent',
            values: [
              { path: ['group', 'key', 'parent', 'child1'], key: 'child1', label: 'Child1', value: 'gc1' },
              { path: ['group', 'key', 'parent', 'child2'], key: 'child2', label: 'Child2', value: 'gc2' },
            ],
          },
        ],
      };
      
      const parentOption = input.options[0];
      const childOption = parentOption.values![0];
      
      expect(checkboxSelectedHelper([input], parentOption)).toBe('checked');
      expect(checkboxSelectedHelper([input], childOption)).toBe('checked');
    });

    it('should handle indeterminate state in hierarchies', () => {
      const input: CheckboxFilterInput = {
        ...baseInput,
        selected: ['parent.child1'],
        options: [
          {
            path: ['group', 'key', 'parent'],
            key: 'parent',
            label: 'Parent',
            values: [
              { path: ['group', 'key', 'parent', 'child1'], key: 'child1', label: 'Child1', value: 'gc1' },
              { path: ['group', 'key', 'parent', 'child2'], key: 'child2', label: 'Child2', value: 'gc2' },
            ],
          },
        ],
      };
      
      const parentOption = input.options[0];
      
      expect(checkboxSelectedHelper([input], parentOption)).toBe('indeterminate');
    });
  });

  describe('parent selection inheritance', () => {
    it('should return "checked" for children when parent is selected', () => {
      const input: CheckboxFilterInput = {
        ...baseInput,
        selected: ['parent'],
        options: [
          {
            path: ['group', 'key', 'parent'],
            key: 'parent',
            label: 'Parent',
            values: [
              { path: ['group', 'key', 'parent', 'child1'], key: 'child1', label: 'Child1', value: 'child1' },
              { path: ['group', 'key', 'parent', 'child2'], key: 'child2', label: 'Child2', value: 'child2' },
            ],
          },
        ],
      };
      
      const parentOption = input.options[0];
      const child1 = parentOption.values![0];
      const child2 = parentOption.values![1];
      
      expect(checkboxSelectedHelper([input], parentOption)).toBe('checked');
      expect(checkboxSelectedHelper([input], child1)).toBe('checked');
      expect(checkboxSelectedHelper([input], child2)).toBe('checked');
    });

    it('should inherit selection through parent-child levels', () => {
      const input: CheckboxFilterInput = {
        ...baseInput,
        selected: ['parent'],
        options: [
          {
            path: ['group', 'key', 'parent'],
            key: 'parent',
            label: 'Parent',
            values: [
              { path: ['group', 'key', 'parent', 'child'], key: 'child', label: 'Child', value: 'gc' },
            ],
          },
        ],
      };
      
      const child = input.options[0].values![0];
      expect(checkboxSelectedHelper([input], child)).toBe('checked');
    });
  });

  describe('edge cases', () => {
    it('should handle option with empty values array', () => {
      const input: CheckboxFilterInput = {
        ...baseInput,
        selected: ['parent'],
        options: [
          {
            path: ['group', 'key', 'parent'],
            key: 'parent',
            label: 'Parent',
            values: [],
          },
        ],
      };
      
      const option = input.options[0];
      expect(checkboxSelectedHelper([input], option)).toBe('checked');
    });

    it('should handle null selected array', () => {
      const input: CheckboxFilterInput = {
        ...baseInput,
        selected: null as any,
        options: [
          { path: ['group', 'key', 'opt'], key: 'opt', label: 'Option', value: 'opt' },
        ],
      };
      
      const option = input.options[0];
      expect(checkboxSelectedHelper([input], option)).toBe('none');
    });

    it('should handle undefined selected array', () => {
      const input: CheckboxFilterInput = {
        ...baseInput,
        selected: undefined as any,
        options: [
          { path: ['group', 'key', 'opt'], key: 'opt', label: 'Option', value: 'opt' },
        ],
      };
      
      const option = input.options[0];
      expect(checkboxSelectedHelper([input], option)).toBe('none');
    });
  });
});

describe('checkboxSelectedHelperBoolean', () => {
  const baseInput: CheckboxFilterInput = {
    group: 'group',
    key: 'key',
    type: InputType.Checkbox,
    options: [],
    selected: [],
    label: 'label',
    target: 'input',
  };

  it('should return true for "checked" state', () => {
    const input: CheckboxFilterInput = {
      ...baseInput,
      selected: ['opt'],
      options: [
        { path: ['group', 'key', 'opt'], key: 'opt', label: 'Option', value: 'opt' },
      ],
    };
    const option = input.options[0];
    expect(checkboxSelectedHelperBoolean([input], option)).toBe(true);
  });

  it('should return true for "indeterminate" state', () => {
    const input: CheckboxFilterInput = {
      ...baseInput,
      selected: ['parent.child1'],
      options: [
        {
          path: ['group', 'key', 'parent'],
          key: 'parent',
          label: 'Parent',
          values: [
            { path: ['group', 'key', 'parent', 'child1'], key: 'child1', label: 'Child1', value: 'child1' },
            { path: ['group', 'key', 'parent', 'child2'], key: 'child2', label: 'Child2', value: 'child2' },
          ],
        },
      ],
    };
    const option = input.options[0];
    expect(checkboxSelectedHelperBoolean([input], option)).toBe(true);
  });

  it('should return false for "none" state', () => {
    const input: CheckboxFilterInput = {
      ...baseInput,
      selected: [],
      options: [
        { path: ['group', 'key', 'opt'], key: 'opt', label: 'Option', value: 'opt' },
      ],
    };
    const option = input.options[0];
    expect(checkboxSelectedHelperBoolean([input], option)).toBe(false);
  });
});
