import type { ExitStatus } from "./exit-status.js";
import { runBaselineDiff, runBaselineUpdate } from "./commands/baseline.js";
import { runDoctor } from "./commands/doctor.js";
import { runDecisionsExport, runDecisionsImport, runDecisionsRevoke } from "./commands/decisions.js";
import { runContractsCalibrate, runContractsList, runContractsPromote, runContractsRetire, runContractsShow } from "./commands/contracts.js";
import { runDiscover } from "./commands/discover.js";
import { runHook } from "./commands/hook.js";
import { runInit } from "./commands/init.js";
import { runVerify, type IoContext } from "./commands/verify.js";
import { formatUsageError, parseArgs } from "./parse-args.js";
import { writeMachineLog } from "./machine-output.js";

export type { IoContext };

export async function main(argv: string[], io: IoContext): Promise<ExitStatus> {
  const parsed = parseArgs(argv);
  if (!parsed.ok) {
    writeMachineLog(formatUsageError(parsed.message), io.stderr);
    return 2;
  }

  if (parsed.command === "verify") {
    if (parsed.options.hook) return runHook(parsed.options, io);
    if (!parsed.options.report && parsed.options.lane === undefined) return runVerify(parsed.options, io);
    const { writeReportForRun } = await import("./commands/report.js");
    return runVerify(parsed.options, io, writeReportForRun);
  }
  if (parsed.command === "discover") {
    if (!parsed.options.report) return runDiscover(parsed.options, io);
    const { writeReportForRun } = await import("./commands/report.js");
    return runDiscover(parsed.options, io, writeReportForRun);
  }
  if (parsed.command === "doctor") return runDoctor(parsed.options, io);
  if (parsed.command === "decisions-export") return runDecisionsExport(parsed.options, io);
  if (parsed.command === "decisions-import") return runDecisionsImport(parsed.options, io);
  if (parsed.command === "decisions-revoke") return runDecisionsRevoke(parsed.options, io);
  if (parsed.command === "contracts-list") return runContractsList(parsed.options, io);
  if (parsed.command === "contracts-show") return runContractsShow(parsed.options, io);
  if (parsed.command === "contracts-calibrate") return runContractsCalibrate(parsed.options, io);
  if (parsed.command === "contracts-promote") return runContractsPromote(parsed.options, io);
  if (parsed.command === "contracts-retire") return runContractsRetire(parsed.options, io);
  if (parsed.command === "baseline-update") return runBaselineUpdate(parsed.options, io);
  if (parsed.command === "baseline-diff") return runBaselineDiff(parsed.options, io);
  if (parsed.command === "init") return runInit(io);
  if (parsed.command === "report") {
    const { runReport } = await import("./commands/report.js");
    return runReport(parsed.options, io);
  }
  if (parsed.command === "serve") {
    const { runServe } = await import("./commands/serve.js");
    return runServe(parsed.options, io);
  }
  const { runFinalize } = await import("./commands/report.js");
  return runFinalize(parsed.options, io);
}
