/**
 * extract-code-blocks — pull TS/TSX/JS/JSX source out of a candidate
 * response that's typically structured as markdown prose plus one or
 * more fenced code blocks.
 *
 * AI candidates almost always wrap their code in triple-backtick fences
 * with language hints (`\`\`\`tsx`, `\`\`\`typescript`, …). Feeding that
 * raw text to `parseImports` (which calls a strict TS parser) extracts
 * zero imports because the markdown surrounds — and breaks — the parse.
 *
 * Strategy: pull every fenced block whose language hint is in the
 * allow-list (or unset, which we treat as TS-compatible by convention),
 * concatenate the contents with blank-line separators, and return that.
 * When the input has no recognized fences, return it unchanged so a
 * raw-code candidate still parses.
 *
 * Out of scope: indented (4-space) code blocks. The corpus uses fenced
 * blocks exclusively, and supporting indented blocks would require a
 * markdown parser; the candidate-corpus reality doesn't justify it.
 */
const ALLOWED_LANGS = new Set([
    "tsx",
    "ts",
    "typescript",
    "jsx",
    "js",
    "javascript",
    "",
]);
const FENCE_RE = /^([ \t]*)```([^\n`]*)\n([\s\S]*?)\n[ \t]*```\s*$/gm;
export function extractCodeBlocks(text) {
    let sawAnyFence = false;
    const blocks = [];
    for (const match of text.matchAll(FENCE_RE)) {
        sawAnyFence = true;
        const lang = (match[2] ?? "").trim().toLowerCase();
        if (!ALLOWED_LANGS.has(lang))
            continue;
        blocks.push(match[3] ?? "");
    }
    // No fences at all → assume the candidate emitted raw source.
    if (!sawAnyFence)
        return text;
    // Fences were present but none in a JS/TS-family language.
    if (blocks.length === 0)
        return "";
    return blocks.join("\n\n");
}
