/**
 * Suppression comment parser for Acurity diagnostic overrides.
 *
 * Supported syntax:
 *   // @rule-ignore ACU-XXX-NNN
 *   // @rule-ignore ACU-XXX-NNN ACU-YYY-NNN   (multiple IDs)
 *   // @rule-ignore ACU-XXX-NNN REASON: some explanation
 *
 * The comment must appear on the line IMMEDIATELY ABOVE the offending code.
 * Diagnostic IDs must follow the ACU-DOMAIN-NNN format (e.g. ACU-VAR-001).
 * The REASON: clause and any trailing text are ignored by the parser.
 */

/** @type {RegExp} Matches a // comment containing @rule-ignore followed by one or more ACU-XXX-NNN tokens */
const RULE_IGNORE_RE = /^\s*\/\/\s*@rule-ignore\s+((?:ACU-[A-Z]+-\d{3}\s*)+)/i;

/** @type {RegExp} Validates individual ACU rule ID tokens */
const ACU_ID_RE = /^ACU-[A-Z]+-\d{3}$/i;

/**
 * Parse suppression comments from a document and build a suppression map.
 * Each `// @rule-ignore ACU-XXX-NNN` on line N suppresses those rule IDs on line N+1.
 *
 * @param {import('vscode').TextDocument} document
 * @returns {Map<number, Set<string>>} Map of 0-based line index → set of suppressed messageIds
 */
function buildSuppressionMap(document) {
    const suppressions = new Map();

    for (let lineIndex = 0; lineIndex < document.lineCount; lineIndex++) {
        const lineText = document.lineAt(lineIndex).text;
        const match = RULE_IGNORE_RE.exec(lineText);
        if (!match) {
            continue;
        }

        const ids = match[1]
            .trim()
            .split(/\s+/)
            .filter((token) => ACU_ID_RE.test(token))
            .map((id) => id.toUpperCase());

        if (ids.length === 0) {
            continue;
        }

        const targetLine = lineIndex + 1;
        if (targetLine >= document.lineCount) {
            continue;
        }

        if (!suppressions.has(targetLine)) {
            suppressions.set(targetLine, new Set());
        }
        ids.forEach((id) => suppressions.get(targetLine).add(id));
    }

    return suppressions;
}

/**
 * Check whether a diagnostic should be suppressed.
 *
 * @param {string} messageId  - Diagnostic message ID, e.g. "ACU-PAT-001"
 * @param {number} lineIndex  - 0-based line index of the diagnostic
 * @param {Map<number, Set<string>>} suppressionMap - From buildSuppressionMap()
 * @returns {boolean}
 */
function isSuppressed(messageId, lineIndex, suppressionMap) {
    const set = suppressionMap.get(lineIndex);
    return set !== undefined && set.has(messageId.toUpperCase());
}

export {
    buildSuppressionMap,
    isSuppressed
};
