// spec: e2e/plans/create-child.plan.md

import { test, expect } from '@playwright/test'
import path from 'path'
import { fileURLToPath } from 'url'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const TEST_IMAGE = path.join(__dirname, '../../.resources/crown.png')

async function deleteNamedChildren(request: any, names: string[]) {
  const res = await request.get('/api/child/list')
  const data = await res.json()
  for (const child of data.children ?? []) {
    if (names.includes(child.name)) {
      await request.delete(`/api/child/${child.id}`)
    }
  }
}

async function deleteAllChildren(request: any) {
  const res = await request.get('/api/child/list')
  const data = await res.json()
  for (const child of data.children ?? []) {
    await request.delete(`/api/child/${child.id}`)
  }
}

test.describe('Create Child', () => {
  // Serial mode: the 'empty state' test calls deleteAllChildren() which would
  // race against sibling tests creating children if they ran in parallel.
  test.describe.configure({ mode: 'serial' })

  test.beforeEach(async ({ page }, testInfo) => {
    test.skip(testInfo.project.name === 'chromium-no-pin', 'Requires parent-authenticated mode')
  })

  test('Create a child with name and age only', async ({ page, request }) => {
    await deleteNamedChildren(request, ['Alice'])

    // 1. Navigate to app root - router redirects to /parent (children list) when parent-authenticated
    await page.goto('/')
    await expect(page).toHaveURL('/parent')

    // 2. Click the 'Add Child' FAB
    await page.getByRole('button', { name: 'Add Child' }).click()
    await expect(page.getByRole('heading', { name: 'Create Child' })).toBeVisible()
    const nameInput = page.getByLabel('Name')
    const ageInput = page.getByLabel('Age')
    const createButton = page.getByRole('button', { name: 'Create' })

    await expect(nameInput).toBeVisible()
    await expect(ageInput).toBeVisible()

    // Submit should be disabled until all required fields are valid.
    await expect(createButton).toBeDisabled()

    // 3. Enter 'Alice' in the Name field
    await nameInput.fill('Alice')
    await expect(createButton).toBeDisabled()

    // 4. Enter '8' in the Age field
    await ageInput.fill('8')

    // 5. Leave Image as default and click Create
    // Use toPass() to handle SSE-triggered form resets from parallel tests
    await expect(async () => {
      if (new URL(page.url()).pathname === '/parent') return
      await deleteNamedChildren(request, ['Alice'])
      await nameInput.fill('Alice')
      await ageInput.fill('8')
      await expect(createButton).toBeEnabled()
      await createButton.click({ timeout: 2000 })
      await expect(page).toHaveURL('/parent', { timeout: 5000 })
    }).toPass({ timeout: 20000 })
    await expect(page.locator('.error')).not.toBeVisible()
    await expect(page).toHaveURL('/parent')
    await expect(page.getByText('Alice')).toBeVisible()
  })

  test('Create a child via the inline Create button in empty state', async ({ page, request }) => {
    // 1. Navigate to empty state and click inline Create.
    //    Retry-loop handles SSE-triggered re-renders: a parallel test may add a child
    //    between deleteAllChildren() and the click, detaching the empty-state button.
    await expect(async () => {
      await deleteAllChildren(request)
      await page.goto('/')
      await expect(page.getByText('No children')).toBeVisible({ timeout: 5000 })
      await page.getByRole('button', { name: 'Create' }).click({ timeout: 5000 })
      await expect(page.getByRole('heading', { name: 'Create Child' })).toBeVisible({
        timeout: 5000,
      })
    }).toPass({ timeout: 30000 })

    // 2. Enter 'Bob' and '10', then submit
    const nameInput = page.getByLabel('Name')
    const ageInput = page.getByLabel('Age')
    const createButton = page.getByRole('button', { name: 'Create' })

    // Submit should be disabled until all required fields are valid
    await expect(createButton).toBeDisabled()

    await nameInput.fill('Bob')
    await expect(createButton).toBeDisabled()

    await ageInput.fill('10')

    // Handle async form initialization race and SSE-triggered form resets
    await expect(async () => {
      if (new URL(page.url()).pathname === '/parent') return
      await deleteNamedChildren(request, ['Bob'])
      await nameInput.fill('Bob')
      await ageInput.fill('10')
      await expect(createButton).toBeEnabled()
      await createButton.click({ timeout: 2000 })
      await expect(page).toHaveURL('/parent', { timeout: 5000 })
    }).toPass({ timeout: 20000 })
    await expect(page.locator('.error')).not.toBeVisible()
    await expect(page).toHaveURL('/parent')
    await expect(page.getByText('Bob')).toBeVisible()
  })

  test('Create a child with a custom uploaded image', async ({ page, request }) => {
    await deleteNamedChildren(request, ['Grace'])

    // 1. Navigate to app root - router redirects to /parent (children list)
    await page.goto('/')
    await page.getByRole('button', { name: 'Add Child' }).click()
    await expect(page.getByRole('heading', { name: 'Create Child' })).toBeVisible()

    // 2. Enter 'Grace' and '6'
    const nameInput = page.getByLabel('Name')
    const ageInput = page.getByLabel('Age')
    const createButton = page.getByRole('button', { name: 'Create' })

    // Submit should be disabled until all required fields are valid
    await expect(createButton).toBeDisabled()

    await nameInput.fill('Grace')
    await expect(createButton).toBeDisabled()

    await ageInput.fill('6')

    // 3. Upload a local image file via 'Add from device'
    const fileChooserPromise = page.waitForEvent('filechooser')
    await page.getByRole('button', { name: 'Add from device' }).click()
    const fileChooser = await fileChooserPromise
    await fileChooser.setFiles(TEST_IMAGE)

    // Handle async form initialization race and SSE-triggered form resets
    await expect(async () => {
      if (new URL(page.url()).pathname === '/parent') return
      await deleteNamedChildren(request, ['Grace'])
      await nameInput.fill('Grace')
      await ageInput.fill('6')
      await expect(createButton).toBeEnabled()
      await createButton.click({ timeout: 2000 })
      await expect(page).toHaveURL('/parent', { timeout: 5000 })
    }).toPass({ timeout: 20000 })
    await expect(page.locator('.error')).not.toBeVisible()
    await expect(page).toHaveURL('/parent')
    await expect(page.getByText('Grace')).toBeVisible()
  })
})
