import { existsSync } from 'node:fs';
import { spawn, spawnSync, type SpawnOptions } from 'node:child_process';
import { fileURLToPath } from 'node:url';

const packageRoot = fileURLToPath(new URL('..', import.meta.url));
const browserDist = fileURLToPath(new URL('../../browser-entry/dist/index.html', import.meta.url));
const host = process.env.LEARNITIVE_E2E_HOST ?? '127.0.0.1';
const port = process.env.LEARNITIVE_E2E_PORT ?? '5188';
const baseUrl = `http://${host}:${port}`;

function resolvePnpmInvocation(): { command: string; prefix: string[] } {
  const execPath = process.env.npm_execpath;
  if (execPath && /(?:^|[/\\])pnpm(?:\.c?js)?$/i.test(execPath)) return { command: process.execPath, prefix: [execPath] };
  if (spawnSync('sh', ['-c', 'command -v pnpm'], { stdio: 'ignore' }).status === 0) return { command: 'pnpm', prefix: [] };
  if (spawnSync('sh', ['-c', 'command -v corepack'], { stdio: 'ignore' }).status === 0) return { command: 'corepack', prefix: ['pnpm'] };
  throw new Error('Unable to resolve pnpm. Run "corepack enable" before scientific runtime certification.');
}

function spawnPnpm(args: string[], options: SpawnOptions) {
  const pnpm = resolvePnpmInvocation();
  return spawn(pnpm.command, [...pnpm.prefix, ...args], options);
}

async function waitFor(url: string, exited: () => boolean) {
  const deadline = Date.now() + 60_000;
  while (Date.now() < deadline) {
    if (exited()) throw new Error('Production preview exited before scientific runtime certification started.');
    try { if ((await fetch(url)).ok) return; } catch { /* retry */ }
    await new Promise((resolve) => setTimeout(resolve, 250));
  }
  throw new Error(`Timed out waiting for production preview at ${url}`);
}

async function main() {
  if (!existsSync(browserDist)) {
    throw new Error('Scientific runtime release certification requires a production browser build. Run `pnpm run build` first.');
  }

  let exited = false;
  const preview = spawnPnpm(
    ['--dir', '../browser-entry', 'exec', 'vite', 'preview', '--configLoader', 'runner', '--host', host, '--port', port, '--strictPort'],
    { cwd: packageRoot, env: process.env, stdio: 'inherit' },
  );
  preview.once('exit', () => { exited = true; });

  try {
    await waitFor(baseUrl, () => exited);
    const test = spawnPnpm([
      'exec', 'playwright', 'test', '-c', './playwright.config.ts',
      '--project=chromium', '--project=firefox', '--project=edge',
      'src/latex-scientific-runtime-certification-r14-28-12.e2e.ts',
    ], {
      cwd: packageRoot,
      env: {
        ...process.env,
        CI: '1',
        LEARNITIVE_RELEASE_QUALITY: '1',
        LEARNITIVE_SCIENTIFIC_RUNTIME_LIVE: '1',
        LEARNITIVE_C_CPP_LIVE: process.env.LEARNITIVE_C_CPP_LIVE ?? '1',
        LEARNITIVE_E2E_BASE_URL: baseUrl,
        LEARNITIVE_E2E_EXTERNAL_SERVER: '1',
      },
      stdio: 'inherit',
    });
    const code = await new Promise<number>((resolve, reject) => {
      test.once('error', reject);
      test.once('exit', (value, signal) => resolve(signal ? 1 : value ?? 1));
    });
    process.exitCode = code;
  } finally {
    if (!preview.killed) preview.kill('SIGTERM');
  }
}

await main();
