import { ComponentFixture, TestBed } from '@angular/core/testing';
import { describe, it, expect, beforeEach } from 'vitest';
import { ProductInfoComponent, ProductInfoItem } from './product-info.component';
import { DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { provideProductImageUrl } from '@isa/shared/product-image';
import { provideProductRouterLinkBuilder } from '@isa/shared/product-router-link';
import { provideRouter } from '@angular/router';

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

  const mockProduct: ProductInfoItem = {
    ean: '9783161484100',
    name: 'Test Product Name',
    contributors: 'Test Author',
  };

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [ProductInfoComponent],
      providers: [
        provideRouter([]),
        provideProductImageUrl('https://test.example.com'),
        provideProductRouterLinkBuilder((ean: string) => `/product/${ean}`),
      ],
    });

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

  it('should create', () => {
    fixture.componentRef.setInput('item', mockProduct);
    fixture.detectChanges();
    expect(component).toBeTruthy();
  });

  it('should have item input', () => {
    fixture.componentRef.setInput('item', mockProduct);
    expect(component.item()).toEqual(mockProduct);
  });

  it('should have default nameSize of medium', () => {
    fixture.componentRef.setInput('item', mockProduct);
    expect(component.nameSize()).toBe('medium');
  });

  describe('nameSizeClass computation', () => {
    beforeEach(() => {
      fixture.componentRef.setInput('item', mockProduct);
    });

    it('should return isa-text-body-2-regular for small size', () => {
      fixture.componentRef.setInput('nameSize', 'small');
      expect(component.nameSizeClass()).toBe('isa-text-body-2-regular');
    });

    it('should return isa-text-subtitle-1-regular for medium size', () => {
      fixture.componentRef.setInput('nameSize', 'medium');
      expect(component.nameSizeClass()).toBe('isa-text-subtitle-1-regular');
    });

    it('should return isa-text-heading-3-regular for large size', () => {
      fixture.componentRef.setInput('nameSize', 'large');
      expect(component.nameSizeClass()).toBe('isa-text-heading-3-regular');
    });
  });

  describe('template rendering', () => {
    beforeEach(() => {
      fixture.componentRef.setInput('item', mockProduct);
      fixture.detectChanges();
    });

    it('should render product contributors', () => {
      const contributorsEl: DebugElement = fixture.debugElement.query(
        By.css('[data-what="product-contributors"]')
      );
      expect(contributorsEl).toBeTruthy();
      expect(contributorsEl.nativeElement.textContent.trim()).toBe(
        'Test Author'
      );
    });

    it('should render product name with correct size class', () => {
      const nameEl: DebugElement = fixture.debugElement.query(
        By.css('[data-what="product-name"]')
      );
      expect(nameEl).toBeTruthy();
      expect(nameEl.nativeElement.textContent.trim()).toBe('Test Product Name');
      expect(nameEl.nativeElement.classList.contains('isa-text-subtitle-1-regular')).toBe(true);
    });

    it('should have E2E attribute on product image', () => {
      const imageEl: DebugElement = fixture.debugElement.query(
        By.css('[data-what="product-image"]')
      );
      expect(imageEl).toBeTruthy();
    });

    it('should project ng-content', () => {
      const customContentFixture = TestBed.createComponent(ProductInfoComponent);
      customContentFixture.componentRef.setInput('item', mockProduct);

      const div = document.createElement('div');
      div.className = 'custom-content';
      div.textContent = 'Custom projected content';
      customContentFixture.nativeElement.appendChild(div);

      customContentFixture.detectChanges();

      const projectedContent = customContentFixture.nativeElement.querySelector('.custom-content');
      expect(projectedContent).toBeTruthy();
      expect(projectedContent.textContent).toBe('Custom projected content');
    });
  });

  describe('name size variations', () => {
    beforeEach(() => {
      fixture.componentRef.setInput('item', mockProduct);
    });

    it('should apply small name size class', () => {
      fixture.componentRef.setInput('nameSize', 'small');
      fixture.detectChanges();

      const nameEl: DebugElement = fixture.debugElement.query(
        By.css('[data-what="product-name"]')
      );
      expect(nameEl.nativeElement.classList.contains('isa-text-body-2-regular')).toBe(true);
    });

    it('should apply large name size class', () => {
      fixture.componentRef.setInput('nameSize', 'large');
      fixture.detectChanges();

      const nameEl: DebugElement = fixture.debugElement.query(
        By.css('[data-what="product-name"]')
      );
      expect(nameEl.nativeElement.classList.contains('isa-text-heading-3-regular')).toBe(true);
    });
  });
});
