import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ButtonComponent } from './button';
import { By } from '@angular/platform-browser';

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

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [ButtonComponent]
    }).compileComponents();

    fixture = TestBed.createComponent(ButtonComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

  describe('Input Properties', () => {
    it('should have default values', () => {
      expect(component.variant).toBe('primary');
      expect(component.size).toBe('md');
      expect(component.disabled).toBe(false);
      expect(component.loading).toBe(false);
    });

    it('should accept variant input', () => {
      component.variant = 'secondary';
      fixture.detectChanges();
      expect(component.variant).toBe('secondary');
    });

    it('should accept size input', () => {
      component.size = 'lg';
      fixture.detectChanges();
      expect(component.size).toBe('lg');
    });

    it('should accept disabled input', () => {
      component.disabled = true;
      fixture.detectChanges();
      expect(component.disabled).toBe(true);
    });

    it('should accept loading input', () => {
      component.loading = true;
      fixture.detectChanges();
      expect(component.loading).toBe(true);
    });
  });

  describe('Template Rendering', () => {
    it('should render projected content', () => {
      fixture.nativeElement.innerHTML = `<ccl-button>Click Me</ccl-button>`;
      fixture.detectChanges();
      expect(fixture.nativeElement.textContent).toContain('Click Me');
    });

    it('should render button element', () => {
      const button = fixture.debugElement.query(By.css('button'));
      expect(button).toBeTruthy();
    });

    it('should apply base CSS class', () => {
      const button = fixture.debugElement.query(By.css('button'));
      expect(button.nativeElement.classList).toContain('ccl-btn');
    });
  });

  describe('Variant Classes', () => {
    it('should apply primary variant by default', () => {
      const button = fixture.debugElement.query(By.css('button'));
      expect(button.nativeElement.classList).toContain('ccl-btn--primary');
    });

    it('should apply secondary variant when set', () => {
      component.variant = 'secondary';
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button'));
      expect(button.nativeElement.classList).toContain('ccl-btn--secondary');
    });

    it('should apply tertiary variant when set', () => {
      component.variant = 'tertiary';
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button'));
      expect(button.nativeElement.classList).toContain('ccl-btn--tertiary');
    });

    it('should apply destructive variant when set', () => {
      component.variant = 'destructive';
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button'));
      expect(button.nativeElement.classList).toContain('ccl-btn--destructive');
    });
  });

  describe('Size Classes', () => {
    it('should apply medium size by default', () => {
      const button = fixture.debugElement.query(By.css('button'));
      expect(button.nativeElement.classList).toContain('ccl-btn--md');
    });

    it('should apply small size when size="sm"', () => {
      component.size = 'sm';
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button'));
      expect(button.nativeElement.classList).toContain('ccl-btn--sm');
    });

    it('should apply large size when size="lg"', () => {
      component.size = 'lg';
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button'));
      expect(button.nativeElement.classList).toContain('ccl-btn--lg');
    });
  });

  describe('Disabled State', () => {
    it('should disable the button when disabled=true', () => {
      component.disabled = true;
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button')).nativeElement;
      expect(button.disabled).toBeTrue();
    });

    it('should not disable the button when disabled=false', () => {
      component.disabled = false;
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button')).nativeElement;
      expect(button.disabled).toBeFalse();
    });

    it('should apply disabled CSS class when disabled=true', () => {
      component.disabled = true;
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button'));
      // The button doesn't have a disabled CSS class, it just has the disabled attribute
      expect(button.nativeElement.disabled).toBeTrue();
    });
  });

  describe('Loading State', () => {
    it('should show loading spinner when loading=true', () => {
      component.loading = true;
      fixture.detectChanges();
      const spinner = fixture.debugElement.query(By.css('.spinner'));
      expect(spinner).toBeTruthy();
    });

    it('should not show loading spinner when loading=false', () => {
      component.loading = false;
      fixture.detectChanges();
      const spinner = fixture.debugElement.query(By.css('.spinner'));
      expect(spinner).toBeNull();
    });

    it('should disable button when loading=true', () => {
      component.loading = true;
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button')).nativeElement;
      expect(button.disabled).toBeTrue();
    });

    it('should apply loading CSS class when loading=true', () => {
      component.loading = true;
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button'));
      expect(button.nativeElement.classList).toContain('ccl-btn--loading');
    });
  });

  describe('Accessibility', () => {
    it('should have button role', () => {
      const button = fixture.debugElement.query(By.css('button'));
      // Native button elements don't need explicit role attribute
      expect(button.nativeElement.tagName).toBe('BUTTON');
    });

    it('should be focusable when not disabled', () => {
      component.disabled = false;
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button')).nativeElement;
      expect(button.disabled).toBeFalse();
    });

    it('should not be focusable when disabled', () => {
      component.disabled = true;
      fixture.detectChanges();
      const button = fixture.debugElement.query(By.css('button')).nativeElement;
      expect(button.disabled).toBeTrue();
    });
  });
});
