// spec: e2e/plans/user-profile.plan.md

import { test, expect, type APIRequestContext } from '@playwright/test'
import { E2E_PIN } from '../../e2e-constants'

const BACKEND = 'http://localhost:5000'
const NEW_PIN = '5678'

async function openAccountSection(page: import('@playwright/test').Page): Promise<void> {
  const accountHeader = page
    .locator('.profile-section')
    .filter({ has: page.locator('.section-title', { hasText: 'Account' }) })
    .locator('.section-header')
  if ((await accountHeader.getAttribute('aria-expanded')) === 'false') {
    await accountHeader.click()
  }
  await page.locator('#section-account').waitFor({ state: 'visible' })
}

async function setPinDirectly(request: APIRequestContext, pin: string): Promise<void> {
  // Request a new code, retrieve it via test endpoint, verify it, then set the pin
  await request.post(`${BACKEND}/user/request-pin-setup`)
  const codeRes = await request.get(`${BACKEND}/user/e2e-get-pin-code`)
  const { code } = await codeRes.json()
  await request.post(`${BACKEND}/user/verify-pin-setup`, { data: { code } })
  await request.post(`${BACKEND}/user/set-pin`, { data: { pin } })
}

test.describe('User Profile – Change Parent PIN', () => {
  test.describe.configure({ mode: 'serial' })

  test.afterAll(async ({ request }) => {
    // Restore original PIN so subsequent test runs start fresh
    await setPinDirectly(request, E2E_PIN)
  })

  test('Change Parent PIN link navigates to PIN setup page', async ({ page }) => {
    await page.goto('/parent/profile')
    await openAccountSection(page)

    await page.getByRole('button', { name: 'Change Parent PIN' }).click()

    await expect(page).toHaveURL(/\/parent\/pin-setup/)
    await expect(page.getByRole('heading', { name: 'Set up your Parent PIN' })).toBeVisible()
  })

  test('Back from PIN setup page returns to profile', async ({ page }) => {
    // Navigate from the profile page so browser history exists
    await page.goto('/parent/profile')
    await openAccountSection(page)
    await page.getByRole('button', { name: 'Change Parent PIN' }).click()
    await expect(page).toHaveURL(/\/parent\/pin-setup/)

    await page.goBack()

    await expect(page).toHaveURL(/\/parent\/profile/)
  })

  test('Send Verification Code advances to step 2', async ({ page }) => {
    await page.goto('/parent/pin-setup')

    await page.getByRole('button', { name: 'Send Verification Code' }).click()

    await expect(page.getByRole('heading', { name: 'Enter Verification Code' })).toBeVisible()

    const codeInput = page.getByPlaceholder('6-digit code')
    await expect(codeInput).toBeVisible()

    // Verify Code is disabled while input is empty
    await expect(page.getByRole('button', { name: 'Verify Code' })).toBeDisabled()
  })

  test('Resend Code button appears after delay', async ({ page }) => {
    await page.goto('/parent/pin-setup')

    await page.getByRole('button', { name: 'Send Verification Code' }).click()
    await expect(page.getByRole('heading', { name: 'Enter Verification Code' })).toBeVisible()

    // According to the component, resend appears after 10 seconds
    await expect(page.getByRole('button', { name: 'Resend Code' })).toBeVisible({ timeout: 15000 })
  })

  test('Invalid code shows error', async ({ page }) => {
    await page.goto('/parent/pin-setup')
    await page.getByRole('button', { name: 'Send Verification Code' }).click()
    await expect(page.getByRole('heading', { name: 'Enter Verification Code' })).toBeVisible()

    await page.getByPlaceholder('6-digit code').fill('ZZZZZZ')
    await page.getByRole('button', { name: 'Verify Code' }).click()

    await expect(page.getByText(/invalid code/i)).toBeVisible()
  })

  test('Valid code advances to step 3 (Create PIN)', async ({ page, request }) => {
    await page.goto('/parent/pin-setup')
    await page.getByRole('button', { name: 'Send Verification Code' }).click()
    await expect(page.getByRole('heading', { name: 'Enter Verification Code' })).toBeVisible()

    // Retrieve the code via the test-only endpoint
    const codeRes = await request.get(`${BACKEND}/user/e2e-get-pin-code`)
    const { code } = await codeRes.json()

    await page.getByPlaceholder('6-digit code').fill(code)
    await page.getByRole('button', { name: 'Verify Code' }).click()

    await expect(page.getByRole('heading', { name: 'Create Parent PIN' })).toBeVisible()
    await expect(page.getByPlaceholder('New PIN')).toBeVisible()
    await expect(page.getByPlaceholder('Confirm PIN')).toBeVisible()
    await expect(page.getByRole('button', { name: 'Set PIN' })).toBeDisabled()
  })

  test('Set PIN disabled when PINs do not match', async ({ page, request }) => {
    await page.goto('/parent/pin-setup')
    await page.getByRole('button', { name: 'Send Verification Code' }).click()
    await expect(page.getByRole('heading', { name: 'Enter Verification Code' })).toBeVisible()

    const codeRes = await request.get(`${BACKEND}/user/e2e-get-pin-code`)
    const { code } = await codeRes.json()
    await page.getByPlaceholder('6-digit code').fill(code)
    await page.getByRole('button', { name: 'Verify Code' }).click()
    await expect(page.getByRole('heading', { name: 'Create Parent PIN' })).toBeVisible()

    await page.getByPlaceholder('New PIN').fill('1111')
    await page.getByPlaceholder('Confirm PIN').fill('2222')

    await expect(page.getByRole('button', { name: 'Set PIN' })).toBeDisabled()
  })

  test('Set PIN disabled for fewer than 4 digits', async ({ page, request }) => {
    await page.goto('/parent/pin-setup')
    await page.getByRole('button', { name: 'Send Verification Code' }).click()
    await expect(page.getByRole('heading', { name: 'Enter Verification Code' })).toBeVisible()

    const codeRes = await request.get(`${BACKEND}/user/e2e-get-pin-code`)
    const { code } = await codeRes.json()
    await page.getByPlaceholder('6-digit code').fill(code)
    await page.getByRole('button', { name: 'Verify Code' }).click()
    await expect(page.getByRole('heading', { name: 'Create Parent PIN' })).toBeVisible()

    await page.getByPlaceholder('New PIN').fill('12')
    await page.getByPlaceholder('Confirm PIN').fill('12')

    await expect(page.getByRole('button', { name: 'Set PIN' })).toBeDisabled()
  })

  test('Set PIN succeeds with matching 4-digit PIN – shows success step', async ({
    page,
    request,
  }) => {
    await page.goto('/parent/pin-setup')
    await page.getByRole('button', { name: 'Send Verification Code' }).click()
    await expect(page.getByRole('heading', { name: 'Enter Verification Code' })).toBeVisible()

    const codeRes = await request.get(`${BACKEND}/user/e2e-get-pin-code`)
    const { code } = await codeRes.json()
    await page.getByPlaceholder('6-digit code').fill(code)
    await page.getByRole('button', { name: 'Verify Code' }).click()
    await expect(page.getByRole('heading', { name: 'Create Parent PIN' })).toBeVisible()

    await page.getByPlaceholder('New PIN').fill(NEW_PIN)
    await page.getByPlaceholder('Confirm PIN').fill(NEW_PIN)
    await expect(page.getByRole('button', { name: 'Set PIN' })).toBeEnabled()
    await page.getByRole('button', { name: 'Set PIN' }).click()

    await expect(page.getByRole('heading', { name: 'Parent PIN Set!' })).toBeVisible()
    await expect(page.getByRole('button', { name: 'Back', exact: true })).toBeVisible()
  })

  test('Back from success step exits parent mode and goes to child selector', async ({
    page,
    request,
  }) => {
    await page.goto('/parent/pin-setup')
    await page.getByRole('button', { name: 'Send Verification Code' }).click()
    await expect(page.getByRole('heading', { name: 'Enter Verification Code' })).toBeVisible()

    const codeRes = await request.get(`${BACKEND}/user/e2e-get-pin-code`)
    const { code } = await codeRes.json()
    await page.getByPlaceholder('6-digit code').fill(code)
    await page.getByRole('button', { name: 'Verify Code' }).click()
    await expect(page.getByRole('heading', { name: 'Create Parent PIN' })).toBeVisible()

    await page.getByPlaceholder('New PIN').fill(NEW_PIN)
    await page.getByPlaceholder('Confirm PIN').fill(NEW_PIN)
    await page.getByRole('button', { name: 'Set PIN' }).click()
    await expect(page.getByRole('heading', { name: 'Parent PIN Set!' })).toBeVisible()

    await page.getByRole('button', { name: 'Back', exact: true }).click()

    await expect(page).toHaveURL(/\/child(\/|$)/)
    // Parent mode exited – "Parent login" button visible instead of parent menu
    await expect(page.getByRole('button', { name: 'Parent login' })).toBeVisible()
  })
})
