/**
 * cloud-list-pages.spec.ts — Sovereign-portal Cloud per-resource list
 * pages E2E lock-in (P3 of issue #309).
 *
 * What this asserts:
 *   • The sidebar's second-level accordion (Compute / Network /
 *     Storage) expands to reveal sub-sub items.
 *   • Each sub-sub link routes to its /cloud/<category>/<resource>
 *     page; the page renders with at least one row + a clickable
 *     row that opens the detail drawer.
 *   • Placeholder pages (Services / Ingresses / DNS Zones / Storage
 *     Classes) render the canonical empty-state shell.
 *   • 1440x900 visual screenshots saved to e2e/screenshots/.
 *
 * Per docs/INVIOLABLE-PRINCIPLES.md #4 (never hardcode), the URL
 * comes from playwright.config.ts (env-driven HOST + BASEPATH); we
 * use a synthetic deploymentId and rely on the SPA's fixture
 * fallback for in-page data.
 */

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

// Deliberately avoid the strings "cloud" or "infrastructure" in the
// deploymentId so the sidebar's path-segment matcher can't be fooled
// by a substring match.
const DEPLOYMENT_ID = 'p3-309-e2e'

interface ListPageCase {
  category: 'compute' | 'network' | 'storage'
  child: string
  /** Page-container testid. */
  pageTestId: string
  /** First row id we expect from the fixture (or '' for placeholder pages). */
  firstRowId: string
  /** True for placeholder routes (Services / Ingresses / DNS Zones / Storage Classes). */
  placeholder: boolean
}

const CASES: readonly ListPageCase[] = [
  // Compute — real data
  { category: 'compute', child: 'clusters',     pageTestId: 'cloud-clusters-page',     firstRowId: 'cloud-clusters-row-cluster-eu-central-primary',     placeholder: false },
  { category: 'compute', child: 'vclusters',    pageTestId: 'cloud-vclusters-page',    firstRowId: 'cloud-vclusters-row-vc-eu-central-dmz',             placeholder: false },
  { category: 'compute', child: 'node-pools',   pageTestId: 'cloud-node-pools-page',   firstRowId: 'cloud-node-pools-row-pool-eu-cp',                   placeholder: false },
  { category: 'compute', child: 'worker-nodes', pageTestId: 'cloud-worker-nodes-page', firstRowId: 'cloud-worker-nodes-row-node-eu-cp-0',               placeholder: false },
  // Network
  { category: 'network', child: 'load-balancers', pageTestId: 'cloud-load-balancers-page', firstRowId: 'cloud-load-balancers-row-lb-eu-central-edge',  placeholder: false },
  { category: 'network', child: 'services',       pageTestId: 'cloud-services-page',       firstRowId: '',                                              placeholder: true },
  { category: 'network', child: 'ingresses',      pageTestId: 'cloud-ingresses-page',      firstRowId: '',                                              placeholder: true },
  { category: 'network', child: 'dns-zones',      pageTestId: 'cloud-dns-zones-page',      firstRowId: '',                                              placeholder: true },
  // Storage
  { category: 'storage', child: 'pvcs',            pageTestId: 'cloud-pvcs-page',            firstRowId: 'cloud-pvcs-row-pvc-postgres-data',            placeholder: false },
  { category: 'storage', child: 'buckets',         pageTestId: 'cloud-buckets-page',         firstRowId: 'cloud-buckets-row-bucket-backups',            placeholder: false },
  { category: 'storage', child: 'volumes',         pageTestId: 'cloud-volumes-page',         firstRowId: 'cloud-volumes-row-vol-postgres-eu',           placeholder: false },
  { category: 'storage', child: 'storage-classes', pageTestId: 'cloud-storage-classes-page', firstRowId: '',                                            placeholder: true },
] as const

async function gotoProvision(page: Page, suffix = '') {
  const tail = suffix ? `/${suffix}` : ''
  await page.goto(`provision/${DEPLOYMENT_ID}${tail}`)
  await page.waitForLoadState('domcontentloaded')
}

async function clearLocalStorage(page: Page) {
  await page.goto('wizard')
  await page.waitForLoadState('domcontentloaded')
  await page.evaluate(() => {
    try {
      window.localStorage.clear()
    } catch {
      /* noop */
    }
  })
}

