/**
 * interpret command — generate a Diagnosis for a Report.
 *
 * Wraps `getDiagnosisRunner(ctx)` from the composition root in a Commander
 * command for consistent CLI integration. Closest analog: compare.ts.
 *
 * Entry points:
 *   ailf interpret <reportId>          — one-line-per-card summary
 *   ailf interpret <reportId> --json   — full Diagnosis JSON
 *   ailf interpret latest              — most recent report
 *   ailf interpret <id> --compare <ref>  — DIAG-05 regression comparison
 *   ailf interpret <id> --refresh      — bypass version-keyed cache
 *
 * @see packages/eval/src/commands/compare.ts — CLI factory analog
 * @see packages/eval/src/composition-root.ts — getDiagnosisRunner
 * @see .planning/phases/05-diagnosis-engine-cli-llm-cards/05-AI-SPEC.md §6
 */
import { dirname, resolve } from "path";
import { fileURLToPath } from "url";
import { Command } from "commander";
import { addOutputDirOption } from "./shared/options.js";
import { resolveOutputDir } from "./shared/resolve-output-dir.js";
import { defaultVersionsFromReport } from "./shared/versions-from-report.js";
// ---------------------------------------------------------------------------
// Module-level root constant (same pattern as compare.ts)
// ---------------------------------------------------------------------------
const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = resolve(__dirname, "..", "..");
// ---------------------------------------------------------------------------
// Card output formatting (AI-SPEC §6 graceful-degradation-visibility)
// ---------------------------------------------------------------------------
/**
 * Visual status markers — locked visual contract per plan Test 7:
 * ready: "✓", degraded: "⚠", missing: "—"
 *
 * Exported so Plan 06-04's post-run hook imports the SAME object and
 * D6-04's "single formatter, single visual contract" is physically
 * enforced — no copy/paste drift possible.
 */
export const STATUS_ICONS = {
    ready: "✓",
    degraded: "⚠",
    missing: "—",
};
function getCardSummaryText(card) {
    if (card.status === "ready") {
        return card.body.summary;
    }
    if (card.status === "degraded") {
        return card.reason;
    }
    // missing
    return card.reason;
}
/**
 * Format a single card as a one-line summary string.
 *
 * Format: `<icon> <cardType>: <summary>`
 * Per AI-SPEC §6: distinct icons for ready / degraded / missing.
 *
 * Exported so Plan 06-04's post-run hook imports the SAME function and
 * D6-04's "single formatter, single visual contract" is physically
 * enforced — no copy/paste drift possible.
 */
export function formatCardSummaryLine(card) {
    const icon = STATUS_ICONS[card.status];
    const text = getCardSummaryText(card);
    return `${icon} ${card.cardType}: ${text}`;
}
// ---------------------------------------------------------------------------
// Command factory
// ---------------------------------------------------------------------------
/**
 * Create the `ailf interpret <reportId>` Commander command.
 *
 * Accepts optional `InterpretCommandOptions` for testability — tests can
 * inject a fake runner factory and store factory without touching module
 * mocks (preferred per testing.md).
 */
export function createInterpretCommand(options = {}) {
    const { runnerFactory, storeFactory, versionsFromReport } = options;
    const cmd = new Command("interpret")
        .description("Generate a Diagnosis for a Report — 8 typed cards explaining what's weak and what to do")
        .argument("<reportId>", "Report ID (or 'latest' for the most recent)")
        .option("-c, --compare <ref>", "Baseline report ID for regression-vs-baseline comparison")
        .option("--refresh", "Bypass the version-keyed cache and recompute")
        .option("--json", "Print full Diagnosis JSON instead of one-line-per-card summary")
        .action(async (reportId, opts) => {
        const outputDir = resolveOutputDir(opts.outputDir);
        // ---------------------------------------------------------------------------
        // Resolve store: injected factory (tests) or composition root (production)
        // ---------------------------------------------------------------------------
        let store;
        let ctx;
        if (storeFactory) {
            store = storeFactory();
            ctx = null;
        }
        else {
            // Production path — lazy import to keep the module fast in tests
            // Minimal config: report-read-only, no eval/fetch/publish.
            const { createAppContext } = await import("../composition-root.js");
            ctx = createAppContext({
                compareEnabled: false,
                gapAnalysisEnabled: false,
                mode: "literacy",
                noAutoScope: false,
                noCache: true,
                noRemoteCache: true,
                outputDir,
                publishEnabled: false,
                rootDir: ROOT,
                searchMode: "open",
                skipEval: true,
                skipFetch: true,
                remote: false,
                apiUrl: "https://ailf-api.sanity.build",
            });
            const prodCtx = ctx;
            store = prodCtx.reportStore;
        }
        if (!store) {
            process.stderr.write("Error: report store is not available\n");
            process.exit(1);
        }
        // ---------------------------------------------------------------------------
        // Resolve main report
        // ---------------------------------------------------------------------------
        const report = reportId === "latest"
            ? await store.latest()
            : await store.read(reportId);
        if (!report) {
            process.stderr.write(`Error: report not found: ${reportId}\n`);
            process.exit(1);
        }
        // ---------------------------------------------------------------------------
        // Optionally resolve baseline (DIAG-05)
        // ---------------------------------------------------------------------------
        let baseline;
        if (opts.compare) {
            baseline = await store.read(opts.compare);
            if (!baseline) {
                process.stderr.write(`Error: baseline report not found: ${opts.compare}\n`);
                process.exit(1);
            }
        }
        // ---------------------------------------------------------------------------
        // Resolve versions
        // ---------------------------------------------------------------------------
        const versions = versionsFromReport
            ? versionsFromReport(report)
            : defaultVersionsFromReport(report);
        // ---------------------------------------------------------------------------
        // Build runner
        // ---------------------------------------------------------------------------
        let runner;
        if (runnerFactory) {
            runner = runnerFactory(ctx);
        }
        else {
            const { getDiagnosisRunner } = await import("../composition-root.js");
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            runner = getDiagnosisRunner(ctx);
        }
        // ---------------------------------------------------------------------------
        // Run diagnosis
        // ---------------------------------------------------------------------------
        const diagnosis = await runner.run({
            // The report here is the eval's ReportStore record, which satisfies
            // the Report interface for runner.run purposes (both carry id + provenance.runId).
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            report: report,
            versions,
            ...(baseline ? { baseline: baseline } : {}),
            refresh: opts.refresh ?? false,
        });
        // ---------------------------------------------------------------------------
        // Print output
        // ---------------------------------------------------------------------------
        if (opts.json) {
            process.stdout.write(`${JSON.stringify(diagnosis, null, 2)}\n`);
        }
        else {
            for (const card of diagnosis.cards) {
                process.stdout.write(`${formatCardSummaryLine(card)}\n`);
            }
        }
    });
    addOutputDirOption(cmd);
    return cmd;
}
