import { signal } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { vi } from 'vitest';

import { CheckoutPaymentFacade } from './checkout-payment.facade';
import { CheckoutPaymentStepComponent } from './checkout-payment-step.component';
import { PaymentMethod, PaymentMethodOption, TransferAccount } from './checkout-page.models';

describe('CheckoutPaymentStepComponent', () => {
  const paymentMethods: ReadonlyArray<PaymentMethodOption> = [
    { id: 'qr', label: 'QR' },
    { id: 'transfer', label: 'Transferencia' },
    { id: 'telepagos', label: 'TelePagos' }
  ];
  const transferAccount: TransferAccount = {
    titular: 'Titular Test',
    entidad: 'Entidad Test',
    cvu: '0000000000000000000000',
    alias: 'alias.test'
  };

  let fixture: ComponentFixture<CheckoutPaymentStepComponent>;
  let payment: {
    paymentMethods: ReadonlyArray<PaymentMethodOption>;
    selectedMethod: ReturnType<typeof signal<PaymentMethod>>;
    copiedTransferField: ReturnType<typeof signal<'cvu' | 'alias' | null>>;
    transferAccount: ReturnType<typeof signal<TransferAccount | null>>;
    payerDni: ReturnType<typeof signal<string>>;
    transferRequestError: ReturnType<typeof signal<string | null>>;
    qrData: ReturnType<typeof signal<string | null>>;
    isLoading: ReturnType<typeof signal<boolean>>;
    canComplete: ReturnType<typeof signal<boolean>>;
    setPurchaseId: ReturnType<typeof vi.fn>;
    selectMethod: ReturnType<typeof vi.fn>;
    copyTransferValue: ReturnType<typeof vi.fn>;
    requestTransferData: ReturnType<typeof vi.fn>;
  };

  beforeEach(async () => {
    payment = {
      paymentMethods,
      selectedMethod: signal<PaymentMethod>('qr'),
      copiedTransferField: signal<'cvu' | 'alias' | null>(null),
      transferAccount: signal<TransferAccount | null>(transferAccount),
      payerDni: signal('12345678'),
      transferRequestError: signal<string | null>(null),
      qrData: signal<string | null>('qr-test'),
      isLoading: signal(false),
      canComplete: signal(true),
      setPurchaseId: vi.fn(),
      selectMethod: vi.fn(),
      copyTransferValue: vi.fn(),
      requestTransferData: vi.fn()
    };

    await TestBed.configureTestingModule({
      imports: [CheckoutPaymentStepComponent]
    })
      .overrideComponent(CheckoutPaymentStepComponent, {
        set: { providers: [{ provide: CheckoutPaymentFacade, useValue: payment }] }
      })
      .compileComponents();

    fixture = TestBed.createComponent(CheckoutPaymentStepComponent);
  });

  it.each([
    ['qr', 'app-qr-payment-content'],
    ['transfer', 'app-transfer-payment-content'],
    ['telepagos', 'app-telepagos-payment-content']
  ] as const)('renders the %s payment content', (method: PaymentMethod, selector: string) => {
    payment.selectedMethod.set(method);
    fixture.detectChanges();

    expect(fixture.nativeElement.querySelector(selector)).not.toBeNull();
  });

  it('delegates method selection to the payment facade', () => {
    fixture.detectChanges();
    const transferRadio = fixture.nativeElement.querySelector('input[value="transfer"]') as HTMLInputElement;
    transferRadio.dispatchEvent(new Event('change'));

    expect(payment.selectMethod).toHaveBeenCalledWith('transfer');
  });

  it('shows only the loading state while generating a QR intent', () => {
    payment.selectedMethod.set('qr');
    payment.isLoading.set(true);
    fixture.detectChanges();

    expect(fixture.nativeElement.textContent).toContain('Cargando información de pago...');
    expect(fixture.nativeElement.querySelector('app-qr-payment-content')).toBeNull();
  });

  it('delegates transfer copy requests to the payment facade', () => {
    payment.selectedMethod.set('transfer');
    fixture.detectChanges();
    fixture.nativeElement.querySelector('app-icon-button').click();

    expect(payment.copyTransferValue).toHaveBeenCalledWith('cvu', transferAccount.cvu);
  });
});
