import { defineConfig, devices, type ReporterDescription } from '@playwright/test';
import { join } from 'node:path';
import { isExternalBaseUrl, loadPlaywrightEnv } from './tests/e2e/helpers/env';

const shellBaseUrl = process.env.BASE_URL;
const configDir = new URL('.', import.meta.url).pathname;
const factoryMode = process.env.E2E_FACTORY_MODE === '1';
// Factory mode: run-factory-e2e.mjs owns the full env contract (factory DB URL,
// run-scoped secrets). Loading .dev.vars here would override it with developer
// values and silently repoint the worker at the live database.
if (!factoryMode) {
  loadPlaywrightEnv(shellBaseUrl, [join(configDir, '.env'), join(configDir, '.dev.vars')]);
}

const PORT = Number(process.env.PORT ?? 4321);
const BASE_URL = shellBaseUrl ?? process.env.BASE_URL ?? `http://localhost:${PORT}`;
process.env.BASE_URL = BASE_URL;

// When BASE_URL points to a deployed environment (e.g. dev.multi.deal), skip the
// local webServer entirely — the app is already running externally.
const isExternalUrl = !factoryMode && isExternalBaseUrl(BASE_URL);

const reporters: ReporterDescription[] = process.env.CI ? [['github'], ['html']] : [['list']];
// Playwright resolves the json reporter's destination from these vars itself.
// Added alongside (never replacing) the human reporter so the failure list
// survives on disk even when stdout capture is truncated.
if (process.env.PLAYWRIGHT_JSON_OUTPUT_FILE || process.env.PLAYWRIGHT_JSON_OUTPUT_NAME)
  reporters.push(['json']);

export default defineConfig({
  testDir: './tests',
  // tests/waveb runs standalone via tests/waveb/playwright.config.ts.
  testIgnore: '**/waveb/**',
  globalSetup: factoryMode
    ? './tests/e2e/factories/global-setup.ts'
    : './tests/e2e/purchase-flows/fixtures/purchase-seed.ts',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: factoryMode ? 0 : process.env.CI ? 2 : 1,
  // workers: 1 locally and in CI — CF free tier has a 10ms CPU ceiling per request.
  // Running 2+ spec files concurrently generates simultaneous SSR requests that
  // each consume 5-15ms CPU → triggers 1102 "Worker exceeded resource limits".
  // Serial execution (workers: 1) keeps CF load to one request at a time.
  // retries: 1 handles the baseline cold-isolate 503/1102 rate (~5/20 probes).
  workers: 1,
  // Factory journeys hit real checkout/RMA/support flows; 30s default times out in the
  // certified full-suite batch even though per-spec runs pass with the same code.
  ...(factoryMode && {
    timeout: 120_000,
    expect: { timeout: 15_000 },
  }),
  reporter: reporters,
  use: {
    baseURL: BASE_URL,
    // Factory mode runs with retries: 0, so on-first-retry never captures anything.
    trace: factoryMode ? 'retain-on-failure' : 'on-first-retry',
    screenshot: 'only-on-failure',
    locale: 'he-IL',
    timezoneId: 'Asia/Jerusalem',
  },
  projects: [
    // No TEST_WORKER_INDEX env override — with workers: 1, TEST_WORKER_INDEX is 0
    // for all tests; all tests use user101 (sequential, never concurrent → no race).
    // NOTE: mobile-chrome uses Chromium engine so browser.browserType().name()
    // returns 'chromium' for both chromium + mobile-chrome projects.
    // Use testInfo.project.name (not browserType) to guard chromium-only sections.
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'mobile-chrome', use: { ...devices['Pixel 7'] } },
    { name: 'mobile-safari', use: { ...devices['iPhone 14'] } },
  ],
  // No webServer when targeting a deployed external URL
  ...(!isExternalUrl && {
    webServer: factoryMode
      ? {
          command: 'node scripts/factory-preview-server.mjs',
          url: `${BASE_URL}/maintenance`,
          reuseExistingServer: false,
          timeout: 120_000,
        }
      : process.env.CI
        ? {
            command: 'pnpm build && pnpm preview',
            url: BASE_URL,
            reuseExistingServer: false,
            timeout: 120_000,
          }
        : {
            command: 'ASTRO_DEV_BACKGROUND=1 pnpm dev',
            url: BASE_URL,
            reuseExistingServer: true,
            timeout: 120_000,
          },
  }),
});
