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

// AZ-460 — e2e companion for the annotation save URL + payload contract.
//
// AC-1 (FT-P-07): the doubly-prefixed canary URL on the real `annotations/`
//                 service. The fast-profile fixture asserts the URL via MSW;
//                 here we observe the real network request to confirm the
//                 service does not silently strip the `/annotations` prefix.
// AC-2 (FT-P-08): captured POST body contains all required fields. Today this
//                 is `test.fail()` (drift documented in fast tests).
//
// This e2e requires the suite docker-compose stack
// (`docker compose -f e2e/docker-compose.suite-e2e.yml up -d`) plus parent-suite
// `:test` images. It will run on the suite-e2e CI lane once those images are
// available; on a developer host without the stack the test skips with the
// standard message.

test.describe('AZ-460 — annotation save URL + payload (e2e companion)', () => {
  test('AC-1 (FT-P-07) — outbound URL is /api/annotations/annotations', async ({ page }) => {
    const requests: { url: string; body: string | null }[] = []
    await page.route('**/api/annotations/annotations**', async (route) => {
      const req = route.request()
      if (req.method() === 'POST') {
        requests.push({ url: req.url(), body: req.postData() })
      }
      await route.continue()
    })

    await page.goto('/annotations')
    // Drive a save through the UI — depends on suite seed data; if no media
    // is selectable in the fixture, the test reports the seed gap explicitly
    // rather than masking the UI.
    const saveBtn = page.getByRole('button', { name: /^Save$/i }).first()
    if (!(await saveBtn.isVisible({ timeout: 5000 }).catch(() => false))) {
      test.skip(true, 'Suite seed has no media available for annotation save')
    }

    await saveBtn.click({ timeout: 5000 }).catch(() => {})

    // Assert
    const saved = await page.waitForFunction(
      (count) => count > 0,
      requests.length,
      { timeout: 5000 },
    ).catch(() => null)
    if (!saved) test.skip(true, 'Save did not fire on this seed')

    expect(requests.length).toBeGreaterThan(0)
    for (const r of requests) {
      expect(r.url).toContain('/api/annotations/annotations')
    }
  })

  test.fail('AC-2 (FT-P-08) — required fields {Source, WaypointId, videoTime, mediaId, detections, status}', async ({ page }) => {
    // Drift gated: production today only sends {mediaId, time, detections}.
    // This e2e companion will flip green when AC-2 lands in Phase B.
    const captured: Record<string, unknown>[] = []
    await page.route('**/api/annotations/annotations**', async (route) => {
      const req = route.request()
      if (req.method() === 'POST') {
        const text = req.postData()
        if (text) captured.push(JSON.parse(text))
      }
      await route.continue()
    })

    await page.goto('/annotations')
    const saveBtn = page.getByRole('button', { name: /^Save$/i }).first()
    if (!(await saveBtn.isVisible({ timeout: 5000 }).catch(() => false))) {
      test.skip(true, 'Suite seed has no media for save')
    }
    await saveBtn.click()

    await page.waitForTimeout(1000)
    expect(captured.length).toBeGreaterThan(0)
    for (const body of captured) {
      expect(body).toHaveProperty('Source')
      expect(['AI', 'Manual']).toContain(body.Source as string)
      expect(body).toHaveProperty('WaypointId')
      expect(body).toHaveProperty('videoTime')
      expect(body).toHaveProperty('mediaId')
      expect(body).toHaveProperty('detections')
      expect(body).toHaveProperty('status')
    }
  })
})
