/**
 * Handle binding analysis for Acurity Architect.
 *
 * Scans a document up to a given line and returns the set of handle variables
 * currently bound to table codes — i.e. opened via INDEX_OPEN_STANDARD (or any
 * function carrying bindsHandle metadata) but not yet closed via INDEX_CLOSE.
 *
 * This is read infrastructure consumed by the hover provider and, in future,
 * by completion hints. It does not produce diagnostics.
 */

import { BuiltInFunctions } from "../builtins/functions.js";
import { extractArgAt } from "../parser.js";

/**
 * Builds the handle→tableCode binding map as it stands at the start of targetLine.
 *
 * Scans lines 0..(targetLine - 1) in order, tracking:
 *   - bindsHandle calls   → add handle variable to map
 *   - INDEX_CLOSE calls   → remove handle variable from map
 *
 * Map keys are lowercased so lookups are case-insensitive.
 *
 * @param {object} document  - VS Code TextDocument (or plainTextDocument)
 * @param {number} targetLine - Line index to scan up to (exclusive)
 * @returns {Map<string, string>}  varName (lowercase) → tableCode (e.g. "shandle" → "MD")
 */
function buildHandleBindingsAtLine(document, targetLine) {
    const bindings = new Map();

    for (let i = 0; i < targetLine; i++) {
        const lineText = document.lineAt(i).text;

        const FUNC_CALL_RE = /\b([A-Z_][A-Z0-9_]*)\s*\(/g;
        let match;
        while ((match = FUNC_CALL_RE.exec(lineText)) !== null) {
            const callName = match[1];
            const entry = BuiltInFunctions[callName];
            if (!entry) continue;

            const callExpr = lineText.slice(match.index);

            if (entry.bindsHandle) {
                const { handleParam, tableCodeParam } = entry.bindsHandle;
                const tableArg = extractArgAt(callExpr, tableCodeParam);
                const handleArg = extractArgAt(callExpr, handleParam);
                if (tableArg && handleArg) {
                    // Strip surrounding quotes from the table code string literal
                    const tableCode = tableArg.trim().replace(/^["']|["']$/g, "");
                    const varName = handleArg.trim().toLowerCase();
                    if (tableCode && /^[A-Za-z_][A-Za-z0-9_]*$/.test(varName)) {
                        bindings.set(varName, tableCode);
                    }
                }
            }

            if (callName === "INDEX_CLOSE" || callName === "SQL_INDEX_CLOSE") {
                const handleArg = extractArgAt(callExpr, 0);
                if (handleArg) {
                    bindings.delete(handleArg.trim().toLowerCase());
                }
            }
        }
    }

    return bindings;
}

export { buildHandleBindingsAtLine };
