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

// AZ-464 — e2e companion for bulk-validate URL + body + UI sync.
//
// AC-1 (FT-P-20 URL): outbound POST URL is `/api/annotations/dataset/bulk-status`.
// AC-2 (FT-P-20 body): drift today — production sends `{annotationIds, status}`,
//                      contract wants `{ids, targetStatus: 30}`. `test.fail()`.
// AC-3 (FT-P-21):     UI rows show `Validated` within 2 s of the 200 response.
//
// Requires the suite docker-compose stack with seeded dataset items. The seed
// must include at least 3 items in Created status so the bulk-validate UI
// path is exercised end-to-end.

test.describe('AZ-464 — bulk-validate (e2e companion)', () => {
  test('AC-1 (FT-P-20) — outbound URL is /api/annotations/dataset/bulk-status', async ({ page }) => {
    const posts: { url: string; body: string | null }[] = []
    await page.route('**/api/annotations/dataset/bulk-status', async (route) => {
      const req = route.request()
      if (req.method() === 'POST') {
        posts.push({ url: req.url(), body: req.postData() })
      }
      await route.continue()
    })

    await page.goto('/dataset')
    // Suite seed must surface at least 3 selectable rows; otherwise skip.
    const rows = page.locator('div.cursor-pointer')
    const visibleCount = await rows.count().catch(() => 0)
    if (visibleCount < 3) {
      test.skip(true, 'Suite seed has fewer than 3 dataset rows for bulk-validate')
    }
    for (let i = 0; i < 3; i++) {
      await rows.nth(i).click({ modifiers: ['Control'] })
    }
    const validateBtn = page.getByRole('button', { name: /Validate \(\d+\)/i })
    if (!(await validateBtn.isVisible({ timeout: 5000 }).catch(() => false))) {
      test.skip(true, 'Validate button not visible — selection not applied?')
    }
    await validateBtn.click()

    await page.waitForFunction(() => true, undefined, { timeout: 3000 }).catch(() => null)
    expect(posts.length).toBe(1)
    const path = new URL(posts[0].url).pathname
    expect(path).toBe('/api/annotations/dataset/bulk-status')
  })

  test.fail('AC-2 (FT-P-20) — body shape `{ids, targetStatus: 30}` (drift)', async ({ page }) => {
    const captured: Record<string, unknown>[] = []
    await page.route('**/api/annotations/dataset/bulk-status', 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('/dataset')
    const rows = page.locator('div.cursor-pointer')
    if ((await rows.count().catch(() => 0)) < 3) {
      test.skip(true, 'Seed gap')
    }
    for (let i = 0; i < 3; i++) {
      await rows.nth(i).click({ modifiers: ['Control'] })
    }
    const validateBtn = page.getByRole('button', { name: /Validate \(\d+\)/i })
    await validateBtn.click()
    await page.waitForTimeout(1000)
    expect(captured.length).toBeGreaterThan(0)
    for (const body of captured) {
      expect(body).toHaveProperty('ids')
      expect(body).toHaveProperty('targetStatus', 30)
    }
  })

  test('AC-3 (FT-P-21) — UI shows Validated badge ≤ 2 000 ms after success', async ({ page }) => {
    await page.goto('/dataset')
    const rows = page.locator('div.cursor-pointer')
    if ((await rows.count().catch(() => 0)) < 3) {
      test.skip(true, 'Seed gap — need 3 rows in Created status')
    }
    for (let i = 0; i < 3; i++) {
      await rows.nth(i).click({ modifiers: ['Control'] })
    }
    const validateBtn = page.getByRole('button', { name: /Validate \(\d+\)/i })
    if (!(await validateBtn.isVisible({ timeout: 5000 }).catch(() => false))) {
      test.skip(true, 'Validate button not visible')
    }
    const t0 = Date.now()
    await validateBtn.click()
    // Wait for at least one row to flip to the Validated badge.
    await page.waitForFunction(
      () => {
        const badges = Array.from(
          document.querySelectorAll('span'),
        ).filter((el) => /Validated/i.test(el.textContent ?? ''))
        return badges.length > 0
      },
      undefined,
      { timeout: 2000 },
    )
    expect(Date.now() - t0).toBeLessThanOrEqual(2000)
  })
})
