/**
 * compare command — structured comparison between two evaluation runs.
 *
 * Wraps the existing compare pipeline logic and formatting utilities
 * in a Commander.js command for consistent CLI integration.
 */
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, } from "fs";
import { dirname, join, resolve } from "path";
import { fileURLToPath } from "url";
import { Command } from "commander";
import { compare } from "../pipeline/compare.js";
import { addOutputDirOption } from "./shared/options.js";
import { resolveOutputDir } from "./shared/resolve-output-dir.js";
import { DEFAULT_NOISE_THRESHOLD, } from "../pipeline/types.js";
import { formatComparisonTable } from "../_vendor/ailf-core/index.js";
const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = resolve(__dirname, "..", "..");
const BASELINES_DIR = join(ROOT, "results", "baselines");
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
export function createCompareCommand() {
    const cmd = new Command("compare")
        .description("Compare two evaluation score summaries")
        .option("-b, --baseline <path>", "Baseline score-summary.json (default: latest baseline)")
        .option("-e, --experiment <path>", "Experiment score-summary.json (default: .ailf/results/latest/score-summary.json)")
        .option("-t, --threshold <n>", "Noise threshold for unchanged classification", parseFloat)
        .option("-o, --output <path>", "Write JSON report to file")
        .option("-f, --format <fmt>", "Output format: table or json", "table")
        .action(async (opts) => {
        const outputDir = resolveOutputDir(opts.outputDir);
        const threshold = opts.threshold ?? DEFAULT_NOISE_THRESHOLD;
        // Resolve experiment path
        const expPath = opts.experiment
            ? resolve(opts.experiment)
            : join(outputDir, "score-summary.json");
        const experiment = loadSummary(expPath);
        // Resolve baseline path
        let basePath;
        if (opts.baseline) {
            basePath = resolve(opts.baseline);
        }
        else {
            const latest = findLatestBaseline();
            if (!latest) {
                console.error("❌ No baselines found. Run 'pnpm baseline:save' first, or use --baseline <path>.");
                process.exit(1);
            }
            basePath = latest;
        }
        const baseline = loadSummary(basePath);
        // Try to load grader consistency data for empirical thresholds
        const consistencyPath = join(outputDir, "grader-consistency.json");
        let graderConsistency;
        if (existsSync(consistencyPath) && opts.threshold === undefined) {
            try {
                const consistencyRaw = JSON.parse(readFileSync(consistencyPath, "utf-8"));
                if (consistencyRaw.recommendedThreshold &&
                    consistencyRaw.perDimension) {
                    graderConsistency =
                        consistencyRaw;
                    console.log(`  📊 Using empirical noise threshold: ±${graderConsistency.recommendedThreshold.toFixed(1)} (from grader consistency data)`);
                }
            }
            catch {
                // Non-fatal — fall back to default threshold
            }
        }
        console.log(`  Baseline:   ${basePath}`);
        console.log(`  Experiment: ${expPath}`);
        if (!graderConsistency) {
            console.log(`  Threshold:  ±${threshold} (default — run --grader-replications for empirical threshold)`);
        }
        console.log("");
        const report = compare(baseline, experiment, {
            graderConsistency,
            noiseThreshold: threshold,
        });
        if (opts.format === "json") {
            const json = JSON.stringify(report, null, 2);
            if (opts.output) {
                writeReport(opts.output, json);
                console.log(`  ✅ Comparison report written to ${opts.output}`);
            }
            else {
                console.log(json);
            }
        }
        else {
            const table = formatComparisonTable(report);
            console.log(table);
            if (opts.output) {
                const json = JSON.stringify(report, null, 2);
                writeReport(opts.output, json);
                console.log(`  ✅ Comparison report also written to ${opts.output}`);
            }
        }
        // Write comparison report to output dir for other steps to consume
        const latestComparisonPath = join(outputDir, "comparison-report.json");
        writeReport(latestComparisonPath, JSON.stringify(report, null, 2));
    });
    addOutputDirOption(cmd);
    return cmd;
}
function findLatestBaseline() {
    if (!existsSync(BASELINES_DIR))
        return null;
    const files = readdirSync(BASELINES_DIR)
        .filter((f) => f.endsWith(".json"))
        .sort()
        .reverse();
    return files.length > 0 ? join(BASELINES_DIR, files[0]) : null;
}
// ---------------------------------------------------------------------------
// Command factory
// ---------------------------------------------------------------------------
function loadSummary(path) {
    if (!existsSync(path)) {
        console.error(`❌ File not found: ${path}`);
        process.exit(1);
    }
    const raw = readFileSync(path, "utf-8");
    return JSON.parse(raw);
}
// W0097: every write path creates its parent dir so a fresh project (no
// `.ailf/results/latest/`) or a user-supplied `--output` pointing at a
// not-yet-existing directory both succeed instead of crashing with ENOENT.
function writeReport(path, contents) {
    mkdirSync(dirname(path), { recursive: true });
    writeFileSync(path, contents);
}
