#!/usr/bin/env tsx
/**
 * cli:run-smoke — index.ts
 *
 * Entry point for the runtime smoke test. Parses CLI args, runs the
 * smoke, prints the standard executeEnvelope on stdout, exits with
 * a non-zero status when probes fail.
 */
import { executeEnvelope, failExecute, printEnvelope } from '../../../../lib/output.js';
import { RunSmokeArgsSchema, type SmokeReport } from './types.js';
import { runSmoke } from './execute.js';

function parseArgs(argv: string[]): Record<string, string | number | boolean> {
  const out: Record<string, string | number | boolean> = {};
  for (let i = 0; i < argv.length; i++) {
    const a = argv[i];
    if (!a.startsWith('--')) continue;
    const key = a.slice(2);
    const next = argv[i + 1];
    if (next === undefined || next.startsWith('--')) {
      out[key] = true;
    } else {
      const num = Number(next);
      out[key] = Number.isFinite(num) && next.match(/^\d/) ? num : next;
      i++;
    }
  }
  return out;
}

function camelize(key: string): string {
  return key.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
}

async function main(): Promise<void> {
  const raw = parseArgs(process.argv.slice(2));
  // The CLI uses kebab-case flags ; the Zod schema uses camelCase. Map.
  const camel: Record<string, unknown> = {};
  for (const [k, v] of Object.entries(raw)) {
    camel[camelize(k)] = v;
  }
  const parsed = RunSmokeArgsSchema.safeParse(camel);
  if (!parsed.success) {
    printEnvelope(
      failExecute<SmokeReport>('run-smoke', [
        'Invalid CLI arguments :',
        ...parsed.error.issues.map((i) => `  - ${i.path.join('.')}: ${i.message}`),
      ]),
    );
    process.exit(2);
    return;
  }
  const report = await runSmoke(parsed.data);
  const envelope = executeEnvelope<SmokeReport>('run-smoke', {
    success: report.passed,
    report,
    errors: report.failures.map(
      (f) => `${f.verb} ${f.url} → ${f.status ?? 'no-response'} (${f.failureReason ?? 'unknown'})${f.expectedBy ? ` (declared by ${f.expectedBy})` : ''}`,
    ),
    nextSteps: report.passed
      ? []
      : [
          'Re-run the relevant scaffolder for each failing probe (cf. report.failures[].expectedBy).',
          'If multiple probes share the same scaffolder origin, fix at the scaffolder level rather than the generated file.',
        ],
  });
  printEnvelope(envelope);
  process.exit(report.passed ? 0 : 1);
}

main().catch((err: unknown) => {
  const message = err instanceof Error ? err.message : String(err);
  printEnvelope(failExecute<SmokeReport>('run-smoke', [`Uncaught error : ${message}`]));
  process.exit(2);
});
