"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DEFAULT_WORKFLOW_TEMPLATE_AUTO_SELECT = void 0;
exports.parseWorkflowTemplateSource = parseWorkflowTemplateSource;
const frontmatter_1 = require("../core/frontmatter");
const catalog_1 = require("../i18n/catalog");
const required_skills_1 = require("./required-skills");
const required_mcp_1 = require("./required-mcp");
const template_errors_1 = require("./template-errors");
const types_1 = require("./types");
const DEFAULT_WORKFLOW_TEMPLATE_TARGET = "issue";
exports.DEFAULT_WORKFLOW_TEMPLATE_AUTO_SELECT = true;
function parseWorkflowTemplateSource(relativePath, source, locale) {
    const frontmatter = (0, frontmatter_1.parseFrontmatterBlock)(source);
    if (frontmatter.kind === "not-frontmatter") {
        return {
            body: source,
            bodyStartLineNumber: 1,
            metadata: null,
        };
    }
    if (frontmatter.kind === "missing-closing-delimiter") {
        throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterMissingClosingDelimiter");
    }
    const metadata = parseWorkflowTemplateMetadata(relativePath, frontmatter.lines, locale);
    return {
        body: frontmatter.body,
        bodyStartLineNumber: frontmatter.bodyStartLineNumber,
        metadata,
    };
}
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: frontmatter parsing keeps key validation in one pass so error positions stay precise.
function parseWorkflowTemplateMetadata(relativePath, lines, locale) {
    let description = null;
    let requiredSkills = null;
    let requiredMcp = null;
    let targets = null;
    let autoSelect = null;
    let updateMode = null;
    for (let index = 0; index < lines.length; index += 1) {
        const line = lines[index] ?? "";
        const trimmed = line.trim();
        if (trimmed.length === 0) {
            continue;
        }
        const parsedLine = (0, frontmatter_1.parseFrontmatterKeyValue)(line);
        if (parsedLine === null) {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidLine");
        }
        const { key } = parsedLine;
        const rawValue = parsedLine.value;
        const value = (0, frontmatter_1.decodeFrontmatterScalar)(rawValue);
        switch (key) {
            case "description":
                if (description !== null) {
                    throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterDuplicateKey", { key });
                }
                description = value.length === 0 ? null : value;
                break;
            case "requires":
                if (requiredSkills !== null || requiredMcp !== null) {
                    throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterDuplicateKey", { key });
                }
                if (rawValue.length !== 0) {
                    throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredSkills");
                }
                {
                    const parsed = parseRequiresBlock(relativePath, lines, index + 1, locale);
                    requiredSkills = parsed.skillRefs;
                    requiredMcp = parsed.mcpRefs;
                    index = parsed.nextIndex - 1;
                }
                break;
            case "targets":
                if (targets !== null) {
                    throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterDuplicateKey", { key });
                }
                if (rawValue.length !== 0) {
                    throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidTargets");
                }
                {
                    const parsed = parseWorkflowTargetsList(relativePath, lines, index + 1, locale);
                    targets = parsed.targets;
                    index = parsed.nextIndex - 1;
                }
                break;
            case "autoSelect":
                if (autoSelect !== null) {
                    throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterDuplicateKey", { key });
                }
                if (value !== "true" && value !== "false") {
                    throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidAutoSelect");
                }
                autoSelect = value === "true";
                break;
            case "updateMode":
                if (updateMode !== null) {
                    throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterDuplicateKey", { key });
                }
                if (!isWorkflowTemplateUpdateMode(value)) {
                    throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidUpdateMode");
                }
                updateMode = value;
                break;
            default:
                throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterUnknownKey", { key });
        }
    }
    return {
        description,
        requiredSkills: requiredSkills ?? [],
        requiredMcp: requiredMcp ?? [],
        targets: targets ?? [DEFAULT_WORKFLOW_TEMPLATE_TARGET],
        autoSelect: autoSelect ?? exports.DEFAULT_WORKFLOW_TEMPLATE_AUTO_SELECT,
        ...(updateMode !== null ? { updateMode } : {}),
    };
}
function isWorkflowTemplateUpdateMode(value) {
    return types_1.WORKFLOW_TEMPLATE_UPDATE_MODES.includes(value);
}
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: requires.skills and requires.mcp parsing stays together to keep frontmatter diagnostics consistent.
function parseRequiresBlock(relativePath, lines, startIndex, locale) {
    let skillRefs = null;
    let mcpRefs = null;
    let index = startIndex;
    for (; index < lines.length;) {
        const line = lines[index] ?? "";
        if (line.trim().length === 0) {
            index += 1;
            continue;
        }
        if (getIndentWidth(line) === 0) {
            break;
        }
        const parsedLine = (0, frontmatter_1.parseFrontmatterKeyValue)(line);
        if (parsedLine === null) {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredSkills");
        }
        if (parsedLine.key !== "skills" && parsedLine.key !== "mcp") {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterUnknownKey", { key: `requires.${parsedLine.key}` });
        }
        if (parsedLine.key === "skills") {
            if (skillRefs !== null) {
                throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterDuplicateKey", { key: "requires.skills" });
            }
            if (parsedLine.value === "[]") {
                skillRefs = [];
                index += 1;
                continue;
            }
            if (parsedLine.value.length !== 0) {
                throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredSkills");
            }
            const parsedSkills = parseRequiredSkillsList(relativePath, lines, index + 1, locale, { parentIndent: getIndentWidth(line) });
            skillRefs = parsedSkills.skillRefs;
            index = parsedSkills.nextIndex;
            continue;
        }
        if (mcpRefs !== null) {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterDuplicateKey", { key: "requires.mcp" });
        }
        if (parsedLine.value === "[]") {
            mcpRefs = [];
            index += 1;
            continue;
        }
        if (parsedLine.value.length !== 0) {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredMcp");
        }
        const parsedMcp = parseRequiredMcpList(relativePath, lines, index + 1, locale, { parentIndent: getIndentWidth(line) });
        mcpRefs = parsedMcp.mcpRefs;
        index = parsedMcp.nextIndex;
    }
    if (skillRefs === null && mcpRefs === null) {
        throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredSkills");
    }
    return {
        skillRefs: skillRefs ?? [],
        mcpRefs: mcpRefs ?? [],
        nextIndex: index,
    };
}
function parseRequiredSkillsList(relativePath, lines, startIndex, locale, options) {
    const skillRefs = [];
    let index = startIndex;
    for (; index < lines.length; index += 1) {
        const line = lines[index] ?? "";
        if (line.trim().length === 0) {
            continue;
        }
        if (getIndentWidth(line) <= options.parentIndent) {
            break;
        }
        const itemMatch = line.match(/^\s*-\s+(.+?)\s*$/u);
        if (!itemMatch) {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredSkills");
        }
        const skillRef = (0, frontmatter_1.decodeFrontmatterScalar)(itemMatch[1] ?? "").trim();
        if (!(0, required_skills_1.isValidRequiredSkillRef)(skillRef)) {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredSkillId", { skillRef });
        }
        skillRefs.push(skillRef);
    }
    if (skillRefs.length === 0) {
        throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredSkills");
    }
    if ((0, required_skills_1.dedupeRequiredSkillRefs)(skillRefs).length !== skillRefs.length) {
        throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterDuplicateRequiredSkill");
    }
    return { skillRefs, nextIndex: index };
}
function parseRequiredMcpList(relativePath, lines, startIndex, locale, options) {
    const mcpRefs = [];
    let index = startIndex;
    for (; index < lines.length; index += 1) {
        const line = lines[index] ?? "";
        if (line.trim().length === 0) {
            continue;
        }
        if (getIndentWidth(line) <= options.parentIndent) {
            break;
        }
        const itemMatch = line.match(/^\s*-\s+(.+?)\s*$/u);
        if (!itemMatch) {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredMcp");
        }
        const mcpRef = (0, frontmatter_1.decodeFrontmatterScalar)(itemMatch[1] ?? "").trim();
        if (!(0, required_mcp_1.isValidRequiredMcpRef)(mcpRef)) {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredMcpId", { mcpRef });
        }
        mcpRefs.push(mcpRef);
    }
    if (mcpRefs.length === 0) {
        throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidRequiredMcp");
    }
    if ((0, required_mcp_1.dedupeRequiredMcpRefs)(mcpRefs).length !== mcpRefs.length) {
        throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterDuplicateRequiredMcp");
    }
    return { mcpRefs, nextIndex: index };
}
function getIndentWidth(line) {
    return line.match(/^\s*/u)?.[0].length ?? 0;
}
function parseWorkflowTargetsList(relativePath, lines, startIndex, locale) {
    const targets = [];
    let index = startIndex;
    for (; index < lines.length; index += 1) {
        const line = lines[index] ?? "";
        if (line.trim().length === 0) {
            continue;
        }
        if (!/^\s/u.test(line)) {
            break;
        }
        const itemMatch = line.match(/^\s*-\s+(.+?)\s*$/u);
        if (!itemMatch) {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidTargets");
        }
        const target = (0, frontmatter_1.decodeFrontmatterScalar)(itemMatch[1] ?? "").trim();
        if (!isWorkflowTarget(target)) {
            throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidTarget", { target });
        }
        targets.push(target);
    }
    if (targets.length === 0) {
        throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterInvalidTargets");
    }
    if (new Set(targets).size !== targets.length) {
        throw invalidTemplateMetadataError(relativePath, locale, "workflow.templateHealth.frontmatterDuplicateTarget");
    }
    return { targets, nextIndex: index };
}
function isWorkflowTarget(value) {
    return (value === "issue" ||
        value === "pull_request" ||
        value === "unplanned" ||
        value === "followup");
}
function invalidTemplateMetadataError(relativePath, locale, reasonKey, variables = {}) {
    return new template_errors_1.WorkflowTemplateCatalogError("invalid-template-metadata", (0, catalog_1.translate)(locale, "workflow.templateHealth.invalidTemplateMetadata", {
        fileName: relativePath,
        reason: (0, catalog_1.translate)(locale, reasonKey, variables),
    }), {
        fileName: relativePath,
        reasonKey,
        ...variables,
    });
}
