import type { Page, BrowserContext } from '@playwright/test';
import type { RouteAccess } from './websiteRouteInventory';

export type WebsiteAuthContext = 'public' | 'auth' | 'admin' | 'sponsor';

export type WebsiteSessionDriftMode = 'invalid-cookie' | 'expired' | 'missing-sponsor-id';
export type WebsiteFaultMode = 'null-array' | 'missing-field' | 'invalid-date';

export function authContextForAccess(access: RouteAccess): WebsiteAuthContext {
  if (access === 'public') return 'public';
  if (access === 'auth') return 'auth';
  if (access === 'admin') return 'admin';
  return 'sponsor';
}

export async function setWebsiteAuthContext(
  context: BrowserContext,
  auth: WebsiteAuthContext,
  options: { sessionDrift?: WebsiteSessionDriftMode; faultMode?: WebsiteFaultMode } = {},
): Promise<void> {
  const domain = 'localhost';
  const base = { domain, path: '/' };

  // The website uses `gridpilot_demo_mode` cookie to switch identity modes without OAuth.
  // We keep these cookies consistent across smoke tests.
  const cookies =
    auth === 'public'
      ? [
          { ...base, name: 'gridpilot_demo_mode', value: 'none' },
          { ...base, name: 'gridpilot_sponsor_id', value: '' },
          { ...base, name: 'gridpilot_sponsor_name', value: '' },
        ]
      : auth === 'sponsor'
        ? [
            { ...base, name: 'gridpilot_demo_mode', value: 'sponsor' },
            { ...base, name: 'gridpilot_sponsor_id', value: 'demo-sponsor-1' },
            { ...base, name: 'gridpilot_sponsor_name', value: 'Demo Sponsor' },
          ]
        : auth === 'admin'
          ? [
              { ...base, name: 'gridpilot_demo_mode', value: 'admin' },
              { ...base, name: 'gridpilot_sponsor_id', value: '' },
              { ...base, name: 'gridpilot_sponsor_name', value: '' },
            ]
          : [
              { ...base, name: 'gridpilot_demo_mode', value: 'driver' },
              { ...base, name: 'gridpilot_sponsor_id', value: '' },
              { ...base, name: 'gridpilot_sponsor_name', value: '' },
            ];

  const driftCookie =
    options.sessionDrift != null ? [{ ...base, name: 'gridpilot_session_drift', value: String(options.sessionDrift) }] : [];

  const faultCookie =
    options.faultMode != null ? [{ ...base, name: 'gridpilot_fault_mode', value: String(options.faultMode) }] : [];

  await context.clearCookies();
  await context.addCookies([...cookies, ...driftCookie, ...faultCookie]);
}

export type ConsoleCapture = {
  consoleErrors: string[];
  pageErrors: string[];
};

export function attachConsoleErrorCapture(page: Page): ConsoleCapture {
  const consoleErrors: string[] = [];
  const pageErrors: string[] = [];

  page.on('pageerror', (err) => {
    pageErrors.push(String(err));
  });

  page.on('console', (msg) => {
    const type = msg.type();
    if (type !== 'error') return;

    const text = msg.text();

    // Filter known benign warnings (keep small + generic).
    if (text.includes('Download the React DevTools')) return;

    // Next/Image accessibility warning (not a runtime failure for smoke coverage).
    if (text.includes('Image is missing required "alt" property')) return;

    // React controlled <select> warning (still renders fine; treat as non-fatal for route coverage).
    if (text.includes('Use the `defaultValue` or `value` props on <select> instead of setting `selected` on <option>.')) return;

    consoleErrors.push(`[${type}] ${text}`);
  });

  return { consoleErrors, pageErrors };
}