import {
  createDirectiveFactory,
  SpectatorDirective,
} from '@ngneat/spectator/jest';
import { ChecklistValueDirective } from './checklist-value.directive';

describe('ChecklistValueDirective', () => {
  let spectator: SpectatorDirective<
    ChecklistValueDirective,
    { value: unknown }
  >;
  const createDirective = createDirectiveFactory({
    directive: ChecklistValueDirective,
    template: `<input type="checkbox" [uiChecklistValue]="value" />`,
  });

  beforeEach(() => {
    // Pass the template here as required by Spectator
    spectator = createDirective();
  });

  it('should create', () => {
    expect(spectator.directive).toBeTruthy();
  });

  it('should set initial value from input', () => {
    // Arrange
    spectator.setHostInput('value', 'test-value');
    spectator.detectChanges();
    // Assert
    expect(spectator.directive.uiChecklistValue()).toEqual('test-value');
  });

  it('should set checked model to false by default', () => {
    // Arrange & Assert
    expect(spectator.directive.checked()).toBe(false);
  });

  it('should update checked state when changed', () => {
    // Arrange
    const checkbox = spectator.query('input') as HTMLInputElement;

    // Act
    checkbox.checked = true;
    spectator.dispatchFakeEvent(checkbox, 'change');

    // Assert
    expect(spectator.directive.checked()).toBe(true);
  });

  it('should handle the change event correctly', () => {
    // Arrange
    const checkbox = spectator.query('input') as HTMLInputElement;
    const changeSpy = jest.spyOn(spectator.directive, 'onChange');
    const checkedSetSpy = jest.spyOn(spectator.directive.checked, 'set');

    // Act
    checkbox.checked = true;
    spectator.dispatchFakeEvent(checkbox, 'change');

    // Assert
    expect(changeSpy).toHaveBeenCalled();
    expect(checkedSetSpy).toHaveBeenCalledWith(true);
  });

  it('should handle different value types', () => {
    // Arrange
    const numberValue = 123;
    const objectValue = { id: 1, name: 'test' };

    // Act - Test with number
    spectator.setHostInput('value', numberValue);
    spectator.detectChanges();

    // Assert - Number value
    expect(spectator.directive.uiChecklistValue()).toEqual(numberValue);

    // Act - Test with object
    spectator.setHostInput('value', objectValue);
    spectator.detectChanges();

    // Assert - Object value
    expect(spectator.directive.uiChecklistValue()).toEqual(objectValue);
  });
});
