"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.selectPreferredVerb = selectPreferredVerb;
exports.auditDisallowedDefineUsage = auditDisallowedDefineUsage;
exports.formatVerbPolicyDiagnostics = formatVerbPolicyDiagnostics;
exports.resolveVerbPolicyEnforcementMode = resolveVerbPolicyEnforcementMode;
const CONTRACT_TERMS = [
    "boundary",
    "schema",
    "vocabulary",
    "policy",
    "rule",
    "interface",
    "decision",
    "contract"
];
const EXECUTABLE_ACTION_TERMS = [
    "add",
    "build",
    "change",
    "create",
    "fix",
    "generate",
    "implement",
    "run",
    "execute",
    "wire",
    "start",
    "migrate",
    "serve",
    "emit",
    "validate behavior"
];
function selectPreferredVerb(options) {
    if (options.intentCategory === "contract") {
        return "define";
    }
    if (options.intentCategory === "runtime-behavior") {
        return "implement";
    }
    if (options.intentCategory === "review") {
        return "review";
    }
    if (options.intentCategory === "evidence") {
        return "capture";
    }
    if (options.sectionType === "scope") {
        return "specify";
    }
    return "document";
}
function auditDisallowedDefineUsage(options) {
    const sectionBodies = extractSecondLevelSections(options.markdownText);
    const violations = [];
    for (const policy of options.sectionPolicies) {
        const sectionText = sectionBodies.get(policy.sectionName);
        if (sectionText === undefined || sectionText.trim() === "") {
            continue;
        }
        for (const sentence of splitSentences(sectionText)) {
            const actionableSentence = sentence.replace(/([`'\"]+)define\1/gi, "");
            if (!/\bdefine\b/i.test(actionableSentence)) {
                continue;
            }
            const classification = classifyDefineSentence(actionableSentence, policy);
            if (classification.allowed) {
                continue;
            }
            violations.push({
                sectionName: policy.sectionName,
                sectionType: policy.sectionType,
                sentence,
                suggestedVerb: classification.suggestedVerb,
                reason: classification.reason
            });
        }
    }
    return violations;
}
function formatVerbPolicyDiagnostics(violations) {
    return violations.map((violation) => {
        return [
            `[${violation.sectionName}] ${violation.reason}`,
            `Sentence: ${violation.sentence}`,
            `Suggested verb: ${violation.suggestedVerb}`
        ].join(" ");
    });
}
function resolveVerbPolicyEnforcementMode(rawMode) {
    if (rawMode?.trim().toLowerCase() === "warn") {
        return "warn";
    }
    return "strict";
}
function classifyDefineSentence(sentence, policy) {
    const lower = sentence.toLowerCase();
    if (hasAnyTerm(lower, EXECUTABLE_ACTION_TERMS)) {
        const suggestedVerb = lower.includes("validate behavior") ? "validate" : "implement";
        return {
            allowed: false,
            suggestedVerb,
            reason: "'define' cannot be mixed with executable outcome language; use an implementation-oriented verb."
        };
    }
    if (hasAnyTerm(lower, CONTRACT_TERMS) && hasNamedDurableContract(sentence) && hasDownstreamConsumer(lower)) {
        return {
            allowed: true,
            suggestedVerb: "define",
            reason: "'define' is allowed for a named durable contract with an identified downstream consumer."
        };
    }
    if (hasAnyTerm(lower, CONTRACT_TERMS)) {
        return {
            allowed: false,
            suggestedVerb: "specify",
            reason: "'define' requires both a named durable contract and an identified downstream consumer."
        };
    }
    if (policy.intentCategory === "prose" || policy.intentCategory === "evidence") {
        const suggestedVerb = selectPreferredVerb(policy);
        return {
            allowed: false,
            suggestedVerb,
            reason: "'define' requires explicit contract terms; use a prose or evidence verb for explanatory sections."
        };
    }
    return {
        allowed: false,
        suggestedVerb: selectPreferredVerb(policy),
        reason: "'define' is not allowed in this section without contract-setting evidence."
    };
}
function hasNamedDurableContract(sentence) {
    if (/`[^`]+`/.test(sentence)) {
        return true;
    }
    const normalized = sentence.replace(/[`'"*_]/g, " ").toLowerCase();
    return CONTRACT_TERMS.some((term) => {
        const match = normalized.match(new RegExp(`\\b([a-z0-9-]+)\\s+${escapeRegExp(term)}\\b`, "i"));
        if (match === null) {
            return false;
        }
        return !["a", "an", "the", "this", "that", "new", "named", "durable", "shared", "canonical"].includes(match[1]);
    });
}
function hasDownstreamConsumer(lowerSentence) {
    return /\b(consum(?:e|ed|er|ers|ing)|downstream|used by|read by|implemented by|validated by|enforced by|projected (?:to|by)|for [a-z0-9_-]+ (?:to|that|which))\b/i.test(lowerSentence);
}
function escapeRegExp(value) {
    return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function hasAnyTerm(input, terms) {
    return terms.some((term) => input.includes(term));
}
function splitSentences(sectionText) {
    const lines = sectionText
        .split(/\r?\n/)
        .map((line) => line.trim())
        .filter((line) => line !== "");
    const sentences = [];
    for (const line of lines) {
        for (const candidate of line.split(/(?<=[.!?])\s+/)) {
            const sentence = candidate.trim();
            if (sentence !== "") {
                sentences.push(sentence);
            }
        }
    }
    return sentences;
}
function extractSecondLevelSections(markdownText) {
    const sections = new Map();
    const lines = markdownText.split(/\r?\n/);
    let currentSection = null;
    for (const line of lines) {
        const headingMatch = line.match(/^##\s+(.+?)\s*$/);
        if (headingMatch !== null) {
            currentSection = headingMatch[1];
            sections.set(currentSection, []);
            continue;
        }
        if (line.startsWith("# ")) {
            currentSection = null;
            continue;
        }
        if (currentSection !== null) {
            sections.get(currentSection)?.push(line);
        }
    }
    const normalized = new Map();
    for (const [name, bodyLines] of sections) {
        normalized.set(name, bodyLines.join("\n"));
    }
    return normalized;
}
