/**
 * Playwright global setup.
 *
 * Order matters:
 *   1. Bring the ephemeral Postgres/Redis containers up (idempotent).
 *   2. Wait for Postgres to accept connections.
 *   3. Apply backend migrations against the ephemeral DB.
 *   4. Seed deterministic fixture users (admin/doctor/patient).
 *
 * After this returns, Playwright will boot the backend + 3 portals via the
 * webServer entries in playwright.config.ts.
 */
import { spawnSync } from 'node:child_process';
import { Client } from 'pg';
import { resolve } from 'node:path';
import { config as loadEnv } from 'dotenv';

const e2eDir = resolve(__dirname, '..');
const repoRoot = resolve(e2eDir, '..', '..');
loadEnv({ path: resolve(e2eDir, '.env.e2e') });

function run(cmd: string, args: string[], opts: { cwd?: string; env?: NodeJS.ProcessEnv } = {}) {
  const r = spawnSync(cmd, args, {
    stdio: 'inherit',
    cwd: opts.cwd ?? e2eDir,
    env: { ...process.env, ...opts.env },
    shell: false,
  });
  if (r.status !== 0) {
    throw new Error(`${cmd} ${args.join(' ')} exited with ${r.status}`);
  }
}

async function waitForPg(timeoutMs = 30_000) {
  const start = Date.now();
  // eslint-disable-next-line no-constant-condition
  while (true) {
    try {
      const c = new Client({
        host: process.env.DB_HOST,
        port: parseInt(process.env.DB_PORT || '5434', 10),
        user: process.env.DB_USERNAME,
        password: process.env.DB_PASSWORD,
        database: process.env.DB_DATABASE,
      });
      await c.connect();
      await c.query('SELECT 1');
      await c.end();
      return;
    } catch (err) {
      if (Date.now() - start > timeoutMs) {
        throw new Error(`Postgres did not become ready within ${timeoutMs}ms: ${err}`);
      }
      await new Promise((r) => setTimeout(r, 500));
    }
  }
}

export default async function globalSetup() {
  console.log('[e2e] step 1/4 — bringing up ephemeral Postgres + Redis');
  run('docker', ['compose', '-f', 'docker-compose.e2e.yml', 'up', '-d', '--wait']);

  console.log('[e2e] step 2/4 — waiting for Postgres');
  await waitForPg();

  console.log('[e2e] step 3/4 — applying migrations');
  run(
    'npm',
    ['run', 'db:migrate'],
    {
      cwd: resolve(repoRoot, 'backend'),
      env: {
        DB_HOST: process.env.DB_HOST,
        DB_PORT: process.env.DB_PORT,
        DB_USERNAME: process.env.DB_USERNAME,
        DB_PASSWORD: process.env.DB_PASSWORD,
        DB_DATABASE: process.env.DB_DATABASE,
        DB_SSL: process.env.DB_SSL,
        NODE_ENV: 'test',
      },
    },
  );

  console.log('[e2e] step 4/4 — seeding fixtures');
  run('npx', ['tsx', 'scripts/seed.ts']);

  console.log('[e2e] setup complete — Playwright will now boot webServers');
}
