/**
 * `everystack audit:lighthouse [--stage <name>] [--host <url>] [--runs N] [--path /]`
 *
 * Mobile Lighthouse audit (Perf / A11y / Best-Practices / SEO) reported as a
 * distribution over N runs, because the Performance score swings run-to-run with
 * LCP. Warms the CloudFront edge first, then measures the warm-HTML path.
 *
 * Config-free: the target URL is the deployed router URL from SST outputs
 * (resolveConfig), or --host. Requires `npx lighthouse` and a headless Chrome.
 */

import { execFileSync } from 'node:child_process';
import { readFileSync, mkdtempSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import {
  CATEGORIES,
  extractRun,
  aggregate,
  formatLighthouseReport,
  type ExtractedRun,
  type LhReport,
} from '../lighthouse.js';
import { resolveConfig } from '../config.js';
import { step, info, fail, warn } from '../output.js';

function runLighthouse(url: string, outPath: string): LhReport {
  // Warm the edge so we measure the real-user (cached-HTML) experience.
  try {
    execFileSync('curl', ['-s', '-o', '/dev/null', url], { timeout: 30_000 });
  } catch {
    // warming is best-effort
  }
  execFileSync(
    'npx',
    [
      'lighthouse',
      url,
      `--only-categories=${CATEGORIES.join(',')}`,
      '--chrome-flags=--headless=new --no-sandbox',
      '--output=json',
      `--output-path=${outPath}`,
      '--quiet',
    ],
    { stdio: ['ignore', 'ignore', 'ignore'], timeout: 120_000 },
  );
  return JSON.parse(readFileSync(outPath, 'utf8'));
}

/** Run Lighthouse N times and return the per-run extracts. Shared with the
 *  `audit` capstone. */
export async function collectLighthouseRuns(url: string, runs: number): Promise<ExtractedRun[]> {
  const tmp = mkdtempSync(join(tmpdir(), 'everystack-lh-'));
  const extracts: ExtractedRun[] = [];
  for (let i = 0; i < runs; i++) {
    step(`Lighthouse run ${i + 1}/${runs} on ${url} ...`);
    try {
      const report = runLighthouse(url, join(tmp, `lh-${i}.json`));
      extracts.push(extractRun(report));
    } catch (err: any) {
      warn(`run ${i + 1} failed: ${err.message?.split('\n')[0] ?? err}`);
    }
  }
  return extracts;
}

export async function auditLighthouseCommand(flags: Record<string, string>): Promise<void> {
  let host = flags.host;
  if (!host) {
    try {
      const config = await resolveConfig(flags.stage);
      host = config.baseUrl;
    } catch (err: any) {
      fail(err.message);
      info('Pass --host <url> to audit a specific URL without resolving a stage.');
      process.exit(1);
    }
  }
  if (!host) {
    fail('No URL to audit. Pass --host <url> or --stage <name>.');
    process.exit(1);
  }

  const runs = flags.runs ? parseInt(flags.runs, 10) : 3;
  const pathName = flags.path || '/';
  const url = host.replace(/\/+$/, '') + (pathName.startsWith('/') ? pathName : '/' + pathName);

  const extracts = await collectLighthouseRuns(url, runs);

  if (extracts.length === 0) {
    fail('All Lighthouse runs failed. Is `npx lighthouse` installed and Chrome available?');
    process.exit(1);
  }

  const agg = aggregate(extracts);
  console.log('');
  console.log(formatLighthouseReport(url, extracts.length, agg).join('\n'));

  if (flags.json) {
    writeFileSync(flags.json, JSON.stringify(agg, null, 2));
    info(`Raw results → ${flags.json}`);
  }
  process.exit(0);
}
