/**
 * TODO tag validator for Acurity Architect.
 * Scans comment text for TODO, FIXME, and HACK tags and emits
 * informational/warning diagnostics in the VS Code Problems panel.
 *
 * Only non-output lines are scanned. A string-aware scan locates the "//"
 * comment so that "//" inside string literals is never mistaken for a comment.
 * Tags inside OICC output lines (>>) are also excluded via isOutput.
 */

import { createDiagnostic } from "../diagnostics/diagnosticFactory.js";

const TODO_TAGS = [
    { pattern: /^\/\/\s*TODO\s*:/i,  messageId: "ACU-TODO-001" },
    { pattern: /^\/\/\s*FIXME\s*:/i, messageId: "ACU-TODO-002" },
    { pattern: /^\/\/\s*HACK\s*:/i,  messageId: "ACU-TODO-003" },
];

/**
 * Finds the column index of the first "//" comment token in lineText that
 * is not inside a string literal. Returns -1 if no comment is present.
 */
function findCommentStart(lineText) {
    let inString = false;
    let stringChar = null;

    for (let i = 0; i < lineText.length - 1; i++) {
        const char = lineText[i];

        if (inString) {
            if (char === stringChar) {
                inString = false;
            }
            continue;
        }

        if (char === '"' || char === "'") {
            inString = true;
            stringChar = char;
        } else if (char === "/" && lineText[i + 1] === "/") {
            return i;
        }
    }

    return -1;
}

/**
 * Validates TODO/FIXME/HACK tags in comment text.
 * @param {vscode.TextDocument} document
 * @param {Function} getRuleSeverity
 * @param {Object} options
 * @returns {vscode.Diagnostic[]}
 */
function validateTodoTags(document, getRuleSeverity, options = {}) {
    const diagnostics = [];

    for (let lineIndex = 0; lineIndex < document.lineCount; lineIndex++) {
        if (options.executionClassificationMap) {
            const cls = options.executionClassificationMap[lineIndex];
            if (cls.isOutput) {
                continue;
            }
        }

        const lineText = document.lineAt(lineIndex).text;
        const commentStart = findCommentStart(lineText);
        if (commentStart === -1) {
            continue;
        }

        const commentText = lineText.substring(commentStart);

        for (const tag of TODO_TAGS) {
            if (tag.pattern.test(commentText)) {
                const colonIndex = commentText.indexOf(":");
                const description = colonIndex !== -1
                    ? commentText.substring(colonIndex + 1).trim()
                    : "";

                const diag = createDiagnostic(
                    { start: { line: lineIndex, character: commentStart }, end: { line: lineIndex, character: lineText.length } },
                    { messageId: tag.messageId, params: { description } },
                    getRuleSeverity
                );
                if (diag) {
                    diagnostics.push(diag);
                }
                break;
            }
        }
    }

    return diagnostics;
}

export { validateTodoTags };
