/**
 * cli-program.ts — pure factory for the AILF Commander program.
 *
 * Splits the program construction out of cli.ts so the CLI is testable
 * in-process. cli.ts owns bootstrap side effects (dotenv loading,
 * retired-flag/env/cmd checks, AILF_LOG_LEVEL pre-scan, parseAsync); this
 * module owns command wiring.
 *
 * The W0078 M4 black-box harness imports `buildCliProgram()` directly so
 * tests can construct a fresh program, attach `exitOverride()`, capture
 * stdout/stderr, and parse a synthetic argv — all without spawning a
 * subprocess.
 *
 * @see packages/eval/src/__tests__/cli-harness/run-cli.ts
 */
import { Command } from "commander";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { CommandGroup, configureProgram } from "./commands/shared/help.js";
import { createAgentReportCommand } from "./commands/agent-report.js";
import { createBaselineCommand } from "./commands/baseline.js";
import { createCacheCommand } from "./commands/cache.js";
import { createCalculateScoresCommand } from "./commands/calculate-scores.js";
import { createCheckStalenessCommand } from "./commands/check-staleness.js";
import { createChronicFailuresCommand } from "./commands/chronic-failures.js";
import { createCompareCommand } from "./commands/compare.js";
import { createCompletionCommand } from "./commands/completion.js";
import { createCoverageAuditCommand } from "./commands/coverage-audit.js";
import { createDiscoveryReportCommand } from "./commands/discovery-report.js";
import { createEvalCommand } from "./commands/eval.js";
import { createFetchDocsCommand } from "./commands/fetch-docs.js";
import { createGenerateConfigsCommand } from "./commands/generate-configs.js";
import { createGraderCommand } from "./commands/grader/index.js";
import { createInitCommand } from "./commands/init.js";
import { createInterpretCommand } from "./commands/interpret.js";
import { createInteractiveCommand } from "./commands/interactive.js";
import { createLookupDocCommand } from "./commands/lookup-doc.js";
import { createMeasureRetrievalCommand } from "./commands/measure-retrieval.js";
import { createNotifySweepCommand } from "./commands/notify-sweep.js";
import { createPrCommentCommand } from "./commands/pr-comment.js";
import { createPublishCommand } from "./commands/publish.js";
import { createReadinessReportCommand } from "./commands/readiness-report.js";
import { createRunCommand } from "./commands/run.js";
import { createRunsCommand } from "./commands/runs.js";
import { createTeamsCommand } from "./commands/teams.js";
import { createValidateConfigCommand } from "./commands/validate.js";
import { createValidateTasksCommand } from "./commands/validate-tasks.js";
import { createWebhookServerCommand } from "./commands/webhook-server.js";
import { createWeeklyDigestCommand } from "./commands/weekly-digest.js";
/**
 * Construct the Commander program with every subcommand registered.
 *
 * Pure factory — no I/O beyond reading package.json for the version, no
 * `process.exit()`, no `process.argv` access. Tests can call this and
 * attach `program.exitOverride()` before parsing to capture exit codes
 * instead of terminating the process.
 *
 * Registration order determines group display order in `--help`. Commands
 * within a group appear in the order they're added.
 */
