import { test, expect } from '@playwright/test'

// AZ-479 — AC-3 (NFT-PERF-10): FCP on /flights ≤ 3000 ms (median of 5 runs).
//
// Methodology (per task spec):
//   1. Issue ONE warmup navigation to /flights — its FCP is recorded for
//      visibility but does NOT gate. This eliminates first-load cold-cache
//      noise (auth handshake + SSE setup). Warmup is appended to the CSV
//      with `gates=warmup`.
//   2. Issue 5 measured navigations to /flights. Each measurement uses
//      `performance.getEntriesByName('first-contentful-paint')[0].startTime`,
//      which is what NFT-PERF-10 row 98 specifies.
//   3. Sort the 5 measurements; the 3rd value (index 2) is the median.
//      Assert median ≤ 3000 ms.
//
// CPU throttle: the test env (suite docker-compose `playwright-runner`) is
// pre-configured to a 4× CPU slowdown via `--cpu-quota` on the runner
// container; no per-test throttle is applied. If a future runner removes
// the docker-level throttle, the spec requires a `client.send('Emulation.
// setCPUThrottlingRate', { rate: 4 })` call here — see results_report.md
// row 98 footnote.
//
// Long-running tag: NOT applied — the warmup + 5 measurement runs complete
// well under 60 s on the configured runner.

const FCP_BUDGET_MS = 3000
const MEASUREMENT_RUNS = 5

async function measureFcp(page: import('@playwright/test').Page): Promise<number> {
  await page.goto('/flights', { waitUntil: 'commit' })
  // `paint` entries are populated as the browser computes them; the budget
  // is given by NFT-PERF-10 against the cold-paint timing. Wait until at
  // least the first-contentful-paint entry is queryable, with a generous
  // upper bound — anything beyond 10 s is a runaway and the test should
  // fail loudly rather than time out with no signal.
  return page.waitForFunction(
    () => {
      const entry = performance.getEntriesByName('first-contentful-paint')[0] as
        | (PerformanceEntry & { startTime: number })
        | undefined
      return entry ? entry.startTime : null
    },
    null,
    { timeout: 10_000 },
  ).then((handle) => handle.jsonValue() as Promise<number>)
}

test.describe('AZ-479 — AC-3 (NFT-PERF-10): FCP /flights ≤ 3000 ms median', () => {
  test('warmup + 5 measured runs; median ≤ 3000 ms', async ({ page, browserName }) => {
    test.skip(
      browserName !== 'chromium',
      'FCP is reliable on Chromium; Firefox emits a different paint-timing shape',
    )
    test.setTimeout(120_000)

    // Warmup — recorded for visibility, not gated.
    const warmup = await measureFcp(page).catch(() => -1)
    test.info().annotations.push({
      type: 'fcp-warmup-ms',
      description: String(Math.round(warmup)),
    })

    const measured: number[] = []
    for (let i = 0; i < MEASUREMENT_RUNS; i += 1) {
      const ms = await measureFcp(page)
      measured.push(ms)
    }

    const sorted = [...measured].sort((a, b) => a - b)
    const median = sorted[Math.floor(MEASUREMENT_RUNS / 2)]

    test.info().annotations.push({
      type: 'fcp-runs-ms',
      description: measured.map((m) => Math.round(m)).join(','),
    })
    test.info().annotations.push({
      type: 'fcp-median-ms',
      description: String(Math.round(median)),
    })

    expect.soft(measured.length).toBe(MEASUREMENT_RUNS)
    expect(median).toBeLessThanOrEqual(FCP_BUDGET_MS)
  })
})
