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

import { ProductAttribute } from '../../../../core/services/catalog/catalog.interface';
import { ProductAttributeSelectorComponent } from './product-attribute-selector.component';

describe('ProductAttributeSelectorComponent', () => {
  const sizeAttribute: ProductAttribute = {
    id: 1,
    codigo: 'size',
    nombre: 'Size',
    is_required: true,
    metadata_schema: null,
    type: 'select',
    options: [
      { id: 10, value: 'S', label: 'S', sort_order: 0, metadata: null },
      { id: 20, value: 'M', label: 'M', sort_order: 1, metadata: null },
    ],
  };

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

  it('keeps an unlimited option available when maximum quantity is null', () => {
    const fixture = TestBed.createComponent(ProductAttributeSelectorComponent);
    fixture.componentRef.setInput('attributes', [sizeAttribute]);
    fixture.componentRef.setInput('inventoryPolicy', 'unlimited');
    fixture.componentRef.setInput('variants', [
      {
        id: 1,
        maximum_addable_quantity: null,
        values: { size: 'S' },
      },
    ]);
    fixture.detectChanges();

    const buttons = Array.from(
      fixture.nativeElement.querySelectorAll('.attribute-selector__text-option'),
    ) as HTMLButtonElement[];
    expect(buttons[0].disabled).toBe(false);
    expect(buttons[1].disabled).toBe(true);
  });

  it('disables tracked options without available stock', () => {
    const fixture = TestBed.createComponent(ProductAttributeSelectorComponent);
    fixture.componentRef.setInput('attributes', [sizeAttribute]);
    fixture.componentRef.setInput('inventoryPolicy', 'tracked');
    fixture.componentRef.setInput('variants', [
      {
        id: 1,
        maximum_addable_quantity: 0,
        values: { size: 'S' },
      },
      {
        id: 2,
        maximum_addable_quantity: 2,
        values: { size: 'M' },
      },
    ]);
    fixture.detectChanges();

    const buttons = Array.from(
      fixture.nativeElement.querySelectorAll('.attribute-selector__text-option'),
    ) as HTMLButtonElement[];
    expect(buttons[0].disabled).toBe(true);
    expect(buttons[1].disabled).toBe(false);
  });

  it('allows multiple event dates and emits the exact matching variant', () => {
    const fixture = TestBed.createComponent(ProductAttributeSelectorComponent);
    const emittedIds: Array<number | null> = [];
    fixture.componentInstance.variantChange.subscribe((variant) =>
      emittedIds.push(variant?.id ?? null),
    );
    fixture.componentRef.setInput('attributes', [
      {
        id: 2,
        codigo: 'event_date',
        nombre: 'Fecha',
        is_required: true,
        allow_multi_select: true,
        metadata_schema: null,
        type: 'event_date',
        options: [
          { id: 101, value: '1', label: '09/10/2026', sort_order: 0, metadata: null },
          { id: 102, value: '2', label: '10/10/2026', sort_order: 1, metadata: null },
        ],
      } satisfies ProductAttribute,
    ]);
    fixture.componentRef.setInput('inventoryPolicy', 'unlimited');
    fixture.componentRef.setInput('variants', [
      { id: 1, maximum_addable_quantity: null, values: { event_date: '1' } },
      { id: 2, maximum_addable_quantity: null, values: { event_date: '2' } },
      { id: 3, maximum_addable_quantity: null, values: { event_date: ['1', '2'] } },
    ]);
    fixture.detectChanges();

    const buttons = Array.from(
      fixture.nativeElement.querySelectorAll('.attribute-selector__text-option'),
    ) as HTMLButtonElement[];
    buttons[0].click();
    fixture.detectChanges();
    buttons[1].click();
    fixture.detectChanges();

    expect(buttons[0].getAttribute('aria-pressed')).toBe('true');
    expect(buttons[1].getAttribute('aria-pressed')).toBe('true');
    expect(emittedIds).toContain(3);
  });

  it('hides configured attributes and matches variants using only visible selections', () => {
    const fixture = TestBed.createComponent(ProductAttributeSelectorComponent);
    const emittedIds: Array<number | null> = [];
    fixture.componentInstance.variantChange.subscribe((variant) =>
      emittedIds.push(variant?.id ?? null),
    );
    fixture.componentRef.setInput('attributes', [
      sizeAttribute,
      {
        id: 2,
        codigo: 'internal_type',
        nombre: 'Internal type',
        is_required: true,
        show_in_selector: false,
        metadata_schema: null,
        type: 'select',
        options: [
          { id: 30, value: 'adult', label: 'Adult', sort_order: 0, metadata: null },
          { id: 40, value: 'child', label: 'Child', sort_order: 1, metadata: null },
        ],
      } satisfies ProductAttribute,
    ]);
    fixture.componentRef.setInput('inventoryPolicy', 'unlimited');
    fixture.componentRef.setInput('variants', [
      { id: 1, maximum_addable_quantity: null, values: { size: 'S', internal_type: 'adult' } },
      { id: 2, maximum_addable_quantity: null, values: { size: 'M', internal_type: 'child' } },
    ]);
    fixture.detectChanges();

    const labels = fixture.nativeElement.querySelectorAll('.attribute-selector__label');
    const buttons = fixture.nativeElement.querySelectorAll('.attribute-selector__text-option');

    expect(labels).toHaveLength(1);
    expect(labels[0].textContent).toContain('Size');
    buttons[1].click();
    fixture.detectChanges();
    expect(emittedIds).toContain(2);
  });
});
