/**
 * Function call whitespace validator for Acurity Architect.
 * Flags whitespace between a function/built-in name and its opening parenthesis.
 *
 * - ACU-FNC-012: Whitespace is not allowed between '{name}' and '('.
 *
 * Severity: warning in default, error in strict, off in legacy.
 *
 * Design:
 *   - Token-stream scan: IDENTIFIER immediately followed by WHITESPACE then LPAREN
 *     on the same line indicates a space before the argument list.
 *   - Only IDENTIFIER tokens are checked; KEYWORD tokens (IF, WHILE, DO, etc.)
 *     are excluded since they don't form function calls.
 *   - The diagnostic range covers the whitespace characters between the name
 *     and '(', so a fix can delete the range directly.
 */

import { TokenType } from "../lexer/tokenTypes.js";
import { buildDocumentAst } from "../ast/documentAst.js";
import { createDiagnostic } from "../diagnostics/diagnosticFactory.js";

/**
 * Validates that function names are not followed by whitespace before '('.
 *
 * @param {object} document - VS Code TextDocument or PlainTextDocument
 * @param {Function} getRuleSeverity - (ruleId: string) => DiagnosticSeverity|null
 * @param {object} [options]
 * @param {object[]} [options.executionClassificationMap]
 * @returns {object[]}
 */
function validateFunctionWhitespace(document, getRuleSeverity, options = {}) {
    const diagnostics = [];
    const ecm = options.executionClassificationMap || null;

    // Early exit if rule is disabled for all profiles.
    if (getRuleSeverity("functionCallWhitespace") === null) return diagnostics;

    const { tokens } = buildDocumentAst(document);

    for (let i = 0; i < tokens.length; i++) {
        const token = tokens[i];
        if (token.type !== TokenType.IDENTIFIER) continue;

        // Skip output or non-executable lines.
        if (ecm) {
            const cls = ecm[token.line];
            if (cls && (cls.isOutput || !cls.isExecutable)) continue;
        }

        // Advance past any whitespace on the same line.
        let j = i + 1;
        while (j < tokens.length && tokens[j].line === token.line &&
               tokens[j].type === TokenType.WHITESPACE) {
            j++;
        }

        if (j >= tokens.length || tokens[j].line !== token.line) continue;
        if (tokens[j].type !== TokenType.LPAREN) continue;

        const lparen = tokens[j];
        const identEnd = token.char + token.value.length;

        if (lparen.char > identEnd) {
            // There is whitespace between the identifier and '('.
            const range = {
                start: { line: token.line, character: identEnd },
                end:   { line: token.line, character: lparen.char }
            };
            const diag = createDiagnostic(
                range,
                { messageId: "ACU-FNC-012", params: { name: token.value } },
                getRuleSeverity
            );
            if (diag) diagnostics.push(diag);
        }
    }

    return diagnostics;
}

export { validateFunctionWhitespace };
