import { defineConfig, devices } from '@playwright/test';

/**
 * End-to-end suite, driving the portal and the backoffice in a real browser.
 *
 * Both frontends are in one project on purpose: the flows that matter cross
 * them — an applicant files, an officer decides, the applicant collects the
 * certificate — and per-app projects cannot express that.
 *
 * Nothing here reads the shared `.env` files. A developer's own stack is
 * usually already running against `ema_db` on the default ports, and
 * `dev/start.sh` rewrites those files on every run; a suite that read them
 * would point at whichever stack was started last. Instead the servers below
 * are launched with explicit environment, on ports of their own, against a
 * database of their own.
 */

const API_PORT = Number(process.env.E2E_API_PORT ?? 3011);
const PORTAL_PORT = Number(process.env.E2E_PORTAL_PORT ?? 4302);
const BACKOFFICE_PORT = Number(process.env.E2E_BACKOFFICE_PORT ?? 4303);

export const E2E = {
  apiUrl: `http://localhost:${API_PORT}/api`,
  portalUrl: `http://localhost:${PORTAL_PORT}`,
  backofficeUrl: `http://localhost:${BACKOFFICE_PORT}`,
  database: process.env.E2E_DB_NAME ?? 'ema_e2e',
  /**
   * Where the API's own output is teed.
   *
   * The one-time code an applicant types at signup exists in exactly one
   * readable place: this log. `iam.user_verifications` stores it argon2-hashed,
   * and the notification rows it is delivered through carry an empty body — so
   * the log line is not a convenience here, it is the only source.
   */
  apiLog: process.env.E2E_API_LOG ?? '/tmp/ema-e2e-api.log',
};

const emaapi =
  '../../../emaapi/apps/server/emaapi';

/** Env the API is started with. Explicit, so no `.env` can redirect it. */
const apiEnv = {
  ...process.env,
  PORT: String(API_PORT),
  DATABASE_NAME: E2E.database,
  // The API applies migrations on boot, which is what bootstraps a fresh E2E
  // database — but it must never be the thing that decides what the schema is.
  MIGRATIONS_RUN: 'false',
  NODE_ENV: 'development',
  FRONTEND_URLS: `${E2E.portalUrl},${E2E.backofficeUrl}`,
  PUBLIC_VERIFY_URL: `${E2E.portalUrl}/verify`,
  PORTAL_BASE_URL: E2E.portalUrl,
  PAYMENT_AUTO_CONFIRM: 'true',
  ALLOW_PAYMENT_BYPASS: 'true',
};

export default defineConfig({
  testDir: './src',
  // Flows share one database, and an officer queue is global state. Serial
  // execution costs wall-clock and buys determinism.
  workers: 1,
  fullyParallel: false,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 1 : 0,
  timeout: 90_000,
  expect: { timeout: 15_000 },
  reporter: [['list'], ['html', { outputFolder: '../../dist/e2e-report', open: 'never' }]],

  use: {
    baseURL: E2E.portalUrl,
    // Kept only for failures — a trace per passing test is noise nobody reads.
    trace: 'retain-on-failure',
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
    actionTimeout: 15_000,
  },

  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
  ],

  webServer: [
    {
      name: 'api',
      // Teed rather than piped to Playwright's own stdout, because the OTP
      // helper has to read it back.
      command: `sh -c 'node dist/main.js 2>&1 | tee ${E2E.apiLog}'`,
      cwd: emaapi,
      env: apiEnv,
      url: `${E2E.apiUrl}/license-types`,
      // 401 is the healthy answer: the route exists and demands a session.
      ignoreHTTPSErrors: true,
      reuseExistingServer: !process.env.CI,
      timeout: 120_000,
      stdout: 'pipe',
      stderr: 'pipe',
    },
    {
      name: 'portal',
      command: `npx vite build --config apps/portal/vite.config.mts --mode e2e && npx vite preview --config apps/portal/vite.config.mts --mode e2e --port ${PORTAL_PORT} --strictPort`,
      cwd: '../..',
      url: E2E.portalUrl,
      reuseExistingServer: !process.env.CI,
      timeout: 180_000,
    },
    {
      name: 'backoffice',
      command: `npx vite build --config apps/backoffice/vite.config.mts --mode e2e && npx vite preview --config apps/backoffice/vite.config.mts --mode e2e --port ${BACKOFFICE_PORT} --strictPort`,
      cwd: '../..',
      url: E2E.backofficeUrl,
      reuseExistingServer: !process.env.CI,
      timeout: 180_000,
    },
  ],
});
