/*
 * Copyright 2026, Jaime Terrats.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { CompletionItemKind, InsertTextFormat } from 'vscode-languageserver';
import { detectContext } from '../document-context.js';
import { getEntriesByType, isIndexLoaded, searchEntries } from '../index-loader.js';
// ─── Supported Extensions ─────────────────────────────────────────────────────
const COMPLETION_EXTENSIONS = new Set(['.cls', '.trigger', '.js', '.ts']);
// ─── Completion Handler ───────────────────────────────────────────────────────
export function handleCompletion(params, getDocument) {
    if (!isIndexLoaded()) {
        return [];
    }
    const document = getDocument(params.textDocument.uri);
    if (!document) {
        return [];
    }
    const uri = params.textDocument.uri;
    const extension = getFileExtension(uri);
    if (!COMPLETION_EXTENSIONS.has(extension)) {
        return [];
    }
    const position = params.position;
    const lineText = getLineText(document, position.line);
    const allLines = getAllLines(document, position.line);
    const context = detectContext(lineText, position.character, extension, allLines);
    return getCompletionsForContext(context);
}
// ─── Context-specific Completions ─────────────────────────────────────────────
function getCompletionsForContext(context) {
    switch (context.kind) {
        case 'apex:class-reference':
            return getApexClassCompletions(context.prefix);
        case 'apex:soql-from':
            return getSoqlObjectCompletions(context.prefix);
        case 'apex:soql-field':
            return getSoqlFieldCompletions(context.prefix, context.soqlObject);
        case 'trigger:object':
            return getTriggerObjectCompletions(context.prefix);
        case 'lwc:apex-import':
            return getLwcApexCompletions(context.prefix);
        case 'lwc:schema-import':
            return getLwcSchemaCompletions(context.prefix);
        default:
            return [];
    }
}
function getApexClassCompletions(prefix) {
    const entries = prefix.length > 0 ? searchEntries(prefix) : getEntriesByType('ApexClass');
    const apexEntries = entries.filter((e) => e.type === 'ApexClass');
    return apexEntries.map((entry) => ({
        label: entry.apiName,
        kind: CompletionItemKind.Class,
        detail: formatDetail(entry),
        documentation: formatDocumentation(entry),
        insertText: entry.apiName,
        insertTextFormat: InsertTextFormat.PlainText,
    }));
}
function getSoqlObjectCompletions(prefix) {
    const entries = prefix.length > 0 ? searchEntries(prefix) : getEntriesByType('CustomObject');
    const objectEntries = entries.filter((e) => e.type === 'CustomObject');
    return objectEntries.map((entry) => ({
        label: entry.apiName,
        kind: CompletionItemKind.Struct,
        detail: entry.fields ? `Custom Object (${entry.fields.length} fields)` : 'Custom Object',
        documentation: formatDocumentation(entry),
        insertText: entry.apiName,
        insertTextFormat: InsertTextFormat.PlainText,
    }));
}
function getSoqlFieldCompletions(prefix, soqlObject) {
    if (!soqlObject) {
        return [];
    }
    const entries = prefix.length > 0 ? searchEntries(prefix) : getEntriesByType('CustomField');
    // Filter to fields that belong to the SOQL object
    const fieldEntries = entries.filter((e) => {
        if (e.type !== 'CustomField')
            return false;
        // Field apiName pattern: Object__c.Field__c or just Field__c
        return e.apiName.startsWith(`${soqlObject}.`);
    });
    return fieldEntries.map((entry) => {
        const fieldName = entry.apiName.includes('.') ? entry.apiName.split('.').pop() : entry.apiName;
        return {
            label: fieldName,
            kind: CompletionItemKind.Field,
            detail: `Field on ${soqlObject}`,
            documentation: formatDocumentation(entry),
            insertText: fieldName,
            insertTextFormat: InsertTextFormat.PlainText,
        };
    });
}
function getTriggerObjectCompletions(prefix) {
    const entries = prefix.length > 0 ? searchEntries(prefix) : getEntriesByType('CustomObject');
    const objectEntries = entries.filter((e) => e.type === 'CustomObject');
    return objectEntries.map((entry) => ({
        label: entry.apiName,
        kind: CompletionItemKind.Struct,
        detail: 'Custom Object',
        documentation: formatDocumentation(entry),
        insertText: entry.apiName,
        insertTextFormat: InsertTextFormat.PlainText,
    }));
}
function getLwcApexCompletions(prefix) {
    const entries = prefix.length > 0 ? searchEntries(prefix) : getEntriesByType('ApexClass');
    const apexEntries = entries.filter((e) => e.type === 'ApexClass');
    return apexEntries
        .map((entry) => {
        const methods = entry.methods ?? [];
        if (methods.length > 0 && !prefix.includes('.')) {
            // Show class.method completions
            return methods.map((method) => ({
                label: `${entry.apiName}.${method}`,
                kind: CompletionItemKind.Method,
                detail: `Apex method: ${entry.apiName}.${method}`,
                insertText: `${entry.apiName}.${method}`,
                insertTextFormat: InsertTextFormat.PlainText,
            }));
        }
        return [
            {
                label: entry.apiName,
                kind: CompletionItemKind.Class,
                detail: formatDetail(entry),
                insertText: entry.apiName,
                insertTextFormat: InsertTextFormat.PlainText,
            },
        ];
    })
        .flat();
}
function getLwcSchemaCompletions(prefix) {
    const items = [];
    // Object completions
    const objects = getEntriesByType('CustomObject');
    for (const obj of objects) {
        if (prefix.length === 0 || obj.apiName.toLowerCase().startsWith(prefix.toLowerCase())) {
            items.push({
                label: obj.apiName,
                kind: CompletionItemKind.Struct,
                detail: 'Custom Object',
                insertText: obj.apiName,
                insertTextFormat: InsertTextFormat.PlainText,
            });
        }
    }
    // Field completions (Object.Field format)
    if (prefix.includes('.')) {
        const fields = getEntriesByType('CustomField');
        for (const field of fields) {
            if (field.apiName.toLowerCase().startsWith(prefix.toLowerCase())) {
                items.push({
                    label: field.apiName,
                    kind: CompletionItemKind.Field,
                    detail: 'Custom Field',
                    insertText: field.apiName,
                    insertTextFormat: InsertTextFormat.PlainText,
                });
            }
        }
    }
    return items;
}
// ─── Helpers ──────────────────────────────────────────────────────────────────
function formatDetail(entry) {
    const parts = [entry.type];
    if (entry.category) {
        parts.push(`(${entry.category})`);
    }
    return parts.join(' ');
}
function formatDocumentation(entry) {
    const lines = [];
    if (entry.description) {
        lines.push(entry.description);
    }
    if (entry.path) {
        lines.push(`Path: ${entry.path}`);
    }
    if (entry.dependencies && entry.dependencies.length > 0) {
        lines.push(`Dependencies: ${entry.dependencies.length}`);
    }
    if (entry.dependents && entry.dependents.length > 0) {
        lines.push(`Dependents: ${entry.dependents.length}`);
    }
    return lines.join('\n');
}
function getFileExtension(uri) {
    const dotIndex = uri.lastIndexOf('.');
    if (dotIndex === -1)
        return '';
    return uri.slice(dotIndex);
}
function getLineText(document, line) {
    const start = { line, character: 0 };
    const end = { line, character: Number.MAX_SAFE_INTEGER };
    return document.getText({ start, end });
}
function getAllLines(document, currentLine) {
    const lines = [];
    const startLine = Math.max(0, currentLine - 5);
    const endLine = Math.min(document.lineCount - 1, currentLine + 5);
    for (let i = startLine; i <= endLine; i++) {
        const start = { line: i, character: 0 };
        const end = { line: i, character: Number.MAX_SAFE_INTEGER };
        lines.push(document.getText({ start, end }));
    }
    return lines;
}
//# sourceMappingURL=completion.js.map