import { TestBed } from '@angular/core/testing';
import { ActivatedRoute, convertToParamMap, Router } from '@angular/router';

import {
  CheckoutService,
  PurchaseDetailResponse,
} from '../../../../core/services/checkout.service';
import { CartService } from '../../../../core/services/cart/cart.service';
import { Tenant } from '../../../../core/services/tenant.interface';
import { TenantService } from '../../../../core/services/tenant.service';
import { PurchaseStatusPageComponent } from './purchase-status-page.component';

const tenant: Tenant = {
  id: 1,
  codigo: 'tickets-tenant',
  nombre: 'Tickets tenant',
  dominio: 'tickets.local',
  primary_color: '#000000',
  secondary_color: '#000000',
  danger_color: '#000000',
  success_color: '#000000',
  header_bg_color: '#000000',
  footer_bg_color: '#000000',
  header_logo: '',
  footer_logo: '',
  categories: [],
  social_media: [
    {
      code: 'whatsapp',
      icon: 'whatsapp',
      name: 'WhatsApp',
      url: 'https://wa.me/543411234567',
    },
  ],
  menues: [
    {
      id: 1,
      code: 'account',
      label: 'Mi cuenta',
      parent_menu_code: null,
      content_type: 'dynamic',
      route: '/mi-cuenta',
      submenues: [
        {
          id: 2,
          code: 'account.tickets',
          label: 'Mis tickets',
          parent_menu_code: 'account',
          content_type: 'dynamic',
          route: '/mi-cuenta/tickets',
          submenues: [],
        },
      ],
    },
  ],
};

const purchase = (hasGeneratedTickets: boolean): PurchaseDetailResponse =>
  ({
    status: 'paid',
    has_generated_tickets: hasGeneratedTickets,
    tickets_count: hasGeneratedTickets ? 1 : 0,
  }) as PurchaseDetailResponse;

