/**
 * doc-attribution-spotlight card — LLM-driven doc-citation spotlight.
 *
 * Model: claude-sonnet-4-6 (routine per AI-SPEC §4 model routing)
 * Version: doc-attribution-spotlight@0.1.0
 *
 * Landmine 11: reads `ctx.judgmentAttributions` (NOT Report.summary).
 * Returns `status: "missing"` when attributions are undefined or empty.
 *
 * Mitigations:
 * - failure-mode #5: docCitations[].docSlug refined against the manifest
 *   allow-list so hallucinated slugs fail Zod parse
 *
 * Schema is in the D0045 trust-boundary scan root; `satisfies` clause is
 * mandatory.
 *
 * @see .planning/phases/05-diagnosis-engine-cli-llm-cards/05-RESEARCH.md (Landmine 11)
 * @see docs/decisions/D0052-judgment-ref-granularity.md
 */
import { z } from "zod";
import { ConfidenceSchema } from "../../../schemas/confidence-schema.js";
import { modelId as mkModelId } from "../../../ports/llm-client.js";
import { buildDocAttributionSpotlightPrompt, buildDocSlugAllowList, } from "../prompt-builders.js";
// ---------------------------------------------------------------------------
// Body schema (D0045 trust boundary — satisfies required)
// ---------------------------------------------------------------------------
/**
 * Module-level static shape. Per-call adds the allow-list refine on docSlug.
 */
export const DocAttributionSpotlightBodySchema = z.object({
    summary: z.string().min(1).max(800),
    docCitations: z
        .array(z.object({
        docSlug: z.string().min(1),
        confidence: ConfidenceSchema,
        role: z.enum(["supports", "contradicts", "missing", "irrelevant"]),
    }))
        .min(1)
        .max(5),
});
// ---------------------------------------------------------------------------
// Generator
// ---------------------------------------------------------------------------
const CARD_MODEL = mkModelId("anthropic:claude-sonnet-4-6");
export const generateDocAttributionSpotlight = async (report, ctx) => {
    // C1: no LLM → missing
    if (!ctx.llm) {
        return {
            status: "missing",
            cardType: "doc-attribution-spotlight",
            reason: "no LLMClient wired",
        };
    }
    // D1: Landmine 11 — short-circuit BEFORE calling LLM when no attribution data
    if (!ctx.judgmentAttributions || ctx.judgmentAttributions.length === 0) {
        return {
            status: "missing",
            cardType: "doc-attribution-spotlight",
            reason: "no attribution data for this run",
        };
    }
    // Build allow-list from the runtime report
    const allowList = buildDocSlugAllowList(report);
    // Per-call schema with docSlug allow-list refine (AI-SPEC §3 Pitfall 1)
    const PerCallSchema = z.object({
        summary: z.string().min(1).max(800),
        docCitations: z
            .array(z.object({
            docSlug: z
                .string()
                .min(1)
                .refine((slug) => allowList.has(slug), {
                message: "docCitations[].docSlug is not in the report document manifest allow-list",
            }),
            confidence: ConfidenceSchema,
            role: z.enum(["supports", "contradicts", "missing", "irrelevant"]),
        }))
            .min(1)
            .max(5),
    });
    const prompt = buildDocAttributionSpotlightPrompt(report, ctx.judgmentAttributions);
    // Destructure `cost` and `model` from the LLMClient return —
    // already provided per llm-client.ts:139-144, previously discarded.
    const { value, usage, cost, model } = await ctx.llm.completeStructured({
        model: CARD_MODEL,
        prompt: `${prompt.system}\n\n${prompt.user}`,
        schema: PerCallSchema,
        temperature: 0.1,
        maxTokens: 2000,
        context: {
            feature: "diagnosis",
            runId: ctx.runId,
            cardId: "doc-attribution-spotlight",
        },
    });
    return {
        status: "ready",
        cardType: "doc-attribution-spotlight",
        body: value,
        meta: {
            cardVersion: "doc-attribution-spotlight@0.1.0",
            tokenUsage: { input: usage.promptTokens, output: usage.completionTokens },
            generatedAt: new Date().toISOString(),
            cost,
            model,
        },
    };
};
