import { expect, test, type Locator, type Page } from '@playwright/test'
import { startFixtureCollector, type FixtureCollector } from './fixture-collector'
import { ADAPTER_STATUSES, ALL_ITEMS, ALL_PANELS } from './fixtures/collector-fixtures'

type UiState = 'present' | 'enabled' | 'disabled' | 'editable'

interface RouteInvariant {
  route: string
  name: string
  locator: (page: Page) => Locator
}

interface UiMatrixEntry extends RouteInvariant {
  state: UiState
}

const ROUTE_INVARIANTS: RouteInvariant[] = [
  { route: '/', name: 'overview needs-you-now card', locator: (page) => page.getByRole('heading', { level: 4, name: 'Needs you now' }) },
  { route: '/inbox', name: 'inbox heading', locator: (page) => page.getByRole('heading', { level: 4, name: 'Inbox' }) },
  { route: '/plans', name: 'plans heading', locator: (page) => page.getByRole('heading', { level: 4, name: 'Plan runs' }) },
  { route: '/agents', name: 'agents heading', locator: (page) => page.getByRole('heading', { level: 4, name: 'Agent fleet' }) },
  { route: '/ci', name: 'CI runners panel', locator: (page) => page.getByRole('heading', { level: 4, name: 'CI runners' }) },
  { route: '/bots', name: 'bots heading', locator: (page) => page.getByRole('heading', { level: 4, name: 'Bots (Botmaster)' }) },
  { route: '/limits', name: 'limits heading', locator: (page) => page.getByRole('heading', { level: 4, name: 'Limits & Spend' }) },
  { route: '/gates', name: 'gates heading', locator: (page) => page.getByRole('heading', { level: 4, name: 'Gates' }) },
  { route: '/projects', name: 'projects repository', locator: (page) => page.getByRole('heading', { level: 4, name: /^multideal/ }) },
  { route: '/projects/multideal', name: 'project detail criterion', locator: (page) => page.getByText('AC-01').first() },
  { route: '/settings', name: 'settings heading', locator: (page) => page.getByRole('heading', { level: 4, name: 'Project colors' }) },
  { route: '/decisions', name: 'decisions heading', locator: (page) => page.locator('#dashboard-main').getByRole('heading', { level: 2, name: 'Decisions' }) },
  { route: '/map', name: 'map canvas', locator: (page) => page.getByTestId('map-canvas') },
]

const ELEMENT_MATRIX: UiMatrixEntry[] = [
  { route: '/settings', name: 'project color input', locator: (page) => page.locator('[data-project-color-input="multideal"]'), state: 'editable' },
  { route: '/settings', name: 'save project colors', locator: (page) => page.locator('[data-save-project-colors]'), state: 'enabled' },
  { route: '/inbox', name: 'non-gateway action', locator: (page) => page.getByRole('button', { name: 'Open run' }), state: 'enabled' },
  { route: '/inbox', name: 'reap action', locator: (page) => page.locator('[data-inbox-item-id="orphan-agent"]').getByRole('button', { name: 'Reap' }), state: 'enabled' },
]

let collector: FixtureCollector

test.describe.configure({ mode: 'serial' })

test.beforeAll(async () => {
  collector = await startFixtureCollector({ panels: ALL_PANELS, adapters: ADAPTER_STATUSES, items: ALL_ITEMS })
})

test.afterAll(async () => {
  await collector.close()
})

async function expectState(locator: Locator, state: UiState): Promise<void> {
  if (state === 'present') return expect(locator).toBeVisible()
  if (state === 'enabled') return expect(locator).toBeEnabled()
  if (state === 'disabled') return expect(locator).toBeDisabled()
  return expect(locator).toBeEditable()
}

for (const invariant of ROUTE_INVARIANTS) {
  test(`${invariant.route} renders ${invariant.name} without runtime failures`, async ({ page }) => {
    const runtimeFailures: string[] = []
    page.on('console', (message) => {
      if (message.type() === 'error') runtimeFailures.push(message.text())
    })
    page.on('pageerror', (error) => runtimeFailures.push(error.message))
    page.on('response', (response) => {
      if (response.url().includes('/api/collector/') && !response.ok()) {
        runtimeFailures.push(`${response.status()} ${response.url()}`)
      }
    })

    await page.goto(invariant.route)
    await expect(invariant.locator(page)).toBeVisible()
    expect(runtimeFailures).toEqual([])
  })
}

for (const entry of ELEMENT_MATRIX) {
  test(`${entry.route} ${entry.name} is ${entry.state}`, async ({ page }) => {
    await page.goto(entry.route)
    await expectState(entry.locator(page), entry.state)
  })
}

test('/inbox destructive confirmation controls are enabled before submission', async ({ page }) => {
  await page.goto('/inbox')
  await page.locator('[data-inbox-item-id="orphan-agent"]').getByRole('button', { name: 'Reap' }).click()

  await expect(page.locator('[data-action-confirm]')).toBeVisible()
  await expect(page.locator('[data-action-confirm]').getByRole('button', { name: 'Cancel' })).toBeEnabled()
  await expect(page.locator('[data-action-confirm-submit]')).toBeEnabled()
})
