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

const CHILD_NAME = 'AssignKindnessChild'
const KIND1_NAME = 'AssignTestKindness1'

async function createTestChild(request: APIRequestContext, name: string): Promise<string> {
  await request.put('/api/child/add', { data: { name, age: 8 } })
  const res = await request.get('/api/child/list')
  const data = (await res.json()) as { children?: { name: string; id: string }[] }
  return data.children?.find((c) => c.name === name)?.id ?? ''
}

async function createTestTask(
  request: APIRequestContext,
  name: string,
  type: 'chore' | 'kindness' | 'penalty',
): Promise<string> {
  await request.put('/api/task/add', { data: { name, points: 5, type } })
  const res = await request.get('/api/task/list')
  const data = (await res.json()) as { tasks?: { name: string; id: string }[] }
  return data.tasks?.find((t) => t.name === name)?.id ?? ''
}

test.describe('Kindness act assignment', () => {
  test.describe.configure({ mode: 'serial' })

  let childId = ''
  let kind1Id = ''

  test.beforeAll(async ({ request }) => {
    // Clean up any stale child from a previous run
    const listRes = await request.get('/api/child/list')
    const listData = await listRes.json()
    for (const c of listData.children ?? []) {
      if (c.name === CHILD_NAME) await request.delete(`/api/child/${c.id}`)
    }

    // Clean up any stale test task from a previous run
    const taskRes = await request.get('/api/task/list')
    const taskData = await taskRes.json()
    for (const t of taskData.tasks ?? []) {
      if (t.name === KIND1_NAME) await request.delete(`/api/task/${t.id}`)
    }

    childId = await createTestChild(request, CHILD_NAME)
    kind1Id = await createTestTask(request, KIND1_NAME, 'kindness')
  })

  test.afterAll(async ({ request }) => {
    if (childId) await request.delete(`/api/child/${childId}`)
    if (kind1Id) await request.delete(`/api/task/${kind1Id}`)
  })

  test('"Assign Kindness Acts" button navigates to the kindness assign view', async ({ page }) => {
    await page.goto(`/parent/${childId}`)
    await expect(page.getByRole('button', { name: 'Assign Kindness Acts' })).toBeVisible()

    await page.getByRole('button', { name: 'Assign Kindness Acts' }).click()
    await page.waitForURL(new RegExp(`/parent/${childId}/assign-kindness(\\?|$)`))

    await expect(page.getByRole('heading', { name: 'Assign Kindness Acts' })).toBeVisible()

    // Test-specific kindness act is listed
    await expect(page.getByText(KIND1_NAME, { exact: true })).toBeVisible()

    // Fresh child — nothing pre-checked
    await expect(
      page.locator('.list-row').filter({ hasText: KIND1_NAME }).locator('.list-checkbox'),
    ).not.toBeChecked()
  })

  test('Select a kindness act and submit — item appears in ParentView', async ({ page }) => {
    await page.goto(`/parent/${childId}`)
    await page.getByRole('button', { name: 'Assign Kindness Acts' }).click()
    await page.waitForURL(new RegExp(`/parent/${childId}/assign-kindness(\\?|$)`))
    await expect(page.getByRole('heading', { name: 'Assign Kindness Acts' })).toBeVisible()

    await page.getByText(KIND1_NAME, { exact: true }).click()
    await expect(
      page.locator('.list-row').filter({ hasText: KIND1_NAME }).locator('.list-checkbox'),
    ).toBeChecked()

    await page.getByRole('button', { name: 'Submit' }).click()
    await page.waitForURL(new RegExp(`/parent/${childId}$`))

    await expect(page.getByRole('button', { name: 'Assign Kindness Acts' })).toBeVisible()
    await expect(page.getByText(KIND1_NAME)).toBeVisible()
  })

  test('Re-opening assign view shows the assigned item as pre-checked', async ({ page }) => {
    await page.goto(`/parent/${childId}/assign-kindness`)
    await expect(page.getByRole('heading', { name: 'Assign Kindness Acts' })).toBeVisible()

    await expect(
      page.locator('.list-row').filter({ hasText: KIND1_NAME }).locator('.list-checkbox'),
    ).toBeChecked()
  })

  test('Uncheck the kindness act and submit — item is removed from ParentView', async ({
    page,
  }) => {
    await page.goto(`/parent/${childId}`)
    await page.getByRole('button', { name: 'Assign Kindness Acts' }).click()
    await page.waitForURL(new RegExp(`/parent/${childId}/assign-kindness(\\?|$)`))
    await expect(page.getByRole('heading', { name: 'Assign Kindness Acts' })).toBeVisible()

    // Uncheck the previously assigned item
    await page.getByText(KIND1_NAME, { exact: true }).click()
    await expect(
      page.locator('.list-row').filter({ hasText: KIND1_NAME }).locator('.list-checkbox'),
    ).not.toBeChecked()

    await page.getByRole('button', { name: 'Submit' }).click()
    await page.waitForURL(new RegExp(`/parent/${childId}$`))

    await expect(page.getByRole('button', { name: 'Assign Kindness Acts' })).toBeVisible()
    await expect(page.getByText(KIND1_NAME)).not.toBeVisible()
  })

  test('Cancel does not persist selection changes', async ({ page }) => {
    await page.goto(`/parent/${childId}`)
    await page.getByRole('button', { name: 'Assign Kindness Acts' }).click()
    await page.waitForURL(new RegExp(`/parent/${childId}/assign-kindness(\\?|$)`))
    await expect(page.getByRole('heading', { name: 'Assign Kindness Acts' })).toBeVisible()

    // Check the item
    await page.getByText(KIND1_NAME, { exact: true }).click()
    await expect(
      page.locator('.list-row').filter({ hasText: KIND1_NAME }).locator('.list-checkbox'),
    ).toBeChecked()

    // Cancel instead of submitting
    await page.getByRole('button', { name: 'Cancel' }).click()
    await page.waitForURL(new RegExp(`/parent/${childId}$`))

    // Navigate back and verify the selection was not saved
    await page.goto(`/parent/${childId}/assign-kindness`)
    await expect(page.getByRole('heading', { name: 'Assign Kindness Acts' })).toBeVisible()
    await expect(
      page.locator('.list-row').filter({ hasText: KIND1_NAME }).locator('.list-checkbox'),
    ).not.toBeChecked()
  })
})
