/**
 * Output renderers for the compliance scorecard.
 *
 * Three formats:
 *   - `table`     — TTY-friendly columnar layout with sparkline-style daily bars.
 *   - `json`      — Same shape returned by `getComplianceScorecard()`.
 *   - `csv`       — One row per cell, suitable for piping into spreadsheets.
 *   - `markdown`  — GitHub-flavored markdown table; used in PR comments and
 *                   nightly digest emails.
 *
 * All renderers MUST consume the same `ComplianceScorecard` shape so a
 * deterministic snapshot test can pin the output.
 */
const SPARK_CHARS = ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"];
function sparkline(values) {
    if (values.length === 0)
        return "";
    const max = Math.max(...values, 0);
    if (max === 0)
        return SPARK_CHARS[0].repeat(values.length);
    return values
        .map((v) => {
        const idx = Math.min(SPARK_CHARS.length - 1, Math.max(0, Math.round((v / max) * (SPARK_CHARS.length - 1))));
        return SPARK_CHARS[idx];
    })
        .join("");
}
function dailyBackfillSeries(cell) {
    const days = Object.keys(cell.daily_backfill_rate).sort();
    return days.map((d) => cell.daily_backfill_rate[d] ?? 0);
}
function pad(s, width, align = "left") {
    const len = visibleLength(s);
    if (len >= width)
        return s;
    const filler = " ".repeat(width - len);
    return align === "left" ? s + filler : filler + s;
}
function visibleLength(s) {
    // Strip a couple of common ANSI escape sequences. The renderer is plain
    // ASCII so far, so this is mostly future-proofing.
    return s.replace(/\x1b\[[0-9;]*m/g, "").length;
}
function formatPercent(rate) {
    return `${(rate * 100).toFixed(2)} %`;
}
function formatNumber(n) {
    return n.toLocaleString("en-US");
}
function colorize(s, code, enabled) {
    if (!enabled)
        return s;
    return `\x1b[${code}m${s}\x1b[0m`;
}
function renderTable(card, options) {
    const color = options.color ?? false;
    const lines = [];
    const window = formatWindowLabel(card);
    lines.push(`Compliance Scorecard — ${window}`);
    lines.push(`group_by=${card.group_by} cells=${card.summary.cell_count} turns=${formatNumber(card.summary.total_turns)} backfill_rate=${formatPercent(card.summary.backfill_rate)}`);
    if (card.estimated) {
        lines.push("(rows marked * are heuristic estimates from historical data)");
    }
    lines.push("");
    const headers = ["Model", "Harness", "Profile", "Turns", "Backfilled", "Backfill %", "Daily"];
    const rows = [];
    for (const cell of card.cells) {
        const series = dailyBackfillSeries(cell);
        rows.push([
            cell.estimated ? `${cell.model}*` : cell.model,
            cell.harness,
            cell.profile,
            formatNumber(cell.total_turns),
            formatNumber(cell.backfilled_turns),
            formatPercent(cell.backfill_rate),
            sparkline(series),
        ]);
    }
    if (rows.length === 0) {
        lines.push("(no cells matched the supplied filters)");
        if (card.summary.top_missed_steps.length > 0) {
            lines.push("");
            lines.push("Top missed steps (across all rows):");
            for (const step of card.summary.top_missed_steps) {
                lines.push(`  - ${step.step}: ${formatNumber(step.count)}`);
            }
        }
        return lines.join("\n");
    }
    const widths = headers.map((h, idx) => Math.max(visibleLength(h), ...rows.map((r) => visibleLength(r[idx] ?? ""))));
    const aligns = [
        "left",
        "left",
        "left",
        "right",
        "right",
        "right",
        "left",
    ];
    const headerLine = headers
        .map((h, idx) => pad(h, widths[idx], aligns[idx] ?? "left"))
        .join("  ");
    lines.push(colorize(headerLine, "1", color));
    lines.push(widths.map((w) => "-".repeat(w)).join("  "));
    for (const row of rows) {
        const formatted = row
            .map((cellValue, idx) => pad(cellValue, widths[idx], aligns[idx] ?? "left"))
            .join("  ");
        lines.push(formatted);
    }
    if (card.summary.top_missed_steps.length > 0) {
        lines.push("");
        lines.push("Top missed steps (across all rows):");
        for (const step of card.summary.top_missed_steps) {
            lines.push(`  - ${step.step}: ${formatNumber(step.count)}`);
        }
    }
    return lines.join("\n");
}
function renderJson(card) {
    return JSON.stringify(card, null, 2);
}
function csvEscape(value) {
    if (/[",\r\n]/.test(value)) {
        return `"${value.replace(/"/g, '""')}"`;
    }
    return value;
}
function renderCsv(card) {
    const headers = [
        "model",
        "harness",
        "profile",
        "total_turns",
        "backfilled_turns",
        "backfill_rate",
        "estimated",
        "top_missed_step",
    ];
    const lines = [headers.join(",")];
    for (const cell of card.cells) {
        const top = cell.top_missed_steps[0]?.step ?? "";
        lines.push([
            cell.model,
            cell.harness,
            cell.profile,
            String(cell.total_turns),
            String(cell.backfilled_turns),
            cell.backfill_rate.toFixed(4),
            cell.estimated ? "true" : "false",
            top,
        ]
            .map(csvEscape)
            .join(","));
    }
    return lines.join("\n");
}
function renderMarkdown(card) {
    const lines = [];
    lines.push(`# Compliance scorecard — ${formatWindowLabel(card)}`);
    lines.push("");
    lines.push(`- **group_by**: \`${card.group_by}\``);
    lines.push(`- **cells**: ${card.summary.cell_count} | **turns**: ${formatNumber(card.summary.total_turns)} | **backfilled**: ${formatNumber(card.summary.backfilled_turns)} (${formatPercent(card.summary.backfill_rate)})`);
    if (card.estimated) {
        lines.push("- _Some rows are heuristic estimates (marked with \\*)._");
    }
    lines.push("");
    lines.push("| Model | Harness | Profile | Turns | Backfilled | Backfill % |");
    lines.push("| --- | --- | --- | ---: | ---: | ---: |");
    for (const cell of card.cells) {
        lines.push(`| ${cell.estimated ? `${cell.model}*` : cell.model} | ${cell.harness} | ${cell.profile} | ${formatNumber(cell.total_turns)} | ${formatNumber(cell.backfilled_turns)} | ${formatPercent(cell.backfill_rate)} |`);
    }
    if (card.summary.top_missed_steps.length > 0) {
        lines.push("");
        lines.push("## Top missed steps");
        lines.push("");
        for (const step of card.summary.top_missed_steps) {
            lines.push(`- \`${step.step}\` — ${formatNumber(step.count)}`);
        }
    }
    return lines.join("\n");
}
function formatWindowLabel(card) {
    if (card.window.since && card.window.until) {
        return `${card.window.since} → ${card.window.until}`;
    }
    if (card.window.since) {
        return `since ${card.window.since}`;
    }
    if (card.window.until) {
        return `until ${card.window.until}`;
    }
    return "all time";
}
export function renderScorecard(card, format, options = {}) {
    switch (format) {
        case "json":
            return renderJson(card);
        case "csv":
            return renderCsv(card);
        case "markdown":
            return renderMarkdown(card);
        case "table":
        default:
            return renderTable(card, options);
    }
}
//# sourceMappingURL=renderer.js.map