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

test.describe('Authentication Flows', () => {
  // Run tests serially since they depend on shared state (registered user)
  test.describe.configure({ mode: 'serial' })

  // Generate unique email for each test run to avoid conflicts
  // Include random suffix to prevent collisions between parallel browser runs
  const timestamp = Date.now()
  const randomSuffix = Math.random().toString(36).substring(7)
  const testEmail = `test${timestamp}${randomSuffix}@example.com`
  const testPassword = 'password123'
  const testName = 'Test User'

  test.describe('Registration', () => {
    test('should display registration form', async ({ page }) => {
      await page.goto('/register')

      await expect(page.locator('h2')).toContainText('Create Account')
      await expect(page.getByLabel('Email')).toBeVisible()
      await expect(page.getByLabel('Password')).toBeVisible()
      await expect(page.getByLabel('Name')).toBeVisible()
      await expect(page.getByRole('button', { name: 'Create Account' })).toBeVisible()
    })

    test('should successfully register a new user', async ({ page }) => {
      await page.goto('/register')

      // Fill out registration form
      await page.getByLabel('Email').fill(testEmail)
      await page.getByLabel('Password').fill(testPassword)
      await page.getByLabel('Name').fill(testName)

      // Submit form
      await page.getByRole('button', { name: 'Create Account' }).click()

      // Should redirect to login page
      await page.waitForURL(/\/login/, { timeout: 10000 })
    })

    test('should show error for duplicate email', async ({ page }) => {
      await page.goto('/register')

      // Try to register with existing email
      await page.getByLabel('Email').fill(testEmail)
      await page.getByLabel('Password').fill(testPassword)
      await page.getByLabel('Name').fill(testName)

      await page.getByRole('button', { name: 'Create Account' }).click()

      // Should show error message (from server)
      await expect(page.getByText(/already exists|error/i)).toBeVisible({ timeout: 5000 })
    })

    test('should have link to login page', async ({ page }) => {
      await page.goto('/register')

      const loginLink = page.getByRole('link', { name: 'Sign in' })
      await expect(loginLink).toBeVisible()

      await loginLink.click()
      await expect(page).toHaveURL('/login')
    })
  })

  test.describe('Login', () => {
    test('should display login form', async ({ page }) => {
      await page.goto('/login')

      await expect(page.locator('h2')).toContainText('Sign In')
      await expect(page.getByLabel('Email')).toBeVisible()
      await expect(page.getByLabel('Password')).toBeVisible()
      await expect(page.getByRole('button', { name: 'Sign In' })).toBeVisible()
    })

    test('should successfully login with valid credentials', async ({ page }) => {
      await page.goto('/login')

      // Fill out login form
      await page.getByLabel('Email').fill(testEmail)
      await page.getByLabel('Password').fill(testPassword)

      // Submit form
      await page.getByRole('button', { name: 'Sign In' }).click()

      // Should redirect to dashboard
      await page.waitForURL('/dashboard', { timeout: 10000 })
    })

    test('should show error for invalid credentials', async ({ page }) => {
      await page.goto('/login')

      await page.getByLabel('Email').fill(testEmail)
      await page.getByLabel('Password').fill('wrongpassword')

      await page.getByRole('button', { name: 'Sign In' }).click()

      // Should show error message
      await expect(page.getByText(/error/i)).toBeVisible({ timeout: 5000 })
    })

    test('should have link to registration page', async ({ page }) => {
      await page.goto('/login')

      const registerLink = page.getByRole('link', { name: 'Sign up' })
      await expect(registerLink).toBeVisible()

      await registerLink.click()
      await expect(page).toHaveURL('/register')
    })
  })

  test.describe('Logout', () => {
    test.beforeEach(async ({ page }) => {
      // Log in before each test
      await page.goto('/login')
      await page.getByLabel('Email').fill(testEmail)
      await page.getByLabel('Password').fill(testPassword)
      await page.getByRole('button', { name: 'Sign In' }).click()
      await page.waitForURL('/dashboard', { timeout: 10000 })
    })

    test('should successfully logout', async ({ page }) => {
      // Find and click logout button
      const logoutButton = page.getByRole('button', { name: /logout|sign out/i })
      await logoutButton.click()

      // Should redirect to login or home page
      await page.waitForURL(/\/(login|$)/, { timeout: 5000 })
    })
  })

  test.describe('Protected Routes', () => {
    test('should redirect to login when accessing dashboard without authentication', async ({
      page,
    }) => {
      await page.goto('/dashboard')

      // Should redirect to login page
      await page.waitForURL('/login', { timeout: 5000 })
    })

    test('should redirect to login when accessing settings without authentication', async ({
      page,
    }) => {
      await page.goto('/settings')

      // Should redirect to login page
      await page.waitForURL('/login', { timeout: 5000 })
    })
  })

  test.describe('Session Persistence', () => {
    test('should maintain session across page reloads', async ({ page }) => {
      // Login
      await page.goto('/login')
      await page.getByLabel('Email').fill(testEmail)
      await page.getByLabel('Password').fill(testPassword)
      await page.getByRole('button', { name: 'Sign In' }).click()
      await page.waitForURL('/dashboard', { timeout: 10000 })

      // Reload page
      await page.reload()

      // Should still be on dashboard
      await expect(page).toHaveURL('/dashboard')
    })

    test('should maintain session when navigating between pages', async ({
      page,
    }) => {
      // Login
      await page.goto('/login')
      await page.getByLabel('Email').fill(testEmail)
      await page.getByLabel('Password').fill(testPassword)
      await page.getByRole('button', { name: 'Sign In' }).click()
      await page.waitForURL('/dashboard', { timeout: 10000 })

      // Navigate to settings
      await page.goto('/settings')
      await expect(page).toHaveURL('/settings')

      // Navigate back to dashboard
      await page.goto('/dashboard')
      await expect(page).toHaveURL('/dashboard')
    })
  })
})