describe('PurchaseStatusPageComponent', () => {
  beforeEach(() => {
    TestBed.resetTestingModule();
  });

  async function render(
    hasGeneratedTickets: boolean,
    forcedStatus?: string,
    purchaseResponse = purchase(hasGeneratedTickets),
  ) {
    const checkoutService = {
      getPurchase: vi.fn().mockResolvedValue(purchaseResponse),
      withCustomLoading() {
        return this;
      },
    };
    const router = {
      navigate: vi.fn().mockResolvedValue(true),
      navigateByUrl: vi.fn().mockResolvedValue(true),
    };
    const cartService = { clearCart: vi.fn() };

    await TestBed.configureTestingModule({
      imports: [PurchaseStatusPageComponent],
      providers: [
        { provide: CheckoutService, useValue: checkoutService },
        { provide: CartService, useValue: cartService },
        { provide: TenantService, useValue: { tenant: () => tenant } },
        {
          provide: ActivatedRoute,
          useValue: {
            snapshot: {
              paramMap: convertToParamMap({ id: '42' }),
              queryParamMap: convertToParamMap(forcedStatus ? { status: forcedStatus } : {}),
            },
          },
        },
        { provide: Router, useValue: router },
      ],
    }).compileComponents();

    const fixture = TestBed.createComponent(PurchaseStatusPageComponent);
    fixture.detectChanges();
    await fixture.whenStable();
    fixture.detectChanges();

    return {
      fixture,
      element: fixture.nativeElement as HTMLElement,
      checkoutService,
      cartService,
      router,
    };
  }

  it('clears the cart when the purchase is approved', async () => {
    const { cartService } = await render(true);

    expect(cartService.clearCart).toHaveBeenCalledOnce();
  });

  it('shows the tickets action when this purchase generated tickets', async () => {
    const { element, checkoutService, router } = await render(true);

    expect(checkoutService.getPurchase).toHaveBeenCalledOnce();
    expect(element.textContent).toContain('Mis tickets');
    expect(element.textContent).not.toContain('WhatsApp');

    element.querySelector<HTMLButtonElement>('app-button button')?.click();

    expect(router.navigateByUrl).toHaveBeenCalledWith('/mi-cuenta/tickets');
  });

  it('shows the tenant WhatsApp action when this purchase did not generate tickets', async () => {
    const openSpy = vi.spyOn(window, 'open').mockImplementation(() => null);
    const { element } = await render(false);

    expect(element.textContent).toContain('WhatsApp');
    expect(element.textContent).not.toContain('Ver mis tickets');

    element.querySelector<HTMLButtonElement>('app-button button')?.click();

    expect(openSpy).toHaveBeenCalledWith(
      'https://wa.me/543411234567',
      '_blank',
      'noopener,noreferrer',
    );

    openSpy.mockRestore();
  });

  it('shows the expired result without polling when checkout redirects after expiration', async () => {
    const { element, checkoutService } = await render(false, 'expired');

    expect(element.textContent).toContain('LA COMPRA VENCIÓ');
    expect(element.textContent).not.toContain('ESTAMOS VERIFICANDO TU PAGO');
    expect(checkoutService.getPurchase).not.toHaveBeenCalled();
  });

  it('shows the primary transfer candidate issue while the purchase is in review', async () => {
    const { element } = await render(false, undefined, {
      status: 'in_review',
      payment_verification: {
        status: 'candidate',
        candidate_count: 2,
        primary: {
          reason: 'exact_dni_near_amount',
          dni_distance: 0,
          payment_amount: '49000.00',
          purchase_amount: '50000.00',
          amount_difference: '1000.00',
          confidence: 'high',
          detected_at: '2026-08-27T18:00:00-03:00',
        },
        reasons: ['exact_dni_near_amount', 'exact_amount_near_dni'],
      },
    } as PurchaseDetailResponse);

    expect(element.textContent).toContain('Encontramos 2 transferencias posibles.');
    expect(element.textContent).toMatch(/diferencia de \$\s*1\.000/);
    expect(element.textContent).toContain('Estamos revisando el pago.');
  });

  it('polls every five seconds while the payment is pending and shows the confirmation', async () => {
    vi.useFakeTimers();

    try {
      const checkoutService = {
        getPurchase: vi
          .fn()
          .mockResolvedValueOnce({ status: 'pending_payment' } as PurchaseDetailResponse)
          .mockResolvedValueOnce(purchase(true)),
        withCustomLoading() {
          return this;
        },
      };
      const cartService = { clearCart: vi.fn() };

      await TestBed.configureTestingModule({
        imports: [PurchaseStatusPageComponent],
        providers: [
          { provide: CheckoutService, useValue: checkoutService },
          { provide: CartService, useValue: cartService },
          { provide: TenantService, useValue: { tenant: () => tenant } },
          {
            provide: ActivatedRoute,
            useValue: { snapshot: { paramMap: convertToParamMap({ id: '42' }) } },
          },
          { provide: Router, useValue: { navigate: vi.fn(), navigateByUrl: vi.fn() } },
        ],
      }).compileComponents();

      const fixture = TestBed.createComponent(PurchaseStatusPageComponent);
      fixture.detectChanges();
      await Promise.resolve();
      fixture.detectChanges();

      expect(checkoutService.getPurchase).toHaveBeenCalledOnce();
      expect(fixture.nativeElement.textContent).toContain('ESTAMOS VERIFICANDO TU PAGO');

      await vi.advanceTimersByTimeAsync(5_000);
      fixture.detectChanges();

      expect(checkoutService.getPurchase).toHaveBeenCalledTimes(2);
      expect(fixture.nativeElement.textContent).toContain('COMPRA REALIZADA!');
      expect(cartService.clearCart).toHaveBeenCalledOnce();

      await vi.advanceTimersByTimeAsync(10_000);
      expect(checkoutService.getPurchase).toHaveBeenCalledTimes(2);
    } finally {
      vi.useRealTimers();
    }
  });

  it('stops polling when the page is destroyed', async () => {
    vi.useFakeTimers();

    try {
      const checkoutService = {
        getPurchase: vi.fn().mockResolvedValue({ status: 'pending_payment' }),
        withCustomLoading() {
          return this;
        },
      };

      await TestBed.configureTestingModule({
        imports: [PurchaseStatusPageComponent],
        providers: [
          { provide: CheckoutService, useValue: checkoutService },
          { provide: CartService, useValue: { clearCart: vi.fn() } },
          { provide: TenantService, useValue: { tenant: () => tenant } },
          {
            provide: ActivatedRoute,
            useValue: { snapshot: { paramMap: convertToParamMap({ id: '42' }) } },
          },
          { provide: Router, useValue: { navigate: vi.fn(), navigateByUrl: vi.fn() } },
        ],
      }).compileComponents();

      const fixture = TestBed.createComponent(PurchaseStatusPageComponent);
      fixture.detectChanges();
      await Promise.resolve();
      fixture.destroy();

      await vi.advanceTimersByTimeAsync(5_000);

      expect(checkoutService.getPurchase).toHaveBeenCalledOnce();
    } finally {
      vi.useRealTimers();
    }
  });
});
