import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SwitchComponent } from './switch.component';
import { provideIcons } from '@ng-icons/core';
import { isaNavigationDashboard } from '@isa/icons';

describe('SwitchComponent', () => {
  let component: SwitchComponent;
  let fixture: ComponentFixture<SwitchComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [SwitchComponent],
      providers: [provideIcons({ isaNavigationDashboard })],
    }).compileComponents();

    fixture = TestBed.createComponent(SwitchComponent);
    component = fixture.componentInstance;
  });

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

  describe('initial state', () => {
    it('should have default values', () => {
      fixture.componentRef.setInput('icon', 'isaNavigationDashboard');
      fixture.detectChanges();

      expect(component.checked()).toBe(false);
      expect(component.color()).toBe('primary');
      expect(component.disabled()).toBe(false);
    });

    it('should render with unchecked state', () => {
      fixture.componentRef.setInput('icon', 'isaNavigationDashboard');
      fixture.detectChanges();

      const track = fixture.nativeElement.querySelector('.ui-switch__track');
      expect(track).toBeTruthy();
      expect(track.classList.contains('ui-switch__track--checked')).toBe(false);
    });
  });

  describe('checked state', () => {
    it('should update when checked input changes', () => {
      fixture.componentRef.setInput('icon', 'isaNavigationDashboard');
      fixture.componentRef.setInput('checked', true);
      fixture.detectChanges();

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

    it('should apply checked class to track', () => {
      fixture.componentRef.setInput('icon', 'isaNavigationDashboard');
      fixture.componentRef.setInput('checked', true);
      fixture.detectChanges();

      const track = fixture.nativeElement.querySelector('.ui-switch__track');
      expect(track.classList.contains('ui-switch__track--checked')).toBe(true);
    });

    it('should apply checked class to thumb', () => {
      fixture.componentRef.setInput('icon', 'isaNavigationDashboard');
      fixture.componentRef.setInput('checked', true);
      fixture.detectChanges();

      const thumb = fixture.nativeElement.querySelector('.ui-switch__thumb');
      expect(thumb.classList.contains('ui-switch__thumb--checked')).toBe(true);
    });
  });

  describe('toggle functionality', () => {
    beforeEach(() => {
      fixture.componentRef.setInput('icon', 'isaNavigationDashboard');
      fixture.detectChanges();
    });

    it('should toggle checked state on click', () => {
      expect(component.checked()).toBe(false);

      fixture.nativeElement.click();
      fixture.detectChanges();

      expect(component.checked()).toBe(true);

      fixture.nativeElement.click();
      fixture.detectChanges();

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

    it('should toggle on Enter key', () => {
      expect(component.checked()).toBe(false);

      const event = new KeyboardEvent('keydown', { key: 'Enter' });
      fixture.nativeElement.dispatchEvent(event);
      fixture.detectChanges();

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

    it('should toggle on Space key', () => {
      expect(component.checked()).toBe(false);

      const event = new KeyboardEvent('keydown', { key: ' ' });
      fixture.nativeElement.dispatchEvent(event);
      fixture.detectChanges();

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

  describe('disabled state', () => {
    beforeEach(() => {
      fixture.componentRef.setInput('icon', 'isaNavigationDashboard');
      fixture.componentRef.setInput('disabled', true);
      fixture.detectChanges();
    });

    it('should not toggle when disabled and clicked', () => {
      expect(component.checked()).toBe(false);

      fixture.nativeElement.click();
      fixture.detectChanges();

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

    it('should apply disabled class', () => {
      expect(fixture.nativeElement.classList.contains('disabled')).toBe(true);
    });

    it('should have aria-disabled attribute', () => {
      expect(fixture.nativeElement.getAttribute('aria-disabled')).toBe('true');
    });
  });

  describe('accessibility', () => {
    beforeEach(() => {
      fixture.componentRef.setInput('icon', 'isaNavigationDashboard');
      fixture.detectChanges();
    });

    it('should have role="switch"', () => {
      expect(fixture.nativeElement.getAttribute('role')).toBe('switch');
    });

    it('should have correct aria-checked when unchecked', () => {
      expect(fixture.nativeElement.getAttribute('aria-checked')).toBe('false');
    });

    it('should have correct aria-checked when checked', () => {
      fixture.componentRef.setInput('checked', true);
      fixture.detectChanges();

      expect(fixture.nativeElement.getAttribute('aria-checked')).toBe('true');
    });

    it('should be keyboard focusable', () => {
      expect(fixture.nativeElement.getAttribute('tabindex')).toBe('0');
    });

    it('should support custom tabindex', () => {
      fixture.componentRef.setInput('tabIndex', 5);
      fixture.detectChanges();

      expect(fixture.nativeElement.getAttribute('tabindex')).toBe('5');
    });
  });

  describe('color theme', () => {
    beforeEach(() => {
      fixture.componentRef.setInput('icon', 'isaNavigationDashboard');
      fixture.detectChanges();
    });

    it('should apply primary color class by default', () => {
      expect(
        fixture.nativeElement.classList.contains('ui-switch__primary'),
      ).toBe(true);
    });

    it('should apply correct color class', () => {
      fixture.componentRef.setInput('color', 'primary');
      fixture.detectChanges();

      expect(
        fixture.nativeElement.classList.contains('ui-switch__primary'),
      ).toBe(true);
    });
  });

  describe('icon rendering', () => {
    it('should render the provided icon', () => {
      fixture.componentRef.setInput('icon', 'isaNavigationDashboard');
      fixture.detectChanges();

      const icon = fixture.nativeElement.querySelector('ng-icon');
      expect(icon).toBeTruthy();
    });
  });
});
