import { describe, it, expect, beforeEach } from 'vitest';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { Component } from '@angular/core';
import { By } from '@angular/platform-browser';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { BulletListItemComponent } from './bullet-list-item.component';
import { BulletListComponent } from './bullet-list.component';
import { isaActionChevronRight } from '@isa/icons';

// Mock icons for testing
const testIcons = {
  isaActionChevronRight,
  customIcon: '<svg></svg>',
  ownIcon: '<svg></svg>',
  parentIcon: '<svg></svg>',
  childIcon: '<svg></svg>',
  newParentIcon: '<svg></svg>',
};

// Test host component without parent BulletListComponent
@Component({
  template: `
    <ui-bullet-list-item [icon]="testIcon">
      <span data-what="item-content">Test item content</span>
    </ui-bullet-list-item>
  `,
  standalone: true,
  imports: [BulletListItemComponent],
  providers: [provideIcons(testIcons)],
})
class TestHostComponent {
  testIcon: string | undefined = undefined;
}

// Test host component with parent BulletListComponent
@Component({
  template: `
    <ui-bullet-list [icon]="parentIcon">
      <ui-bullet-list-item [icon]="childIcon">
        <span data-what="item-content">Test item content</span>
      </ui-bullet-list-item>
    </ui-bullet-list>
  `,
  standalone: true,
  imports: [BulletListComponent, BulletListItemComponent],
})
class TestHostWithParentComponent {
  parentIcon = 'parentIcon';
  childIcon: string | undefined = undefined;
}

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

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

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

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

  it('should have undefined icon by default', () => {
    expect(component.icon()).toBeUndefined();
  });

  it('should accept custom icon input', () => {
    fixture.componentRef.setInput('icon', 'customIcon');
    fixture.detectChanges();

    expect(component.icon()).toBe('customIcon');
  });

  it('should render with correct CSS class', () => {
    const hostElement = fixture.nativeElement;
    expect(hostElement.classList.contains('ui-bullet-list-item')).toBe(true);
  });

  it('should render ng-icon with correct size', () => {
    const ngIcon = fixture.debugElement.query(By.directive(NgIcon));
    expect(ngIcon).toBeTruthy();
    expect(ngIcon.nativeElement.getAttribute('size')).toBe('1.5rem');
  });

  it('should use undefined iconName when no icon is provided and no parent exists', () => {
    expect(component.iconName()).toBeUndefined();
  });

  it('should use own icon when provided', () => {
    fixture.componentRef.setInput('icon', 'ownIcon');
    fixture.detectChanges();

    expect(component.iconName()).toBe('ownIcon');
  });

  it('should project content correctly', async () => {
    const hostFixture = TestBed.createComponent(TestHostComponent);
    hostFixture.detectChanges();

    const projectedContent = hostFixture.nativeElement.querySelector('[data-what="item-content"]');
    expect(projectedContent).toBeTruthy();
    expect(projectedContent.textContent.trim()).toBe('Test item content');
  });

  it('should inherit parent icon when no own icon is provided', async () => {
    const hostFixture = TestBed.createComponent(TestHostWithParentComponent);
    hostFixture.detectChanges();

    const bulletListItem = hostFixture.debugElement.query(
      sel => sel.componentInstance instanceof BulletListItemComponent
    ).componentInstance;

    expect(bulletListItem.iconName()).toBe('parentIcon');
  });

  it('should use own icon instead of parent icon when both are provided', async () => {
    const hostFixture = TestBed.createComponent(TestHostWithParentComponent);
    const hostComponent = hostFixture.componentInstance;
    hostComponent.childIcon = 'childIcon';
    hostFixture.detectChanges();

    const bulletListItem = hostFixture.debugElement.query(
      sel => sel.componentInstance instanceof BulletListItemComponent
    ).componentInstance;

    expect(bulletListItem.iconName()).toBe('childIcon');
  });

  it('should render ng-icon with computed iconName', async () => {
    const hostFixture = TestBed.createComponent(TestHostWithParentComponent);
    hostFixture.detectChanges();

    const ngIcon = hostFixture.debugElement.query(By.directive(NgIcon));
    expect(ngIcon.componentInstance.name()).toBe('parentIcon');
  });

  it('should update icon when parent icon changes', async () => {
    const hostFixture = TestBed.createComponent(TestHostWithParentComponent);
    const hostComponent = hostFixture.componentInstance;
    hostFixture.detectChanges();

    const bulletListItem = hostFixture.debugElement.query(
      sel => sel.componentInstance instanceof BulletListItemComponent
    ).componentInstance;

    expect(bulletListItem.iconName()).toBe('parentIcon');

    // Change parent icon
    hostComponent.parentIcon = 'newParentIcon';
    hostFixture.detectChanges();

    expect(bulletListItem.iconName()).toBe('newParentIcon');
  });
});