import '@angular/compiler';
import { TestBed, getTestBed } from '@angular/core/testing';
import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
import { afterEach, beforeAll, describe, expect, it } from 'vitest';

import { VariantSelectorComponent } from './variant-selector.component';

describe('VariantSelectorComponent', () => {
  beforeAll(() => {
    try {
      getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting());
    } catch {
      // Test environment may already be initialized by another setup entrypoint.
    }
  });

  afterEach(() => TestBed.resetTestingModule());

  it('updates following selections to the first compatible variant', async () => {
    await TestBed.configureTestingModule({
      imports: [VariantSelectorComponent],
    }).compileComponents();
    const fixture = TestBed.createComponent(VariantSelectorComponent);
    fixture.componentRef.setInput('variants', [
      { id: 1, values: { alojamiento: 'Carpa', servicio: 'Almuerzo' } },
      { id: 2, values: { alojamiento: 'Carpa', servicio: 'Cena' } },
      { id: 3, values: { alojamiento: 'Hotel', servicio: 'Cena' } },
    ]);
    fixture.componentRef.setInput('selectedVariant', 1);
    fixture.detectChanges();

    (fixture.componentInstance as any).onValueChange('alojamiento', 'Hotel');
    fixture.detectChanges();

    expect(fixture.componentInstance.selectedVariant()).toBe(3);
    expect((fixture.componentInstance as any).selectedValues()).toEqual({
      alojamiento: 'Hotel',
      servicio: 'Cena',
    });
  });

  it('renders backend option labels and compares equivalent option objects by value', async () => {
    await TestBed.configureTestingModule({
      imports: [VariantSelectorComponent],
    }).compileComponents();
    const fixture = TestBed.createComponent(VariantSelectorComponent);
    fixture.componentRef.setInput('variants', [
      {
        id: 1,
        values: {
          color: { value: 'red', label: 'Rojo' },
          talle: { value: 's', label: 'Small' },
        },
      },
      {
        id: 2,
        values: {
          color: { value: 'red', label: 'Rojo' },
          talle: { value: 'm', label: 'Medium' },
        },
      },
    ]);
    fixture.componentRef.setInput('selectedVariant', 2);
    fixture.detectChanges();

    const selects = Array.from(
      fixture.nativeElement.querySelectorAll('select'),
    ) as HTMLSelectElement[];

    expect(selects).toHaveLength(2);
    expect(selects[0].selectedOptions[0]?.textContent).toBe('Rojo');
    expect(selects[1].selectedOptions[0]?.textContent).toBe('Medium');
    expect(fixture.nativeElement.textContent).not.toContain('[object Object]');

    (fixture.componentInstance as any).onValueChange('talle', {
      value: 's',
      label: 'Small',
    });

    expect(fixture.componentInstance.selectedVariant()).toBe(1);
  });

  it('requires manual selections when autoSelectFirst is disabled', async () => {
    await TestBed.configureTestingModule({
      imports: [VariantSelectorComponent],
    }).compileComponents();
    const fixture = TestBed.createComponent(VariantSelectorComponent);
    fixture.componentRef.setInput('variants', [
      { id: 1, values: { sector: 'A', asiento: '1' } },
      { id: 2, values: { sector: 'A', asiento: '2' } },
    ]);
    fixture.componentRef.setInput('autoSelectFirst', false);
    fixture.detectChanges();

    expect(fixture.componentInstance.selectedVariant()).toBeNull();
    expect((fixture.componentInstance as any).selectedValues()).toEqual({});

    (fixture.componentInstance as any).onValueChange('sector', 'A');
    fixture.detectChanges();

    expect(fixture.componentInstance.selectedVariant()).toBeNull();
    expect((fixture.componentInstance as any).selectedValues()).toEqual({ sector: 'A' });

    fixture.componentRef.setInput('variants', [
      { id: 1, values: { sector: 'A', asiento: '1' } },
      { id: 2, values: { sector: 'A', asiento: '2' } },
    ]);
    fixture.detectChanges();

    expect((fixture.componentInstance as any).selectedValues()).toEqual({ sector: 'A' });
    expect((fixture.componentInstance as any).selectors()[1].options).toHaveLength(2);

    (fixture.componentInstance as any).onValueChange('asiento', '2');

    expect(fixture.componentInstance.selectedVariant()).toBe(2);
  });

  it('clears every selected value when the reset token changes', async () => {
    await TestBed.configureTestingModule({
      imports: [VariantSelectorComponent],
    }).compileComponents();
    const fixture = TestBed.createComponent(VariantSelectorComponent);
    fixture.componentRef.setInput('variants', [{ id: 1, values: { sector: 'A', asiento: '1' } }]);
    fixture.componentRef.setInput('autoSelectFirst', false);
    fixture.detectChanges();

    (fixture.componentInstance as any).onValueChange('sector', 'A');
    (fixture.componentInstance as any).onValueChange('asiento', '1');
    expect(fixture.componentInstance.selectedVariant()).toBe(1);

    fixture.componentRef.setInput('resetToken', 1);
    fixture.detectChanges();

    expect(fixture.componentInstance.selectedVariant()).toBeNull();
    expect((fixture.componentInstance as any).selectedValues()).toEqual({});
  });
});