export function buildCliProgram(opts) {
    const { evalRoot } = opts;
    const pkgPath = resolve(evalRoot, "package.json");
    const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
    const program = new Command()
        .name("ailf")
        .description("AI Literacy Framework — evaluate how well docs enable AI coding tools\n\nMeasure whether AI coding agents can find the right documentation\nand produce correct implementations of your product features.")
        .version(pkg.version)
        .option("-v, --verbose", "Increase log output")
        .option("-q, --quiet", "Suppress non-error output")
        .option("--dotenv <path>", "Override default .env file path")
        .option("--explain", "Show execution plan without running")
        .option("--explain-format <fmt>", "Output format for --explain (console, json)", "console")
        .option("-y, --yes", "With --explain: show plan then prompt to confirm execution");
    configureProgram(program);
    // Global --explain hook — intercepts any command before execution
    program.hook("preAction", async (thisCommand, actionCommand) => {
        const globalOpts = thisCommand.opts();
        if (!globalOpts.explain)
            return;
        const { handleExplain } = await import("./commands/explain-handler.js");
        try {
            await handleExplain(actionCommand, globalOpts.yes ?? false, evalRoot);
            process.exit(0);
        }
        catch (err) {
            // Sentinel from --yes confirmation: user wants to proceed
            if (err !== null &&
                typeof err === "object" &&
                "__proceedArgv" in err) {
                const filteredArgv = err.__proceedArgv;
                console.log("\n  ▸ Proceeding with execution…\n");
                await program.parseAsync(filteredArgv);
                return;
            }
            throw err;
        }
    });
    // ── Core Workflow ──────────────────────────────────────────────────────
    program.addCommand(createRunCommand().helpGroup(CommandGroup.CoreWorkflow));
    program.addCommand(createCompareCommand().helpGroup(CommandGroup.CoreWorkflow));
    program.addCommand(createBaselineCommand().helpGroup(CommandGroup.CoreWorkflow));
    program.addCommand(createPublishCommand().helpGroup(CommandGroup.CoreWorkflow));
    program.addCommand(createRunsCommand().helpGroup(CommandGroup.CoreWorkflow));
    // ── Analysis & Reports ────────────────────────────────────────────────
    const reportCommand = new Command("report")
        .description("Generate analysis and reporting outputs from evaluation runs")
        .addCommand(createReadinessReportCommand())
        .addCommand(createChronicFailuresCommand())
        .addCommand(createCoverageAuditCommand())
        .addCommand(createDiscoveryReportCommand())
        .addCommand(createAgentReportCommand())
        .addCommand(createWeeklyDigestCommand())
        .addCommand(createNotifySweepCommand())
        .addCommand(createCheckStalenessCommand());
    program.addCommand(reportCommand.helpGroup(CommandGroup.AnalysisReports));
    // `ailf interpret <reportId>` — top-level (not nested under report) per AI-SPEC
    program.addCommand(createInterpretCommand().helpGroup(CommandGroup.AnalysisReports));
    // ── Grader Reliability ────────────────────────────────────────────────
    program.addCommand(createGraderCommand().helpGroup(CommandGroup.GraderReliability));
    // ── Setup & Configuration ─────────────────────────────────────────────
    program.addCommand(createInitCommand().helpGroup(CommandGroup.SetupConfig));
    const validateCommand = new Command("validate")
        .description("Validate AILF configuration and task files")
        .addCommand(createValidateConfigCommand())
        .addCommand(createValidateTasksCommand());
    program.addCommand(validateCommand.helpGroup(CommandGroup.SetupConfig));
    program.addCommand(createFetchDocsCommand().helpGroup(CommandGroup.SetupConfig));
    program.addCommand(createTeamsCommand().helpGroup(CommandGroup.SetupConfig));
    program.addCommand(createCacheCommand().helpGroup(CommandGroup.SetupConfig));
    // ── Pipeline Internals ────────────────────────────────────────────────
    program.addCommand(createEvalCommand().helpGroup(CommandGroup.PipelineInternals));
    program.addCommand(createCalculateScoresCommand().helpGroup(CommandGroup.PipelineInternals));
    program.addCommand(createPrCommentCommand().helpGroup(CommandGroup.PipelineInternals));
    program.addCommand(createGenerateConfigsCommand().helpGroup(CommandGroup.PipelineInternals));
    program.addCommand(createMeasureRetrievalCommand().helpGroup(CommandGroup.PipelineInternals));
    program.addCommand(createLookupDocCommand().helpGroup(CommandGroup.PipelineInternals));
    program.addCommand(createWebhookServerCommand().helpGroup(CommandGroup.PipelineInternals));
    // ── Developer Tools ───────────────────────────────────────────────────
    program.addCommand(createInteractiveCommand().helpGroup(CommandGroup.DeveloperTools));
    // Shell completion — must be registered last (needs full program tree)
    program.addCommand(createCompletionCommand(program).helpGroup(CommandGroup.DeveloperTools));
    return program;
}
