import { ComponentFixture, TestBed } from '@angular/core/testing';
import { QuantityControlOptionComponent } from './quantity-control-option.component';
import { QuantityControlComponent } from './quantity-control.component';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { signal } from '@angular/core';

describe('QuantityControlOptionComponent', () => {
  let component: QuantityControlOptionComponent;
  let fixture: ComponentFixture<QuantityControlOptionComponent>;
  let mockParent: Partial<QuantityControlComponent>;

  beforeEach(async () => {
    // Create a mock parent component with only the necessary properties
    mockParent = {
      value: signal(1),
      selectValue: vi.fn(),
      enterEditMode: vi.fn(),
    };

    await TestBed.configureTestingModule({
      imports: [QuantityControlOptionComponent],
      providers: [
        { provide: QuantityControlComponent, useValue: mockParent },
      ],
    }).compileComponents();

    fixture = TestBed.createComponent(QuantityControlOptionComponent);
    component = fixture.componentInstance;

    // Set required inputs
    fixture.componentRef.setInput('id', 'option-1');
    fixture.componentRef.setInput('value', 1);
    fixture.detectChanges();
  });

  describe('Component Creation', () => {
    it('should create', () => {
      expect(component).toBeTruthy();
    });

    it('should have id input', () => {
      expect(component.id()).toBe('option-1');
    });

    it('should have value input', () => {
      expect(component.value()).toBe(1);
    });

    it('should not be active by default', () => {
      expect(component.active()).toBe(false);
    });

    it('should not be disabled by default', () => {
      expect(component.disabled).toBeUndefined();
    });
  });

  describe('Selected State', () => {
    it('should be selected when value matches parent value', () => {
      mockParent.value!.set(1);

      expect(component.selected()).toBe(true);
    });

    it('should not be selected when value does not match parent value', () => {
      mockParent.value!.set(5);

      expect(component.selected()).toBe(false);
    });

    it('should never be selected for edit option', () => {
      fixture.componentRef.setInput('value', 'edit');
      mockParent.value!.set(1);
      fixture.detectChanges();

      expect(component.selected()).toBe(false);
    });
  });

  describe('Active State', () => {
    it('should set active state when setActiveStyles is called', () => {
      component.setActiveStyles();

      expect(component.active()).toBe(true);
    });

    it('should set inactive state when setInactiveStyles is called', () => {
      component.active.set(true);

      component.setInactiveStyles();

      expect(component.active()).toBe(false);
    });
  });

  describe('CSS Classes', () => {
    it('should return "active" class when active', () => {
      component.active.set(true);

      expect(component.activeClass()).toBe('active');
    });

    it('should return empty string when not active', () => {
      component.active.set(false);

      expect(component.activeClass()).toBe('');
    });

    it('should return "selected" class when selected', () => {
      mockParent.value!.set(1);

      expect(component.selectedClass()).toBe('selected');
    });

    it('should return empty string when not selected', () => {
      mockParent.value!.set(5);

      expect(component.selectedClass()).toBe('');
    });

    it('should return "disabled" class when disabled property is truthy', () => {
      // Create a fresh component instance to test the computed logic
      const testFixture = TestBed.createComponent(QuantityControlOptionComponent);
      const testComponent = testFixture.componentInstance;
      testFixture.componentRef.setInput('id', 'test');
      testFixture.componentRef.setInput('value', 1);
      testComponent.disabled = true;
      testFixture.detectChanges();

      expect(testComponent.disabledClass()).toBe('disabled');
    });

    it('should return empty string when disabled is falsy', () => {
      // Component is created with disabled undefined by default
      expect(component.disabledClass()).toBe('');
    });
  });

  describe('Selection Behavior', () => {
    it('should call parent selectValue when selecting a number option', () => {
      component.select();

      expect(mockParent.selectValue).toHaveBeenCalledWith(1);
    });

    it('should call parent enterEditMode when selecting edit option', () => {
      fixture.componentRef.setInput('value', 'edit');
      fixture.detectChanges();

      component.select();

      expect(mockParent.enterEditMode).toHaveBeenCalled();
    });

    it('should not select when disabled', () => {
      component.disabled = true;

      component.select();

      expect(mockParent.selectValue).not.toHaveBeenCalled();
    });
  });

  describe('Different Value Types', () => {
    it('should handle numeric values', () => {
      fixture.componentRef.setInput('value', 5);
      fixture.detectChanges();

      expect(component.value()).toBe(5);
    });

    it('should handle edit value', () => {
      fixture.componentRef.setInput('value', 'edit');
      fixture.detectChanges();

      expect(component.value()).toBe('edit');
    });

    it('should handle zero value', () => {
      fixture.componentRef.setInput('value', 0);
      fixture.detectChanges();

      expect(component.value()).toBe(0);
    });
  });

  describe('Element Reference', () => {
    it('should have element reference', () => {
      expect(component.elementRef).toBeDefined();
      expect(component.elementRef.nativeElement).toBeDefined();
    });
  });

  describe('Highlightable Interface', () => {
    it('should implement Highlightable interface', () => {
      expect(component.setActiveStyles).toBeDefined();
      expect(component.setInactiveStyles).toBeDefined();
    });

    it('should toggle highlighting correctly', () => {
      component.setActiveStyles();
      expect(component.active()).toBe(true);

      component.setInactiveStyles();
      expect(component.active()).toBe(false);
    });
  });
});
