import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component, DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { TextareaComponent } from './textarea';

@Component({
  template: `
    <ccl-textarea 
      [placeholder]="placeholder"
      [disabled]="disabled"
      [readonly]="readonly"
      [error]="error"
      [errorMessage]="errorMessage"
      [helperText]="helperText"
      [rows]="rows"
      [cols]="cols"
      [maxLength]="maxLength"
      [minLength]="minLength"
      [resize]="resize"
      (valueChange)="onValueChange($event)">
    </ccl-textarea>
  `,
  standalone: true,
  imports: [TextareaComponent]
})
class TestHostComponent {
  placeholder = '';
  disabled = false;
  readonly = false;
  error = false;
  errorMessage = '';
  helperText = '';
  rows = 4;
  cols?: number;
  maxLength?: number;
  minLength?: number;
  resize: 'none' | 'both' | 'horizontal' | 'vertical' = 'vertical';
  
  value = '';
  
  onValueChange(value: string): void {
    this.value = value;
  }
}

describe('TextareaComponent', () => {
  let component: TextareaComponent;
  let fixture: ComponentFixture<TextareaComponent>;
  let hostComponent: TestHostComponent;
  let hostFixture: ComponentFixture<TestHostComponent>;

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

    fixture = TestBed.createComponent(TextareaComponent);
    component = fixture.componentInstance;
    
    hostFixture = TestBed.createComponent(TestHostComponent);
    hostComponent = hostFixture.componentInstance;
    
    fixture.detectChanges();
    hostFixture.detectChanges();
  });

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

  describe('Input Properties', () => {
    it('should have default values', () => {
      expect(component.placeholder).toBe('');
      expect(component.disabled).toBe(false);
      expect(component.readonly).toBe(false);
      expect(component.error).toBe(false);
      expect(component.errorMessage).toBe('');
      expect(component.helperText).toBe('');
      expect(component.rows).toBe(4);
      expect(component.cols).toBeUndefined();
      expect(component.maxLength).toBeUndefined();
      expect(component.minLength).toBeUndefined();
      expect(component.resize).toBe('vertical');
    });

    it('should accept placeholder input', () => {
      component.placeholder = 'Enter your message';
      fixture.detectChanges();
      expect(component.placeholder).toBe('Enter your message');
    });

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

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

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

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

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

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

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

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

    it('should accept errorMessage input', () => {
      component.errorMessage = 'Message is too short';
      fixture.detectChanges();
      expect(component.errorMessage).toBe('Message is too short');
    });

    it('should accept helperText input', () => {
      component.helperText = 'Maximum 500 characters';
      fixture.detectChanges();
      expect(component.helperText).toBe('Maximum 500 characters');
    });
  });

  describe('ID Generation', () => {
    it('should generate unique ID', () => {
      expect(component.id).toMatch(/^ccl-textarea-/);
      expect(component.id.length).toBeGreaterThan(12);
    });

    it('should have different IDs for different instances', () => {
      const fixture2 = TestBed.createComponent(TextareaComponent);
      const component2 = fixture2.componentInstance;
      expect(component.id).not.toBe(component2.id);
    });
  });

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

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

    it('should set placeholder', () => {
      component.placeholder = 'Enter your message';
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.placeholder).toBe('Enter your message');
    });

    it('should set rows', () => {
      component.rows = 6;
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.rows).toBe(6);
    });

    it('should set cols when provided', () => {
      component.cols = 50;
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.cols).toBe(50);
    });

    it('should set maxlength when provided', () => {
      component.maxLength = 500;
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.maxLength).toBe(500);
    });

    it('should set minlength when provided', () => {
      component.minLength = 10;
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.minLength).toBe(10);
    });

    it('should render helper text when provided', () => {
      component.helperText = 'Maximum 500 characters';
      fixture.detectChanges();
      const helper = fixture.debugElement.query(By.css('.ccl-textarea__helper'));
      expect(helper.nativeElement.textContent).toContain('Maximum 500 characters');
    });

    it('should not render helper text when not provided', () => {
      component.helperText = '';
      fixture.detectChanges();
      const helper = fixture.debugElement.query(By.css('.ccl-textarea__helper'));
      expect(helper).toBeNull();
    });

    it('should render error message when provided', () => {
      component.error = true;
      component.errorMessage = 'Message is too short';
      fixture.detectChanges();
      const error = fixture.debugElement.query(By.css('.ccl-textarea__error'));
      expect(error.nativeElement.textContent).toContain('Message is too short');
    });

    it('should not render error message when error is false', () => {
      component.error = false;
      component.errorMessage = 'Message is too short';
      fixture.detectChanges();
      const error = fixture.debugElement.query(By.css('.ccl-textarea__error'));
      expect(error).toBeNull();
    });
  });

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

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

  describe('Readonly State', () => {
    it('should set readonly when readonly=true', () => {
      component.readonly = true;
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.readOnly).toBeTrue();
    });

    it('should not set readonly when readonly=false', () => {
      component.readonly = false;
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.readOnly).toBeFalse();
    });
  });

  describe('Error State', () => {
    it('should set aria-invalid when error=true', () => {
      component.error = true;
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.getAttribute('aria-invalid')).toBe('true');
    });

    it('should not set aria-invalid when error=false', () => {
      component.error = false;
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.getAttribute('aria-invalid')).toBe('false');
    });
  });

  describe('Resize Behavior', () => {
    it('should set resize style to none', () => {
      component.resize = 'none';
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.style.resize).toBe('none');
    });

    it('should set resize style to both', () => {
      component.resize = 'both';
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.style.resize).toBe('both');
    });

    it('should set resize style to horizontal', () => {
      component.resize = 'horizontal';
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.style.resize).toBe('horizontal');
    });

    it('should set resize style to vertical', () => {
      component.resize = 'vertical';
      fixture.detectChanges();
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.style.resize).toBe('vertical');
    });
  });

  describe('Value Change', () => {
    it('should emit value change on input', () => {
      spyOn(component.valueChange, 'emit');
      fixture.detectChanges();
      
      const textarea = fixture.debugElement.query(By.css('textarea'));
      textarea.nativeElement.value = 'Hello world';
      textarea.nativeElement.dispatchEvent(new Event('input'));
      
      expect(component.valueChange.emit).toHaveBeenCalledWith('Hello world');
    });

    it('should update internal value on input', () => {
      fixture.detectChanges();
      
      const textarea = fixture.debugElement.query(By.css('textarea'));
      textarea.nativeElement.value = 'Hello world';
      textarea.nativeElement.dispatchEvent(new Event('input'));
      
      expect(component.value).toBe('Hello world');
    });
  });

  describe('Accessibility', () => {
    it('should have proper ARIA attributes', () => {
      component.error = true;
      component.helperText = 'Helper text';
      fixture.detectChanges();
      
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.getAttribute('aria-invalid')).toBe('true');
      expect(textarea.nativeElement.getAttribute('aria-describedby')).toContain('help');
    });

    it('should associate helper text with textarea', () => {
      component.helperText = 'Maximum 500 characters';
      fixture.detectChanges();
      
      const textarea = fixture.debugElement.query(By.css('textarea'));
      const helper = fixture.debugElement.query(By.css('.ccl-textarea__helper'));
      expect(textarea.nativeElement.getAttribute('aria-describedby')).toBe(helper.nativeElement.id);
    });
  });

  describe('Length Constraints', () => {
    it('should handle maxLength constraint', () => {
      component.maxLength = 100;
      fixture.detectChanges();
      
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.maxLength).toBe(100);
    });

    it('should handle minLength constraint', () => {
      component.minLength = 10;
      fixture.detectChanges();
      
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.minLength).toBe(10);
    });

    it('should not set maxLength when not provided', () => {
      component.maxLength = undefined;
      fixture.detectChanges();
      
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.maxLength).toBe(-1); // Default HTML value
    });

    it('should not set minLength when not provided', () => {
      component.minLength = undefined;
      fixture.detectChanges();
      
      const textarea = fixture.debugElement.query(By.css('textarea'));
      expect(textarea.nativeElement.minLength).toBe(-1); // Default HTML value
    });
  });
});


