/**
 * Authentication tests for the cPad Control Panel.
 *
 * Coverage:
 *  • Login page renders correctly
 *  • Login with valid credentials → redirected to /cp/dashboard (or /cp/)
 *  • Login with invalid credentials → error message shown, no redirect
 *  • Logout → session is destroyed, login page is shown
 *
 * These tests do NOT use the pre-saved storageState; they exercise the actual
 * login/logout flow from scratch.
 *
 * Run:
 *   npx playwright test tests/cpad/auth.spec.ts --project=chromium
 */

import { test, expect } from '@playwright/test';
import {
  ADMIN_EMAIL,
  ADMIN_PASSWORD,
  CP_PATH,
  DASHBOARD_PATH,
  attachErrorListeners,
} from '../helpers/auth';

// ─────────────────────────────────────────────────────────────────────────────
// Login page
// ─────────────────────────────────────────────────────────────────────────────

test.describe('cPad Login Page', () => {
  test('login page loads and shows email + password fields', async ({ page }) => {
    const { consoleErrors, networkErrors } = attachErrorListeners(page);

    await page.goto(CP_PATH + '/login');

    // Basic page health
    await expect(page.locator('body')).toBeVisible();
    const title = await page.title();
    expect(title.length, 'Page title should not be empty').toBeGreaterThan(0);

    // Form fields
    const emailField    = page.locator('input[name="email"], input[type="email"]').first();
    const passwordField = page.locator('input[name="password"], input[type="password"]').first();
    const submitButton  = page.locator('button[type="submit"], input[type="submit"]').first();

    await expect(emailField).toBeVisible();
    await expect(passwordField).toBeVisible();
    await expect(submitButton).toBeVisible();

    // No JS crashes on page load
    expect(consoleErrors.length, `Console errors: ${consoleErrors.join(' | ')}`).toBe(0);
    expect(networkErrors.length, `Network errors: ${networkErrors.join(' | ')}`).toBe(0);
  });
});

// ─────────────────────────────────────────────────────────────────────────────
// Successful login
// ─────────────────────────────────────────────────────────────────────────────

test.describe('cPad Successful Login', () => {
  test('admin can log in and is redirected to dashboard', async ({ page }) => {
    const { consoleErrors, networkErrors } = attachErrorListeners(page);

    await page.goto(CP_PATH + '/login');

    await page.locator('input[name="email"], input[type="email"]').first().fill(ADMIN_EMAIL);
    await page.locator('input[name="password"], input[type="password"]').first().fill(ADMIN_PASSWORD);
    await page.locator('button[type="submit"], input[type="submit"]').first().click();

    // After successful login the URL should be within /cp and not be /login
    await page.waitForURL(
      (url) => url.pathname.startsWith(CP_PATH) && !url.pathname.endsWith('/login'),
      { timeout: 20_000 },
    );

    await expect(page.locator('body')).toBeVisible();

    // No server errors
    const body = await page.locator('body').textContent() ?? '';
    expect(/Whoops|Server Error|500/.test(body), 'Server error page after login').toBe(false);

    expect(networkErrors.length, `HTTP 5xx errors: ${networkErrors.join(' | ')}`).toBe(0);
  });
});

// ─────────────────────────────────────────────────────────────────────────────
// Failed login
// ─────────────────────────────────────────────────────────────────────────────

test.describe('cPad Failed Login', () => {
  test('wrong password shows error and stays on login page', async ({ page }) => {
    const { networkErrors } = attachErrorListeners(page);

    await page.goto(CP_PATH + '/login');

    await page.locator('input[name="email"], input[type="email"]').first().fill(ADMIN_EMAIL);
    await page.locator('input[name="password"], input[type="password"]').first().fill('WrongPassword999!');
    await page.locator('button[type="submit"], input[type="submit"]').first().click();

    // Should stay on the login page
    await page.waitForLoadState('networkidle');
    expect(page.url()).toContain('/login');

    // No 5xx errors from a bad credentials attempt
    expect(networkErrors.length, `HTTP 5xx errors: ${networkErrors.join(' | ')}`).toBe(0);
  });

  test('empty credentials show validation errors', async ({ page }) => {
    await page.goto(CP_PATH + '/login');

    // Submit without filling in anything
    await page.locator('button[type="submit"], input[type="submit"]').first().click();
    await page.waitForLoadState('networkidle');

    // Still on login page
    expect(page.url()).toContain(CP_PATH);
  });
});

// ─────────────────────────────────────────────────────────────────────────────
// Logout
// ─────────────────────────────────────────────────────────────────────────────

test.describe('cPad Logout', () => {
  test('logout destroys session and shows login page', async ({ page }) => {
    // Log in first
    await page.goto(CP_PATH + '/login');
    await page.locator('input[name="email"], input[type="email"]').first().fill(ADMIN_EMAIL);
    await page.locator('input[name="password"], input[type="password"]').first().fill(ADMIN_PASSWORD);
    await page.locator('button[type="submit"], input[type="submit"]').first().click();

    await page.waitForURL(
      (url) => url.pathname.startsWith(CP_PATH) && !url.pathname.endsWith('/login'),
      { timeout: 20_000 },
    );

    // Perform logout via the /cp/logout route
    await page.goto(CP_PATH + '/logout');
    await page.waitForLoadState('networkidle');

    // Should land on the login page again
    expect(page.url()).toContain('/login');

    // Attempting to access dashboard now should redirect back to login
    await page.goto(DASHBOARD_PATH);
    await page.waitForLoadState('networkidle');
    expect(page.url()).toContain('/login');
  });
});
