/**
 * pipeline/readiness-report.ts
 *
 * Pure computation module for launch readiness reports.
 *
 * Combines threshold evaluation, ceiling decomposition, and gap analysis
 * into a single actionable readiness checklist for a given feature area.
 *
 * This module has NO side effects — no file I/O, no process.argv, no env vars.
 * Callers (command handlers, orchestration steps) handle I/O and pass data in.
 *
 * Exports pure functions:
 *   - generateReadinessReport()  — builds the structured report
 *   - formatReadinessMarkdown()  — renders the report as markdown
 *
 * @see docs/archive/exec-plans/scenario-matrix-implementation/phase-5-readiness-thresholds.md
 * @see docs/archive/exec-plans/eliminate-lib-layer.md
 */
import { evaluateThresholds } from "./thresholds.js";
// ---------------------------------------------------------------------------
// Pure functions (exported for testing)
// ---------------------------------------------------------------------------
/**
 * Format a readiness report as markdown.
 *
 * Pure function — takes a structured report and returns a markdown string.
 */
export function formatReadinessMarkdown(report) {
    const lines = [];
    const areaLabel = formatAreaLabel(report.area);
    // Header
    const statusEmoji = report.pass ? "✅" : "❌";
    const statusLabel = report.pass ? "READY" : "NOT READY";
    lines.push(`## 🚀 Launch Readiness: ${areaLabel}`);
    lines.push("");
    lines.push(`**Overall:** ${statusEmoji} ${statusLabel} (${fmt(report.score)}/100, threshold: ${report.threshold})`);
    lines.push("");
    // Dimension Checklist
    lines.push("### Dimension Checklist");
    lines.push("");
    lines.push("| Dimension | Score | Threshold | Status |");
    lines.push("|---|---|---|---|");
    for (const dim of report.dimensions) {
        const status = dim.pass ? "✅ Meets threshold" : "❌ Below threshold";
        lines.push(`| ${dim.dimension} | ${fmt(dim.score)} | ${fmt(dim.threshold)} | ${status} |`);
    }
    lines.push("");
    // Ceiling Analysis
    lines.push("### Ceiling Analysis");
    lines.push("");
    lines.push("| Metric | Value | Assessment |");
    lines.push("|---|---|---|");
    const ceilingAssessment = report.ceiling.ceilingScore >= 60
        ? "✅ Docs enable reasonable performance"
        : "⚠️ Below 60 — docs need improvement";
    lines.push(`| Ceiling Score | ${fmt(report.ceiling.ceilingScore)} | ${ceilingAssessment} |`);
    const floorAssessment = report.ceiling.floorScore >= 30
        ? "Model has moderate baseline knowledge"
        : "Model has limited baseline knowledge";
    lines.push(`| Floor Score | ${fmt(report.ceiling.floorScore)} | ${floorAssessment} |`);
    const liftSign = report.ceiling.docLift >= 0 ? "+" : "";
    const liftAssessment = report.ceiling.docLift < 0
        ? "❌ Docs are hurting performance"
        : report.ceiling.docLift >= 10
            ? "✅ Docs add significant value"
            : "⚠️ Docs add minimal value";
    lines.push(`| Doc Lift | ${liftSign}${fmt(report.ceiling.docLift)} | ${liftAssessment} |`);
    lines.push(`| Doc Quality Gap | ${fmt(report.ceiling.docQualityGap)} | ${report.ceiling.docQualityGap > 30 ? "Room for improvement via documentation" : "✅ Docs are high quality"} |`);
    lines.push("");
    // Failing Criteria (only shown when there are violations)
    if (report.violations.length > 0) {
        lines.push("### Failing Criteria");
        for (let i = 0; i < report.violations.length; i++) {
            const v = report.violations[i];
            lines.push(`${i + 1}. **${v.description}**`);
        }
        lines.push("");
        lines.push("### Recommendation");
        const count = report.violations.length;
        const itemWord = count === 1 ? "item" : "items";
        lines.push(`Fix the ${count} ${itemWord} above and re-evaluate.`);
        lines.push("");
    }
    // Gap Analysis (if available)
    if (report.gaps.length > 0) {
        lines.push("### Gap Analysis");
        lines.push("");
        lines.push("| Failure Mode | Est. Lift | Confidence | Remediation |");
        lines.push("|---|---|---|---|");
        for (const gap of report.gaps) {
            const confIcon = gap.confidence === "high"
                ? "🟢"
                : gap.confidence === "medium"
                    ? "🟡"
                    : "🔴";
            lines.push(`| ${gap.failureMode} | +${gap.estimatedLift.toFixed(1)} | ${confIcon} ${gap.confidence} | ${gap.remediation} |`);
        }
        lines.push("");
    }
    // Historical Progress (if available)
    if (report.history.length > 0) {
        lines.push("### Historical Progress");
        lines.push("");
        lines.push("| Date | Score | Tag |");
        lines.push("|---|---|---|");
        for (const entry of report.history) {
            const date = entry.timestamp.slice(0, 10);
            const tag = entry.tag ?? "—";
            lines.push(`| ${date} | ${fmt(entry.score)} | ${tag} |`);
        }
        // Show current score as the last row
        lines.push(`| ${new Date().toISOString().slice(0, 10)} | ${fmt(report.score)} | *current* |`);
        lines.push("");
    }
    return lines.join("\n");
}
/**
 * Generate a structured readiness report for a given feature area.
 *
 * This is a pure function — it takes all data as parameters and produces
 * a structured report. No I/O.
 */
