import { Component } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { MainCarouselComponent } from './main-carousel.component';

@Component({
  imports: [MainCarouselComponent],
  template: `
    <app-main-carousel
      [images]="images"
      [imageAlts]="['Primera promoción', 'Segunda promoción', 'Tercera promoción']"
      [autoSlideInterval]="1000"
    />
  `,
})
class TestHostComponent {
  readonly images = ['/images/one.webp', '/images/two.webp', '/images/three.webp'];
}

describe('MainCarouselComponent', () => {
  let fixture: ComponentFixture<TestHostComponent>;

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

    fixture = TestBed.createComponent(TestHostComponent);
    fixture.detectChanges();
  });

  it('renderiza solamente las imágenes y sus indicadores', () => {
    const element = fixture.nativeElement as HTMLElement;
    const images = element.querySelectorAll('.main-carousel__image');
    const indicators = element.querySelectorAll('.main-carousel__indicator');

    expect(images).toHaveLength(3);
    expect(indicators).toHaveLength(3);
    expect(images[0].getAttribute('alt')).toBe('Primera promoción');
    expect(images[0].classList).toContain('main-carousel__image--active');
  });

  it('carga las imágenes secuencialmente y prioriza la imagen visible', () => {
    const images = fixture.nativeElement.querySelectorAll(
      '.main-carousel__image',
    ) as NodeListOf<HTMLImageElement>;

    expect(images[0].getAttribute('src')).toBe('/images/one.webp');
    expect(images[0].getAttribute('fetchpriority')).toBe('high');
    expect(images[1].getAttribute('src')).toBeNull();
    expect(images[2].getAttribute('src')).toBeNull();

    images[0].dispatchEvent(new Event('load'));
    fixture.detectChanges();

    expect(images[1].getAttribute('src')).toBe('/images/two.webp');
    expect(images[1].getAttribute('fetchpriority')).toBe('low');
    expect(images[2].getAttribute('src')).toBeNull();

    images[1].dispatchEvent(new Event('load'));
    fixture.detectChanges();

    expect(images[2].getAttribute('src')).toBe('/images/three.webp');
  });

  it('avanza automáticamente entre las imágenes', () => {
    fixture.destroy();
    vi.useFakeTimers();

    try {
      fixture = TestBed.createComponent(TestHostComponent);
      fixture.detectChanges();
      const images = fixture.nativeElement.querySelectorAll(
        '.main-carousel__image',
      ) as NodeListOf<HTMLImageElement>;

      images[0].dispatchEvent(new Event('load'));
      fixture.detectChanges();
      images[1].dispatchEvent(new Event('load'));
      fixture.detectChanges();

      vi.advanceTimersByTime(1000);
      fixture.detectChanges();

      expect(images[1].classList).toContain('main-carousel__image--active');
    } finally {
      fixture.destroy();
      vi.useRealTimers();
    }
  });

  it('permite seleccionar una imagen desde los indicadores', () => {
    const indicators = fixture.nativeElement.querySelectorAll(
      '.main-carousel__indicator',
    ) as NodeListOf<HTMLButtonElement>;

    indicators[2].click();
    fixture.detectChanges();

    const images = fixture.nativeElement.querySelectorAll('.main-carousel__image');
    expect(images[2].classList).toContain('main-carousel__image--active');
    expect(indicators[2].getAttribute('aria-current')).toBe('true');
  });

  it('permite navegar con las flechas del teclado', () => {
    const carousel = fixture.nativeElement.querySelector('.main-carousel') as HTMLElement;

    carousel.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
    fixture.detectChanges();

    const images = fixture.nativeElement.querySelectorAll('.main-carousel__image');
    expect(images[2].classList).toContain('main-carousel__image--active');
  });
});
