import { test, expect } from '@playwright/test'
import { AuthHelper, generateTestEmail, generateTestPassword, TEST_LANGUAGE, fillInput } from '../helpers/auth'
import { createMailpitHelper } from '../helpers/mailpit'

/**
 * Complete end-to-end user journey tests
 * These tests verify entire workflows from registration to feature usage
 */

test.describe('Complete User Journeys', () => {
  test('new user can register and see verification message', async ({ page }) => {
    const auth = new AuthHelper(page)
    const testEmail = generateTestEmail('journey')
    const testPassword = generateTestPassword()

    // 1. Navigate to registration
    await page.goto('/auth/register')
    await page.waitForLoadState('networkidle')

    // 2. Fill and submit registration form
    await auth.register(testEmail, testPassword, 'Journey User')

    // 3. Should show verification required message (use heading to avoid strict mode violation)
    await expect(
      page.getByText(/Verifieer Je E-mail/i).first()
    ).toBeVisible({ timeout: 10000 })

    // 4. Email should be displayed
    await expect(page.getByText(testEmail)).toBeVisible()
  })

  test('user can navigate from login to registration and back', async ({ page }) => {
    // 1. Start at login page
    await page.goto('/auth')
    await page.waitForLoadState('networkidle')

    // 2. Click register link
    const registerLink = page.getByRole('link', { name: TEST_LANGUAGE.signUp })
    await registerLink.click()

    // 3. Should be on registration page
    await expect(page).toHaveURL(/.*\/auth\/register/)
    await expect(page.getByText(TEST_LANGUAGE.createAccount).first()).toBeVisible()

    // 4. Click back to login (uses Dutch "Inloggen")
    const loginLink = page.getByRole('link', { name: TEST_LANGUAGE.signIn })
    await loginLink.click()

    // 5. Should be back on login page
    await expect(page).toHaveURL(/.*\/auth$/)
    await expect(page.getByText(TEST_LANGUAGE.signIn).first()).toBeVisible()
  })

  test('user can access forgot password from login page', async ({ page }) => {
    // 1. Start at login page
    await page.goto('/auth')
    await page.waitForLoadState('networkidle')

    // 2. Click forgot password link
    const forgotLink = page.getByRole('link', { name: TEST_LANGUAGE.forgotPasswordLink })
    await forgotLink.click()

    // 3. Should be on forgot password page
    await expect(page).toHaveURL(/.*\/auth\/forgot-password/)
    await expect(page.getByText(TEST_LANGUAGE.forgotPassword).first()).toBeVisible()

    // 4. Submit email
    const emailInput = page.locator('input[type="email"]')
    const submitButton = page.locator('button[type="submit"]')

    await fillInput(emailInput, generateTestEmail('forgot-journey'))
    await submitButton.click()

    // 5. Should see success message (use heading to avoid strict mode violation)
    await expect(
      page.getByText(/E-mail Verstuurd/i).first()
    ).toBeVisible({ timeout: 10000 })
  })

  test('user can access magic link from login page', async ({ page }) => {
    // 1. Start at login page
    await page.goto('/auth')
    await page.waitForLoadState('networkidle')

    // 2. Click magic link button (rendered as a link, not button)
    const magicLinkButton = page.getByRole('link', { name: /magic link/i })
    await magicLinkButton.click()

    // 3. Should be on magic link page
    await expect(page).toHaveURL(/.*\/auth\/magic-link/)
    await expect(page.getByText(TEST_LANGUAGE.magicLink).first()).toBeVisible()

    // 4. Submit email
    const emailInput = page.locator('input[type="email"]')
    const submitButton = page.locator('button[type="submit"]')

    await fillInput(emailInput, generateTestEmail('magic-journey'))
    await submitButton.click()

    // 5. Should see success message (use heading to avoid strict mode violation)
    await expect(
      page.getByText(/Magic Link Verstuurd/i).first()
    ).toBeVisible({ timeout: 10000 })
  })

  test('complete password reset flow navigation', async ({ page }) => {
    // 1. Start at login
    await page.goto('/auth')
    await page.waitForLoadState('networkidle')

    // 2. Navigate to forgot password
    await page.getByRole('link', { name: TEST_LANGUAGE.forgotPasswordLink }).click()
    await expect(page).toHaveURL(/.*\/auth\/forgot-password/)

    // 3. Request reset
    const testEmail = generateTestEmail('reset-journey')
    const emailInput = page.locator('input[type="email"]')
    const submitButton = page.locator('button[type="submit"]')

    await fillInput(emailInput, testEmail)
    await submitButton.click()

    // 4. Should see success (use heading to avoid strict mode violation)
    await expect(
      page.getByText(/E-mail Verstuurd/i).first()
    ).toBeVisible({ timeout: 10000 })

    // 5. Navigate back to login from success page
    const backLink = page.getByRole('link', { name: TEST_LANGUAGE.backToLogin })
    await backLink.click()
    await expect(page).toHaveURL(/.*\/auth$/)
  })

  test('complete registration to dashboard flow (requires email verification)', async ({ page, request }) => {
    // Complete flow: Register → Verify Email → Auto-login → Dashboard
    const mailpit = createMailpitHelper(request)
    await mailpit.deleteAllMessages()

    const auth = new AuthHelper(page)
    const testEmail = generateTestEmail('full-journey')
    const testPassword = generateTestPassword()

    // 1. Register
    await auth.register(testEmail, testPassword, 'Full Journey User')
    await page.waitForLoadState('networkidle')

    // 2. Should show verification required message
    await expect(
      page.getByText(/Verifieer Je E-mail/i).first()
    ).toBeVisible({ timeout: 10000 })

    // 3. Wait for verification email and get verification link
    const verificationEmail = await mailpit.waitForEmail(testEmail, {
      subject: /verify/i,
      timeout: 10000
    })
    const verificationLink = await mailpit.getVerificationLink(verificationEmail.ID)
    expect(verificationLink).toBeTruthy()

    // 4. Click verification link
    await page.goto(verificationLink!)
    await page.waitForLoadState('networkidle')

    // 5. Should auto-login and redirect to dashboard
    await expect(page).toHaveURL(/.*\/dashboard/, { timeout: 10000 })
  })

  test('authentication pages have consistent styling', async ({ page }) => {
    const authPages = [
      '/auth',
      '/auth/register',
      '/auth/forgot-password',
      '/auth/magic-link'
    ]

    for (const pagePath of authPages) {
      await page.goto(pagePath)
      // Use networkidle with extended timeout for CI
      await page.waitForLoadState('networkidle', { timeout: 60000 })

      // All pages should have email input (common element)
      const emailInput = page.locator('input[type="email"]')
      await expect(emailInput).toBeVisible({ timeout: 10000 })

      // All pages should have a form or submit button
      const submitButton = page.locator('button[type="submit"]').first()
      await expect(submitButton).toBeVisible({ timeout: 5000 })
    }
  })

  test('all auth pages are accessible without login', async ({ page }) => {
    const publicPages = [
      '/auth',
      '/auth/register',
      '/auth/forgot-password',
      '/auth/magic-link',
      '/auth/reset-password?token=test'
    ]

    for (const pagePath of publicPages) {
      await page.goto(pagePath)
      await page.waitForLoadState('networkidle')
      await page.waitForLoadState('networkidle')

      // Should not redirect to another auth page (except if already logged in)
      const currentUrl = page.url()
      const basePagePath = pagePath.split('?')[0] || pagePath
      expect(
        currentUrl.includes(basePagePath)
        || currentUrl.includes('/dashboard')
      ).toBeTruthy()
    }
  })

  test('forms have proper loading states', async ({ page }) => {
    // Test login loading state
    await page.goto('/auth')
    await page.waitForLoadState('networkidle')

    const emailInput = page.locator('input[type="email"]')
    const passwordInput = page.locator('input[type="password"]')
    const loginButton = page.locator('button[type="submit"]')

    await fillInput(emailInput, generateTestEmail())
    await fillInput(passwordInput, generateTestPassword())
    await loginButton.click()

    // Button should be disabled during loading
    await expect(loginButton).toBeDisabled()

    // Reset and test registration loading state
    await page.goto('/auth/register')
    await page.waitForLoadState('networkidle')

    const nameInput = page.locator('input[type="text"]')
    const regEmailInput = page.locator('input[type="email"]')
    const regPasswordInput = page.locator('input[type="password"]')
    const registerButton = page.locator('button[type="submit"]')

    await fillInput(nameInput, 'Test User')
    await fillInput(regEmailInput, generateTestEmail())
    await fillInput(regPasswordInput, generateTestPassword())
    await registerButton.click()

    await expect(registerButton).toBeDisabled()
  })
})
