"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;
}
