/**
 * Pipeline step: Compare against baseline scores.
 *
 * This step is already pure (no execSync, no env vars) — the logic is
 * inlined directly from the former pipeline/steps/compare-step.ts.
 * This is an optional step — failure doesn't stop the pipeline.
 *
 * Baseline resolution order (highest priority first):
 *  1. `compareBaselineReportId` — fetch the named report doc
 *     and use its `summary` (a ReportSummary, which is a
 *     superset of ComparableSummary) as the baseline.
 *  2. `compareBaseline` — local filesystem path (CLI ergonomics).
 *  3. Latest baseline in `results/baselines/`.
 */
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, } from "fs";
import { join, resolve } from "path";
import { assoc, } from "../../_vendor/ailf-core/index.js";
import { emitFileContents } from "../../artifact-capture/emit-file.js";
import { compare } from "../../pipeline/compare.js";
export class CompareStep {
    name = "compare";
    optional = true;
    check() {
        return [];
    }
    async execute(ctx) {
        const start = Date.now();
        const { rootDir } = ctx.config;
        const scoreSummaryPath = resolve(rootDir, "results", "latest", "score-summary.json");
        if (!existsSync(scoreSummaryPath)) {
            return {
                durationMs: Date.now() - start,
                error: "score-summary.json not found. Run calculate-scores first.",
                status: "failed",
            };
        }
        // Load experiment (current run)
        const experiment = JSON.parse(readFileSync(scoreSummaryPath, "utf-8"));
        // Resolve baseline. Pinned report id wins over local FS, which wins
        // over auto-discovery of the most recent file in `results/baselines/`.
        let baseline;
        const pinnedReportId = ctx.config.compareBaselineReportId;
        if (pinnedReportId) {
            if (!ctx.reportStore) {
                return {
                    reason: "compareBaselineReportId set but no reportStore is configured. " +
                        "Check Sanity credentials in .ailf/config.yaml.",
                    status: "skipped",
                };
            }
            const result = await ctx.reportStore.loadBaselineFromReport(pinnedReportId);
            if (result.kind === "error") {
                return {
                    durationMs: Date.now() - start,
                    error: `Failed to load baseline report ${pinnedReportId}: ${result.message}`,
                    status: "failed",
                };
            }
            if (result.kind === "not_found") {
                return {
                    reason: `Baseline report ${pinnedReportId} not found.`,
                    status: "skipped",
                };
            }
            baseline = result.baseline;
        }
        else {
            let resolvedBaselinePath;
            if (ctx.config.compareBaseline) {
                resolvedBaselinePath = resolve(ctx.config.compareBaseline);
            }
            else {
                const baselinesDir = resolve(rootDir, "results", "baselines");
                if (!existsSync(baselinesDir)) {
                    return {
                        reason: "No baselines directory found. Run 'pnpm baseline:save' first.",
                        status: "skipped",
                    };
                }
                const files = readdirSync(baselinesDir)
                    .filter((f) => f.endsWith(".json"))
                    .sort()
                    .reverse();
                if (files.length === 0) {
                    return {
                        reason: "No baseline files found. Run 'pnpm baseline:save' first.",
                        status: "skipped",
                    };
                }
                resolvedBaselinePath = join(baselinesDir, files[0]);
            }
            if (!existsSync(resolvedBaselinePath)) {
                return {
                    durationMs: Date.now() - start,
                    error: `Baseline file not found: ${resolvedBaselinePath}`,
                    status: "failed",
                };
            }
            baseline = JSON.parse(readFileSync(resolvedBaselinePath, "utf-8"));
        }
        // Run comparison
        const options = ctx.config.compareThreshold
            ? { noiseThreshold: ctx.config.compareThreshold }
            : undefined;
        const report = compare(baseline, experiment, options);
        // Write report to outputDir (respects --output-dir)
        mkdirSync(ctx.config.outputDir, { recursive: true });
        const reportPath = resolve(ctx.config.outputDir, "comparison-report.json");
        writeFileSync(reportPath, JSON.stringify(report, null, 2));
        // W0050 — comparisonReport is per-entry keyed by mode ({run, mode}).
        await emitFileContents(ctx.artifactWriter, "comparisonReport", assoc(ctx, { mode: ctx.config.mode }), reportPath);
        // Build summary
        const improved = report.improved.length;
        const regressed = report.regressed.length;
        const unchanged = report.unchanged.length;
        const overallDelta = report.deltas.overall;
        const deltaStr = overallDelta > 0
            ? `+${Math.round(overallDelta)}`
            : String(Math.round(overallDelta));
        const parts = [`Overall: ${deltaStr}`];
        if (improved > 0)
            parts.push(`${improved} improved`);
        if (regressed > 0)
            parts.push(`${regressed} regressed`);
        if (unchanged > 0)
            parts.push(`${unchanged} unchanged`);
        return {
            durationMs: Date.now() - start,
            status: "success",
            summary: parts.join(", "),
        };
    }
}
