/**
 * Keyword completion provider for Acurity Architect.
 * Offers block-closing and statement-opening keywords at statement start.
 */

import * as vscode from "vscode";
import { LANGUAGE_ID } from "../../core/src/constants.js";
import { getBlockContextAtLine } from "../../core/src/analysis/blockContext.js";
import { isStatementStart, isAfterBlockCloser } from "../../core/src/analysis/completionContext.js";
import { parseIncludeDirective } from "../../core/src/parser.js";

// ---------------------------------------------------------------------------
// Keyword tables
// ---------------------------------------------------------------------------

/**
 * Block-closing completions offered when cursor is inside each block kind.
 * Innermost block only.
 */
const CLOSERS_BY_KIND = {
    "IF": [
        { label: "ELSE",        detail: "Else branch",                       sort: "0_ELSE" },
        { label: "ENDIF",       detail: "Close IF block",                    sort: "0_ENDIF" }
    ],
    "DO": [
        { label: "BREAK",       detail: "Exit the DO loop",                  sort: "0_BREAK" },
        { label: "CONTINUE",    detail: "Jump to next DO iteration",         sort: "0_CONTINUE" },
        { label: "UNTIL",       detail: "Exit DO loop when condition is true", sort: "0_UNTIL" },
        { label: "ENDDO",       detail: "Close DO block",                    sort: "0_ENDDO" }
    ],
    "CASE": [
        { label: "VALUE",       detail: "CASE branch (expression match)",    sort: "0_VALUE" },
        { label: "OTHERWISE",   detail: "Default CASE branch",               sort: "0_OTHERWISE" },
        { label: "ENDCASE",     detail: "Close CASE block",                  sort: "0_ENDCASE" }
    ],
    "FUNCTION": [
        { label: "RETURN",      detail: "Return a value",                    sort: "0_RETURN" },
        { label: "ENDFUNCTION", detail: "Close FUNCTION block",              sort: "0_ENDFUNCTION" }
    ]
};

/** Statement-opening keywords always available at statement start. */
const ALWAYS_AVAILABLE = [
    // Block openers
    { label: "IF",             detail: "Conditional block",               sort: "1_IF" },
    { label: "DO",             detail: "Loop block",                      sort: "1_DO" },
    { label: "CASE",           detail: "Multi-branch block",              sort: "1_CASE" },
    { label: "FUNCTION",       detail: "Function definition",             sort: "1_FUNCTION" },
    { label: "MACRO",          detail: "Macro declaration (single line)", sort: "1_MACRO" },
    // Variable declarations
    { label: "STRING",         detail: "Declare STRING variable",         sort: "1_STRING" },
    { label: "SHORT",          detail: "Declare SHORT variable",          sort: "1_SHORT" },
    { label: "LONG",           detail: "Declare LONG variable",           sort: "1_LONG" },
    { label: "DOUBLE",         detail: "Declare DOUBLE variable",         sort: "1_DOUBLE" },
    { label: "DATE",           detail: "Declare DATE variable",           sort: "1_DATE" },
    { label: "TIME",           detail: "Declare TIME variable",           sort: "1_TIME" },
    // Directives and assignment
    { label: "SET",            detail: "Assignment statement",            sort: "1_SET" },
    { label: "OPTION",         detail: "Set document option",             sort: "1_OPTION" },
    { label: "NEWINTERPRETER", detail: "Reset interpreter state",         sort: "1_NEWINTERPRETER" },
    { label: "INCLUDE",        detail: "Include another file",            sort: "1_INCLUDE" },
    { label: "INCLUDEONCE",    detail: "Include file at most once",       sort: "1_INCLUDEONCE" },
    { label: "INCLUDETEST",    detail: "Include file in tests only",      sort: "1_INCLUDETEST" },
    { label: "REQUIRE",        detail: "Require another file",            sort: "1_REQUIRE" },
    { label: "EXIT",           detail: "Exit the report",                 sort: "1_EXIT" },
    { label: "END-OF-CODE",    detail: "Mark end of executable code",     sort: "1_END-OF-CODE" },
    // Low priority
    { label: "VAR",            detail: "Declare variable (legacy)",       sort: "2_VAR" },
    { label: "HASH-ON",        detail: "Switch to hash-on mode",          sort: "2_HASH-ON" },
    { label: "HASH-OFF",       detail: "Switch to hash-off mode",         sort: "2_HASH-OFF" }
];

// ---------------------------------------------------------------------------
// Line-type guards (mirrors builtinCompletionProvider)
// ---------------------------------------------------------------------------

function isSuppressedLine(lineText) {
    const t = lineText.trimStart();
    return t.startsWith("//") || /^#\s*\/\//.test(t) || /^#\s*NOTE\b/i.test(t);
}

function isOutputLine(lineText) {
    const t = lineText.trimStart();
    return t.startsWith(">>") || t.startsWith("??") || /^#\s*\?\?/.test(t);
}

// ---------------------------------------------------------------------------
// Core
// ---------------------------------------------------------------------------

function createKeywordCompletionItems(document, position) {
    const lineText = document.lineAt(position.line).text;
    const linePrefix = lineText.slice(0, position.character);

    if (isSuppressedLine(lineText)) return [];
    if (isOutputLine(lineText)) return [];
    if (parseIncludeDirective(lineText) || /^\s*#?\s*(INCLUDE(?:ONCE|TEST)?|REQUIRE)\s/i.test(lineText)) return [];
    if (isAfterBlockCloser(linePrefix)) return [];
    if (!isStatementStart(linePrefix)) return [];

    const { stack } = getBlockContextAtLine(document, position.line);
    const innermostKind = stack.length > 0 ? stack[stack.length - 1].kind : null;

    // Extract the identifier fragment the user has typed so far for prefix filtering.
    const typedUpper = (linePrefix.match(/([A-Za-z][A-Za-z0-9_-]*)$/) || ["", ""])[1].toUpperCase();

    const candidates = [
        ...(innermostKind && CLOSERS_BY_KIND[innermostKind] ? CLOSERS_BY_KIND[innermostKind] : []),
        ...ALWAYS_AVAILABLE
    ];

    const items = [];
    for (const entry of candidates) {
        if (typedUpper && !entry.label.toUpperCase().startsWith(typedUpper)) continue;

        const item = new vscode.CompletionItem(entry.label, vscode.CompletionItemKind.Keyword);
        item.insertText = entry.label;
        item.detail = entry.detail;
        item.sortText = entry.sort;
        item.filterText = entry.label.toUpperCase();
        items.push(item);
    }

    return items;
}

// ---------------------------------------------------------------------------
// Registration
// ---------------------------------------------------------------------------

function initializeKeywordCompletionProvider(context) {
    const provider = vscode.languages.registerCompletionItemProvider(
        LANGUAGE_ID,
        {
            provideCompletionItems(document, position) {
                return createKeywordCompletionItems(document, position);
            }
        }
    );
    context.subscriptions.push(provider);
}

export {
    initializeKeywordCompletionProvider,
    createKeywordCompletionItems
};