test.describe('Cloud list pages (#309 P3 — surfaces preserved by #350)', () => {
  test.beforeEach(async ({ page }) => {
    await clearLocalStorage(page)
  })

  // The legacy /cloud/<category>/<resource> URLs are now 301
  // redirects to the consolidated /cloud?view=list&kind=… shape (issue
  // #350). The list-page components below are reused inside the new
  // CloudListView, so the same testid contracts hold.

  for (const c of CASES) {
    test(`${c.category}/${c.child} renders + ${c.placeholder ? 'shows empty state' : 'opens drawer on row click'}`, async ({ page }) => {
      await gotoProvision(page, `cloud/${c.category}/${c.child}`)
      // Page container must mount.
      await expect(
        page.getByTestId(c.pageTestId),
        `expected /cloud/${c.category}/${c.child} to mount [data-testid=${c.pageTestId}]`,
      ).toBeVisible()

      if (c.placeholder) {
        // Placeholder pages must surface the canonical empty state.
        const emptyId = c.pageTestId.replace('-page', '-empty')
        await expect(
          page.getByTestId(emptyId),
          `placeholder page ${c.pageTestId} must surface [data-testid=${emptyId}]`,
        ).toBeVisible()
      } else {
        // Data-backed pages must render the seeded first row + open
        // the detail drawer when clicked.
        const row = page.getByTestId(c.firstRowId)
        await expect(row, `expected first-row [${c.firstRowId}] on ${c.pageTestId}`).toBeVisible()
        await row.click()
        const detailId = c.pageTestId.replace('-page', '-detail')
        await expect(
          page.getByTestId(detailId),
          `clicking row should open [${detailId}] on ${c.pageTestId}`,
        ).toBeVisible()
        // Esc + close button parity (sanity).
        await page.getByTestId(`${detailId}-close`).click()
        await expect(page.getByTestId(detailId)).toHaveCount(0)
      }
    })
  }

  test('the consolidated list-view chip strip renders 6 primary chips + a + More overflow (was 12-tile grid)', async ({ page }) => {
    // Issue #350 collapsed the three CloudComputePage / CloudNetworkPage /
    // CloudStoragePage category landings into a single CloudListView; the
    // 12-tile card grid that originally sat above the list table was
    // reduced to a compact chip strip in the toolbar by issue #366 item 1.
    // 6 primary chips render inline; the remaining 6 overflow kinds live
    // behind a `+ More` popover.
    await gotoProvision(page, 'cloud?view=list')
    const chips = page.getByTestId('cloud-kind-chips')
    await expect(chips).toBeVisible()
    const primaryChips = chips.locator('button[data-kind]')
    await expect(primaryChips).toHaveCount(6)
    await expect(page.getByTestId('cloud-kind-chip-more')).toBeVisible()
  })

  test('every data-backed page exposes a + New CTA in the header (#349)', async ({ page }) => {
    // Subset of CASES that have CRUD wiring today (Phase A.2 of #347).
    // Placeholder pages (Services / Ingresses / DNS Zones / Storage
    // Classes) are gated on #321 and intentionally omit the CTA.
    const dataBackedWithCtaSuffixes = [
      { suffix: 'compute/clusters', testId: 'cloud-clusters' },
      { suffix: 'compute/vclusters', testId: 'cloud-vclusters' },
      { suffix: 'compute/node-pools', testId: 'cloud-node-pools' },
      { suffix: 'compute/worker-nodes', testId: 'cloud-worker-nodes' },
      { suffix: 'network/load-balancers', testId: 'cloud-load-balancers' },
      { suffix: 'storage/pvcs', testId: 'cloud-pvcs' },
      { suffix: 'storage/buckets', testId: 'cloud-buckets' },
      { suffix: 'storage/volumes', testId: 'cloud-volumes' },
    ] as const

    for (const c of dataBackedWithCtaSuffixes) {
      await gotoProvision(page, `cloud/${c.suffix}`)
      const cta = page.getByTestId(`${c.testId}-new-btn`)
      await expect(cta, `+ New CTA must be visible on ${c.suffix}`).toBeVisible()
    }
  })

  test('every row exposes a kebab menu with Edit + Delete (#349)', async ({ page }) => {
    const rowsWithActions = [
      { suffix: 'compute/clusters', rowId: 'cloud-clusters-row-cluster-eu-central-primary' },
      { suffix: 'compute/vclusters', rowId: 'cloud-vclusters-row-vc-eu-central-dmz' },
      { suffix: 'compute/node-pools', rowId: 'cloud-node-pools-row-pool-eu-cp' },
      { suffix: 'compute/worker-nodes', rowId: 'cloud-worker-nodes-row-node-eu-cp-0' },
      { suffix: 'network/load-balancers', rowId: 'cloud-load-balancers-row-lb-eu-central-edge' },
      { suffix: 'storage/pvcs', rowId: 'cloud-pvcs-row-pvc-postgres-data' },
      { suffix: 'storage/buckets', rowId: 'cloud-buckets-row-bucket-backups' },
      { suffix: 'storage/volumes', rowId: 'cloud-volumes-row-vol-postgres-eu' },
    ] as const

    for (const c of rowsWithActions) {
      await gotoProvision(page, `cloud/${c.suffix}`)
      const trigger = page.getByTestId(`${c.rowId}-actions-trigger`)
      await expect(trigger, `kebab on ${c.suffix} → ${c.rowId}`).toBeVisible()
      await trigger.click()
      await expect(page.getByTestId(`${c.rowId}-actions-edit`)).toBeVisible()
      await expect(page.getByTestId(`${c.rowId}-actions-delete`)).toBeVisible()
      await page.keyboard.press('Escape')
    }
  })

  test('captures 1440×900 screenshots of every list page', async ({ page }) => {
    // 12 list pages × ~3s per navigation+redirect+settle blows past
    // the default 30s test timeout. Bump explicitly so the screenshot
    // sweep has headroom across all cases without relying on the
    // global config.
    test.setTimeout(120_000)
    for (const c of CASES) {
      await gotoProvision(page, `cloud/${c.category}/${c.child}`)
      await page.waitForSelector(`[data-testid=${c.pageTestId}]`, { timeout: 10_000 })
      // Wait for the data-loaded surface so the screenshot captures
      // populated rows / drawer-ready state rather than the brief
      // "Loading…" placeholder. Falls back to either the seeded first
      // row (data-backed pages) or the empty-state container
      // (placeholder pages).
      const settledSelector = c.placeholder
        ? `[data-testid="${c.pageTestId.replace('-page', '-empty')}"]`
        : `[data-testid="${c.firstRowId}"]`
      await page.waitForSelector(settledSelector, { timeout: 10_000 }).catch(() => {})
      await page.waitForTimeout(150)
      await page.screenshot({
        path: `e2e/screenshots/p3-cloud-${c.category}-${c.child}.png`,
        fullPage: false,
      })
    }
  })
})
