/**
 * check-staleness command — verifies recent evaluation reports exist.
 *
 * Exits 0 when the most recent report in the Sanity Content Lake is within
 * the max-age window, 1 otherwise (including "no reports at all"). Emits a
 * single JSON line on stdout summarizing the decision so CI can pipe it
 * directly into an alert payload.
 *
 * Used by the scheduled staleness workflow to detect silent pipeline
 * failures — cases where scheduled evaluations stop producing reports but
 * no workflow run fails loudly enough to be noticed.
 */
import { Command } from "commander";
export function createCheckStalenessCommand() {
    return new Command("staleness")
        .description("Exit 1 if no evaluation report has been produced within the max-age window")
        .option("--max-age <days>", "Max age in days before reports are considered stale", (v) => Number.parseInt(v, 10), 3)
        .action(async (opts) => {
        const { getSanityClient } = await import("../sanity/client.js");
        // Resolve report-store credentials with the same precedence as
        // weekly-digest.ts and composition-root.ts — AILF_REPORT_* wins over
        // the evaluated-source SANITY_* defaults so the staleness probe tracks
        // the actual report dataset even when it diverges from the eval source.
        //
        // The `??` fallbacks matter: passing `{ projectId: undefined }` would
        // clobber `getSanityClient`'s built-in default via spread. The
        // staleness workflow only sets SANITY_PROJECT_ID, so without the
        // fallback the probe crashes with "Configuration must contain
        // `projectId`" instead of doing its job (issue #272).
        const projectId = process.env.AILF_REPORT_PROJECT_ID ?? process.env.SANITY_PROJECT_ID;
        const dataset = process.env.AILF_REPORT_DATASET ?? process.env.SANITY_DATASET;
        const token = process.env.AILF_REPORT_SANITY_API_TOKEN ?? process.env.SANITY_API_TOKEN;
        const client = getSanityClient({
            ...(projectId ? { projectId } : {}),
            ...(dataset ? { dataset } : {}),
            ...(token ? { token } : {}),
        });
        const maxAgeDays = opts.maxAge;
        // Bound the GROQ sort with a `completedAt > $floor` filter. Beyond
        // ~10,000 reports the unbounded `order(completedAt desc)[0]` scan
        // becomes a noticeable cost; a floor proportional to the max-age
        // window keeps the scan cheap regardless of corpus size. The factor
        // of 10× max-age gives plenty of headroom — if the last report
        // predates the floor, the absence of any result still yields the
        // correct "stale" verdict.
        const floorDays = Math.max(maxAgeDays * 10, 30);
        const floor = new Date(Date.now() - floorDays * 24 * 60 * 60 * 1000).toISOString();
        const QUERY = `*[_type == "ailf.report" && completedAt > $floor] | order(completedAt desc)[0]{
        "reportId": reportId,
        "completedAt": completedAt,
        "tag": tag
      }`;
        const latest = await client.fetch(QUERY, { floor });
        // Use `process.exitCode` + `return` rather than `process.exit()` so
        // stdout flushes cleanly when the caller captures via `$(...)` — a
        // hard exit can drop buffered output on piped captures. Matches the
        // pattern used by agent-report.ts, capture-list.ts, etc.
        if (!latest || !latest.completedAt) {
            console.log(JSON.stringify({
                floorDays,
                maxAgeDays,
                reason: "no-reports",
                stale: true,
            }));
            process.exitCode = 1;
            return;
        }
        const ageMs = Date.now() - new Date(latest.completedAt).getTime();
        const ageDays = Number((ageMs / (24 * 60 * 60 * 1000)).toFixed(2));
        const stale = ageDays > maxAgeDays;
        console.log(JSON.stringify({
            ageDays,
            floorDays,
            latestCompletedAt: latest.completedAt,
            latestReportId: latest.reportId,
            latestTag: latest.tag,
            maxAgeDays,
            stale,
        }));
        process.exitCode = stale ? 1 : 0;
    });
}
