import { test, expect } from '@playwright/test'
import { loginAsOperator } from './helpers/auth.js'
import { listFailedPairings, ensureAtLeastOneFailedPairing } from './helpers/backend-api.js'

/**
 * Failed Pairings page e2e tests.
 *
 * NOTE: There is currently no public test-seed endpoint for failed_pairings.
 * Production rows are inserted by the backend pairing service when a real
 * pairing fails. These tests therefore rely on the database already containing
 * at least one row (any cause). If the table is empty the tests are skipped
 * with a clear TODO so the user can either:
 *   - run the real pairing flow once to generate real fixtures, or
 *   - add a backend test-only seed route (see helpers/backend-api.js).
 */

test.describe('Failed Pairings page', () => {
  test.beforeEach(async ({ page }) => {
    await loginAsOperator(page)
  })

  test('renders the table when at least one row exists', async ({ page }) => {
    let seeded
    try {
      seeded = await ensureAtLeastOneFailedPairing()
    } catch (e) {
      test.skip(true, `No failed-pairings rows in DB. ${e.message}`)
      return
    }

    await page.goto('/failed-pairings')
    await expect(page.getByRole('heading', { name: 'Failed Pairings', level: 1 })).toBeVisible()

    // The table headers should always render once data has loaded.
    await expect(page.getByRole('columnheader', { name: 'Created' })).toBeVisible()
    await expect(page.getByRole('columnheader', { name: 'Cause' })).toBeVisible()
    await expect(page.getByRole('columnheader', { name: 'Operator Action' })).toBeVisible()

    // At least one data row (skip the header row).
    const dataRows = page.locator('table tbody tr')
    const count = await dataRows.count()
    expect(count).toBeGreaterThanOrEqual(1)

    // The "empty" placeholder row should NOT be visible when we have data.
    await expect(page.getByText('Belum ada data failed pairings.')).not.toBeVisible()

    // Sanity check — total label matches what the backend reports.
    await expect(page.getByText(`(${seeded.total} total)`)).toBeVisible()
  })

  test('cause-tag filter narrows the visible rows', async ({ page }) => {
    // We need rows of at least 2 distinct cause tags to make a meaningful
    // assertion about filtering. If the DB has fewer, skip with a clear
    // message rather than producing a fake-positive.
    const all = await listFailedPairings({ limit: 200 })
    const distinctCauses = [...new Set((all?.rows ?? []).map((r) => r.cause_tag))]
    if (distinctCauses.length < 2) {
      test.skip(
        true,
        `Need >=2 distinct cause_tags in failed_pairings to test filter. Found: ${distinctCauses.join(', ') || '(none)'}.`,
      )
      return
    }

    const targetCause = distinctCauses[0]
    const expectedFiltered = await listFailedPairings({ causeTags: [targetCause], limit: 200 })

    await page.goto('/failed-pairings')
    await expect(page.getByRole('heading', { name: 'Failed Pairings', level: 1 })).toBeVisible()

    // Capture pre-filter total — must be >= filtered total or assertion is bogus.
    const totalBefore = all.total
    expect(totalBefore).toBeGreaterThan(expectedFiltered.total)

    // Tick the cause checkbox. The filter section labels the checkbox with the
    // human label from PairingFailureCauseLabel — find it by its associated text.
    // Map the cause_tag to its label by re-importing the constants.
    const { PairingFailureCauseLabel } = await import(
      '../../src/core/constants.js'
    )
    const targetLabel = PairingFailureCauseLabel[targetCause]

    await page.getByRole('checkbox', { name: targetLabel }).check()

    // Expect the new total to match the API-computed expectation.
    await expect(page.getByText(`(${expectedFiltered.total} total)`)).toBeVisible()

    // And every visible row should reflect the chosen cause tag.
    const causeCells = page.locator('table tbody tr td:nth-child(4)')
    const visibleCount = await causeCells.count()
    expect(visibleCount).toBeGreaterThan(0)
    for (let i = 0; i < visibleCount; i++) {
      await expect(causeCells.nth(i)).toHaveText(targetLabel)
    }
  })
})
