import { test, expect } from '@playwright/test';
import {
  loginSeedUser,
  takeScreenshot,
  setupConsoleErrorTracking,
  setupNetworkTracking,
  assertCleanPage,
} from './utils/test-helpers';

test.describe('Journey 1: Registration, Login & Auth Flow', () => {
  let consoleErrors: string[];
  let network: ReturnType<typeof setupNetworkTracking>;

  test.beforeEach(async ({ page }) => {
    consoleErrors = setupConsoleErrorTracking(page);
    network = setupNetworkTracking(page);
  });

  test('should display registration form with all fields', async ({ page }) => {
    await page.goto('/auth/register');
    await takeScreenshot(page, '01-registration-page');

    // Use id selectors (always present) with name as fallback
    await expect(page.locator('#name')).toBeVisible();
    await expect(page.locator('#email')).toBeVisible();
    await expect(page.locator('#password')).toBeVisible();
    await expect(page.locator('#confirmPassword')).toBeVisible();
    await expect(page.locator('button[type="submit"]')).toBeVisible();

    assertCleanPage(consoleErrors, network);
  });

  test('should validate registration form (client-side)', async ({ page }) => {
    await page.goto('/auth/register');

    // Submit empty form — HTML5 validation should prevent submission
    await page.click('button[type="submit"]');
    await takeScreenshot(page, '02-registration-validation');

    // Should still be on register page
    expect(page.url()).toContain('/auth/register');
    assertCleanPage(consoleErrors, network);
  });

  test('should show error for mismatched passwords', async ({ page }) => {
    await page.goto('/auth/register');

    await page.fill('#name', 'Test User');
    await page.fill('#email', 'test@example.com');
    await page.fill('#password', 'SecurePassword123!');
    await page.fill('#confirmPassword', 'DifferentPassword!');
    await page.click('button[type="submit"]');
    await page.waitForTimeout(1000);

    const errorText = await page.textContent('body');
    expect(errorText).toContain('Passwords do not match');
    await takeScreenshot(page, '03-password-mismatch');
    assertCleanPage(consoleErrors, network);
  });

  test('should login with seed user and reach dashboard', async ({ page }) => {
    await loginSeedUser(page);
    await takeScreenshot(page, '04-logged-in-dashboard');

    expect(page.url()).toContain('/dashboard');
    assertCleanPage(consoleErrors, network);
  });

  test('should redirect unauthenticated users from dashboard to login', async ({ page }) => {
    await page.goto('/dashboard');
    // Auth middleware redirects to login
    await page.waitForURL('**/auth/login**', { timeout: 10000 });
    await takeScreenshot(page, '05-redirect-to-login');

    expect(page.url()).toContain('/auth/login');
    assertCleanPage(consoleErrors, network);
  });

  test('should redirect authenticated users from login to dashboard', async ({ page }) => {
    // First login
    await loginSeedUser(page);
    expect(page.url()).toContain('/dashboard');

    // Now try visiting login page — should redirect back to dashboard
    await page.goto('/auth/login');
    await page.waitForURL('**/dashboard', { timeout: 10000 });

    expect(page.url()).toContain('/dashboard');
    assertCleanPage(consoleErrors, network);
  });

  test('should show error for invalid credentials', async ({ page }) => {
    await page.goto('/auth/login');
    await page.fill('input[name="email"]', 'nonexistent@example.com');
    await page.fill('input[name="password"]', 'WrongPassword123!');
    await page.click('button[type="submit"]');
    await page.waitForTimeout(3000);
    await takeScreenshot(page, '06-login-invalid-credentials');

    // Should still be on login page
    expect(page.url()).toContain('/auth/login');
    assertCleanPage(consoleErrors, network);
  });

  test('should logout and redirect to home', async ({ page }) => {
    await loginSeedUser(page);
    expect(page.url()).toContain('/dashboard');

    await page.getByRole('button', { name: /sign out/i }).click();
    await page.waitForURL(/\/(\?.*)?$/, { timeout: 10000 });

    expect(page.url()).toMatch(/\/(\?.*)?$/);
    assertCleanPage(consoleErrors, network);
  });

  test('should persist session across page navigation', async ({ page }) => {
    await loginSeedUser(page);
    expect(page.url()).toContain('/dashboard');

    // Navigate to an external page then back to dashboard
    await page.goto('/pricing');
    await page.waitForTimeout(1000);
    expect(page.url()).toContain('/pricing');

    // Navigate back to dashboard — should still be authenticated (no redirect to login)
    await page.goto('/dashboard');
    await page.waitForTimeout(2000);
    await takeScreenshot(page, '07-session-persisted');

    expect(page.url()).toContain('/dashboard');
    // Should NOT have been redirected to login
    expect(page.url()).not.toContain('/auth/login');
    assertCleanPage(consoleErrors, network);
  });

  test('should not be able to access dashboard after logout', async ({ page }) => {
    await loginSeedUser(page);
    expect(page.url()).toContain('/dashboard');

    // Logout
    await page.getByRole('button', { name: /sign out/i }).click();
    await page.waitForURL(/\/(\?.*)?$/, { timeout: 10000 });

    // Try to access dashboard — should redirect to login
    await page.goto('/dashboard');
    await page.waitForURL('**/auth/login**', { timeout: 10000 });
    await takeScreenshot(page, '08-no-access-after-logout');

    expect(page.url()).toContain('/auth/login');
    assertCleanPage(consoleErrors, network);
  });
});
