/**
 * Authentication helper for cPad Control Panel tests.
 *
 * Usage in tests that do NOT use the pre-saved storageState:
 *   import { loginAsAdmin } from '../helpers/auth';
 *   await loginAsAdmin(page);
 *
 * The cpad-setup project (auth.setup.ts) calls loginAsAdmin once and persists
 * the session to tests/.auth/admin.json so all other cpad tests reuse it.
 */

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

export const ADMIN_EMAIL    = 'gregor@klevze.si';
export const ADMIN_PASSWORD = 'Gre15#10gor!1976$';
export const CP_PATH        = '/cp';
export const DASHBOARD_PATH = '/cp/dashboard';
export const AUTH_FILE      = path.join('tests', '.auth', 'admin.json');

/**
 * Perform a full cPad login and wait for the dashboard to load.
 * Verifies the redirect ends up on a /cp/dashboard URL.
 */
export async function loginAsAdmin(page: Page): Promise<void> {
  // Attach console-error listener so callers can detect JS exceptions
  page.on('console', (msg) => {
    if (msg.type() === 'error') {
      console.warn(`[CONSOLE ERROR] ${msg.text()}`);
    }
  });

  await page.goto(CP_PATH);

  // Wait for the login form to be ready
  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 emailField.waitFor({ state: 'visible', timeout: 15_000 });
  await emailField.fill(ADMIN_EMAIL);
  await passwordField.fill(ADMIN_PASSWORD);
  await submitButton.click();

  // After login, the panel may show a 2FA screen or land on dashboard
  // Wait up to 20 s for a URL that contains /cp (but isn't the login page)
  await page.waitForURL((url) => url.pathname.startsWith(CP_PATH) && !url.pathname.endsWith('/login'), {
    timeout: 20_000,
  });
}

/**
 * Verify the current page is the cPad dashboard.
 * Call this *after* loginAsAdmin to assert a successful login.
 */
export async function assertDashboard(page: Page): Promise<void> {
  await expect(page).toHaveURL(new RegExp(`${CP_PATH}`));
}

/**
 * Attach console-error and network-failure listeners to the page.
 * Returns arrays that accumulate errors so the calling test can assert them.
 */
export function attachErrorListeners(page: Page): {
  consoleErrors: string[];
  networkErrors: string[];
} {
  const consoleErrors: string[] = [];
  const networkErrors: string[] = [];

  page.on('console', (msg) => {
    if (msg.type() === 'error') {
      consoleErrors.push(msg.text());
    }
  });

  page.on('pageerror', (err) => {
    consoleErrors.push(`[pageerror] ${err.message}`);
  });

  page.on('response', (response) => {
    const status = response.status();
    if (status >= 500) {
      networkErrors.push(`HTTP ${status}: ${response.url()}`);
    }
  });

  page.on('requestfailed', (request) => {
    networkErrors.push(`[requestfailed] ${request.url()} — ${request.failure()?.errorText}`);
  });

  return { consoleErrors, networkErrors };
}