export function generateReadinessReport(opts) {
    const { area, gapAnalysis, history = [], scoreSummary, thresholdConfig, } = opts;
    // Find the area's scores
    const areaScore = scoreSummary.scores.find((s) => s.feature === area);
    if (!areaScore) {
        throw new Error(`Area "${area}" not found in score summary. Available areas: ${scoreSummary.scores.map((s) => s.feature).join(", ")}`);
    }
    // Evaluate thresholds for the full summary (to get violations)
    const thresholdEvaluation = evaluateThresholds(scoreSummary, thresholdConfig);
    // Filter violations to only this area
    const areaViolations = thresholdEvaluation.violations.filter((v) => v.area === area);
    // Resolve per-area thresholds (with defaults)
    const areaOverrides = thresholdConfig.areas?.[area];
    const compositeThreshold = areaOverrides?.composite ?? thresholdConfig.defaults.composite;
    const dimDefaults = thresholdConfig.defaults.dimensions ?? {};
    const dimOverrides = areaOverrides?.dimensions ?? {};
    // Build dimension checks
    const dimensions = [
        {
            dimension: "Task Completion",
            pass: areaScore.taskCompletion >=
                (dimOverrides["task-completion"] ??
                    dimDefaults["task-completion"] ??
                    0),
            score: areaScore.taskCompletion,
            threshold: dimOverrides["task-completion"] ?? dimDefaults["task-completion"] ?? 0,
        },
        {
            dimension: "Code Correctness",
            pass: areaScore.codeCorrectness >=
                (dimOverrides["code-correctness"] ??
                    dimDefaults["code-correctness"] ??
                    0),
            score: areaScore.codeCorrectness,
            threshold: dimOverrides["code-correctness"] ??
                dimDefaults["code-correctness"] ??
                0,
        },
        {
            dimension: "Doc Coverage",
            pass: areaScore.docCoverage >=
                (dimOverrides["doc-coverage"] ?? dimDefaults["doc-coverage"] ?? 0),
            score: areaScore.docCoverage,
            threshold: dimOverrides["doc-coverage"] ?? dimDefaults["doc-coverage"] ?? 0,
        },
    ];
    // Filter gap analysis to this area
    const areaGaps = gapAnalysis?.gaps.filter((g) => g.area === area) ?? [];
    // Ceiling decomposition
    const ceiling = {
        ceilingScore: areaScore.ceilingScore,
        docLift: areaScore.docLift,
        docQualityGap: areaScore.docQualityGap,
        floorScore: areaScore.floorScore,
    };
    const pass = areaViolations.length === 0;
    return {
        area,
        ceiling,
        dimensions,
        gaps: areaGaps,
        history,
        pass,
        score: areaScore.totalScore,
        threshold: compositeThreshold,
        thresholdEvaluation,
        violations: areaViolations,
    };
}
// ---------------------------------------------------------------------------
// Formatting helpers (private)
// ---------------------------------------------------------------------------
/** Format a score for display (round to nearest integer) */
function fmt(n) {
    return String(Math.round(n));
}
/** Convert kebab-case area name to title case */
function formatAreaLabel(area) {
    return area
        .split("-")
        .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
        .join(" ");
}
