import { Page, Route, expect, test } from '@playwright/test';

/**
 * Track Q Q5 / frontend backlog F62: "repeat webhook and double-click create
 * exactly one order." The webhook-idempotency half is a backend contract
 * (PHASE-1-MONEY-FX-PAYMENTS-CONTRACT.md §6.3, provider + providerEventId as
 * the dedup key) this suite cannot exercise without a live backend. This
 * test covers the half that IS frontend-testable: a double-click on the
 * checkout button must not fire two checkout-session requests.
 */

const FAKE_ITEM = {
  categoryID: 1, itemID: 5151, name: 'Idempotency Test Item', photos: null,
  description: '', currency: 'RUB', price: 500, discount: 0, rating: 0,
  callbacks: null, questions: null, quantity: 1,
};

test('double-clicking checkout sends exactly one checkout-session request', async ({ page, context }) => {
  await page.addInitScript(item => {
    window.localStorage.setItem('marketplace_cart', JSON.stringify([item]));
  }, FAKE_ITEM);

  // Root-caused and fixed 2026-08-21 - see checkout-request-shape.spec.ts's
  // fakeCustomerSession comment and api-headers.interceptor.ts.
  await context.addCookies([{ name: 'webSessionID', value: 'e2e-fake-session', url: 'http://localhost:4200' }]);
  await page.route('**/users/sessions/**', route =>
    route.fulfill({
      status: 200, contentType: 'application/json',
      body: JSON.stringify({ sessionId: 'e2e-fake-session', status: 'active', username: 'e2e_user', userId: 1 }),
    }),
  );
  await page.route('**/api/v2/pricing/fx-quote**', route =>
    route.fulfill({
      status: 200, contentType: 'application/json',
      body: JSON.stringify({ quoteId: 'fxq_e2e', base: 'RUB', quote: 'RUB', rate: 1, source: 'e2e', observedAt: new Date().toISOString(), expiresAt: new Date(Date.now() + 300000).toISOString() }),
    }),
  );

  let checkoutRequestCount = 0;
  await page.route('**/api/v2/storefront/checkout', async (route: Route) => {
    checkoutRequestCount += 1;
    // Deliberately slow, so a real double-click's second event has to land
    // while the first request is still in flight - the exact race this test
    // exists to catch.
    await new Promise(resolve => setTimeout(resolve, 300));
    route.fulfill({
      status: 200, contentType: 'application/json',
      body: JSON.stringify({
        checkoutSessionId: 'chk_e2e_idempotent',
        lines: [{ offerId: String(FAKE_ITEM.itemID), qty: 1, unitPrice: { amountMinor: 50000, currency: 'RUB' }, lineTotal: { amountMinor: 50000, currency: 'RUB' }, priceSnapshotId: 'snap_e2e' }],
        subtotal: { amountMinor: 50000, currency: 'RUB' }, discount: { amountMinor: 0, currency: 'RUB' },
        delivery: { amountMinor: 0, currency: 'RUB' }, total: { amountMinor: 50000, currency: 'RUB' },
        fxQuoteId: 'fxq_e2e', expiresAt: new Date(Date.now() + 300000).toISOString(),
      }),
    });
  });
  await page.route('**/api/v2/storefront/payments/intents', route =>
    route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ qrId: 'qr_e2e', nspkurl: 'https://example.com/pay', qrTTL: 5 }) }),
  );

  await page.goto('/cart');
  await page.waitForLoadState('networkidle');

  // No <label for="terms-checkbox"> exists in the markup - the checkbox and
  // its text share a plain clickable wrapper - so toggle the input directly.
  await page.locator('#terms-checkbox').dispatchEvent('click');
  await expect(page.locator('#terms-checkbox')).toBeChecked();

  const qrButton = page.getByRole('button', { name: /qr/i }).first();
  await expect(qrButton).toBeEnabled({ timeout: 10_000 });
  await qrButton.dblclick();

  // Give the deliberately slow mock time to resolve and for any second,
  // erroneously-fired request to have landed.
  await page.waitForTimeout(1000);

  expect(checkoutRequestCount, 'a double-click must not create two checkout sessions').toBe(1);
});
