// spec: e2e/plans/parent-notifications.plan.md §10

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

function digestToggle(page: Page) {
  return page
    .locator('.toggle-field-row')
    .filter({ has: page.locator('.toggle-field-label', { hasText: 'Daily Digest' }) })
    .locator('button.toggle-btn')
}

function pushToggle(page: Page) {
  return page
    .locator('.toggle-field-row')
    .filter({ has: page.locator('.toggle-field-label', { hasText: 'Push Notifications' }) })
    .locator('button.toggle-btn')
}

async function openNotificationsSection(page: Page): Promise<void> {
  const header = page
    .locator('.profile-section')
    .filter({ has: page.locator('.section-title', { hasText: 'Notifications' }) })
    .locator('.section-header')
  if ((await header.getAttribute('aria-expanded')) === 'false') {
    await header.click()
  }
  await page.locator('#section-notifications').waitFor({ state: 'visible' })
}

test.describe('User Profile Notification Settings', () => {
  test.describe.configure({ mode: 'serial' })

  // ---------------------------------------------------------------------------
  // 10.1 Email Digest toggle is visible on User Profile page
  // ---------------------------------------------------------------------------
  test('Email Digest toggle is visible on User Profile page', async ({ page }) => {
    await page.goto('/parent/profile')
    await openNotificationsSection(page)
    await expect(digestToggle(page)).toBeVisible({ timeout: 5000 })
  })

  // ---------------------------------------------------------------------------
  // 10.2 Email Digest toggle initialises from the server value
  // ---------------------------------------------------------------------------
  test('Email Digest toggle initialises from the server value', async ({ page, request }) => {
    // Set known state: enabled
    await request.put('/api/user/profile', { data: { email_digest_enabled: true } })
    await page.goto('/parent/profile')
    await openNotificationsSection(page)
    await expect(digestToggle(page)).toHaveAttribute('aria-pressed', 'true', { timeout: 5000 })

    // Set known state: disabled
    await request.put('/api/user/profile', { data: { email_digest_enabled: false } })
    await page.reload()
    await openNotificationsSection(page)
    await expect(digestToggle(page)).toHaveAttribute('aria-pressed', 'false', { timeout: 5000 })

    // Restore default
    await request.put('/api/user/profile', { data: { email_digest_enabled: true } })
  })

  // ---------------------------------------------------------------------------
  // 10.3 Toggling Email Digest off sends email_digest_enabled: false to API
  // ---------------------------------------------------------------------------
  test('Toggling Email Digest off sends correct API payload', async ({ page, request }) => {
    await request.put('/api/user/profile', { data: { email_digest_enabled: true } })
    await page.goto('/parent/profile')
    await openNotificationsSection(page)
    // Wait for profile to load and toggle to reflect server state
    await expect(digestToggle(page)).toHaveAttribute('aria-pressed', 'true', { timeout: 5000 })

    let capturedBody: Record<string, unknown> | null = null
    await page.route('**/api/user/profile', async (route) => {
      if (route.request().method() === 'PUT') {
        capturedBody = JSON.parse(route.request().postData() ?? '{}')
      }
      await route.continue()
    })

    await digestToggle(page).click()

    // Toggles auto-save; wait for the PUT and verify the payload.
    await page.waitForTimeout(500)
    expect(capturedBody).not.toBeNull()
    expect((capturedBody as Record<string, unknown>)['email_digest_enabled']).toBe(false)
    await expect(digestToggle(page)).toHaveAttribute('aria-pressed', 'false', { timeout: 3000 })

    // Restore
    await request.put('/api/user/profile', { data: { email_digest_enabled: true } })
  })

  // ---------------------------------------------------------------------------
  // 10.4 Toggling Email Digest on sends email_digest_enabled: true to API
  // ---------------------------------------------------------------------------
  test('Toggling Email Digest on sends correct API payload', async ({ page, request }) => {
    await request.put('/api/user/profile', { data: { email_digest_enabled: false } })
    await page.goto('/parent/profile')
    await openNotificationsSection(page)
    // Wait for profile to load and toggle to reflect server state
    await expect(digestToggle(page)).toHaveAttribute('aria-pressed', 'false', { timeout: 5000 })

    let capturedBody: Record<string, unknown> | null = null
    await page.route('**/api/user/profile', async (route) => {
      if (route.request().method() === 'PUT') {
        capturedBody = JSON.parse(route.request().postData() ?? '{}')
      }
      await route.continue()
    })

    await digestToggle(page).click()

    await page.waitForTimeout(500)
    expect(capturedBody).not.toBeNull()
    expect((capturedBody as Record<string, unknown>)['email_digest_enabled']).toBe(true)
    await expect(digestToggle(page)).toHaveAttribute('aria-pressed', 'true', { timeout: 3000 })

    // Restore
    await request.put('/api/user/profile', { data: { email_digest_enabled: true } })
  })

  // ---------------------------------------------------------------------------
  // 10.5 Push Notifications toggle is visible on User Profile page
  // ---------------------------------------------------------------------------
  test('Push Notifications toggle is visible on User Profile page', async ({ page }) => {
    await page.goto('/parent/profile')
    await openNotificationsSection(page)
    await expect(pushToggle(page)).toBeVisible({ timeout: 5000 })
  })

  // ---------------------------------------------------------------------------
  // 10.6 Push Notifications toggle initialises to off when no subscription exists
  // ---------------------------------------------------------------------------
  test('Push Notifications toggle initialises to off when no subscription exists', async ({
    page,
  }) => {
    // Do NOT grant notifications permission — toggle should start unchecked
    await page.goto('/parent/profile')
    await openNotificationsSection(page)
    const toggle = pushToggle(page)
    await expect(toggle).toBeVisible({ timeout: 5000 })
    // Either aria-pressed="false" or disabled (when browser denies permissions)
    const ariaPressed = await toggle.getAttribute('aria-pressed')
    expect(ariaPressed).toBe('false')
  })

  // ---------------------------------------------------------------------------
  // 10.8 Push Notifications toggle is disabled when browser permission is denied
  // ---------------------------------------------------------------------------
  test('Push Notifications toggle is disabled when browser permission is denied', async ({
    page,
    context,
  }) => {
    // Do not grant permission (leave as denied/prompt)
    await context.clearPermissions()
    await page.goto('/parent/profile')
    await openNotificationsSection(page)
    const toggle = pushToggle(page)
    await expect(toggle).toBeVisible({ timeout: 5000 })
    // When permission is denied, the toggle should be disabled or aria-pressed="false"
    const isDisabled = await toggle.isDisabled().catch(() => false)
    const ariaPressed = await toggle.getAttribute('aria-pressed')
    // Either disabled or not pressed — permission denied prevents enabling it
    expect(isDisabled || ariaPressed === 'false').toBe(true)
  })
})
