"use strict";
// src/orchestrator/graph/SymbolExtractor.ts
// v1.14.0 — Extract top-level symbols from tree-sitter ASTs.
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractSymbols = extractSymbols;
const TreeSitterRegistry_1 = require("./TreeSitterRegistry");
const TS_SYMBOL_KIND_MAP = {
    function_declaration: 'function',
    generator_function_declaration: 'function',
    class_declaration: 'class',
    abstract_class_declaration: 'class',
    interface_declaration: 'interface',
    type_alias_declaration: 'type',
    enum_declaration: 'enum',
};
function nameFromNode(node) {
    if (node.childForFieldName) {
        const named = node.childForFieldName('name');
        if (named)
            return named.text;
    }
    for (const c of node.children) {
        if (c.type === 'identifier' || c.type === 'type_identifier')
            return c.text;
    }
    return null;
}
function tsExtract(file, root, lang) {
    const out = [];
    const handleDecl = (node, exported) => {
        const kind = TS_SYMBOL_KIND_MAP[node.type];
        if (kind) {
            const name = nameFromNode(node);
            if (name) {
                out.push({
                    name, kind, file,
                    startLine: node.startPosition.row + 1,
                    endLine: node.endPosition.row + 1,
                    exported, language: lang,
                });
            }
            return;
        }
        if (node.type === 'lexical_declaration' || node.type === 'variable_declaration') {
            // export const FOO = ...; const FOO = ...
            for (const c of node.children) {
                if (c.type === 'variable_declarator') {
                    const name = nameFromNode(c);
                    if (name) {
                        out.push({
                            name, kind: 'const', file,
                            startLine: node.startPosition.row + 1,
                            endLine: node.endPosition.row + 1,
                            exported, language: lang,
                        });
                    }
                }
            }
        }
    };
    for (const top of root.children) {
        if (top.type === 'export_statement') {
            for (const inner of top.children) {
                if (inner.type === 'export' || inner.type === 'default')
                    continue;
                handleDecl(inner, true);
            }
        }
        else {
            handleDecl(top, false);
        }
    }
    // Methods inside classes (one-level deep — good enough for v1.14).
    for (const cls of out.filter(s => s.kind === 'class')) {
        const node = findNodeAtLine(root, cls.startLine - 1);
        if (!node)
            continue;
        const body = node.children.find(c => c.type === 'class_body');
        if (!body)
            continue;
        for (const m of body.children) {
            if (m.type === 'method_definition' || m.type === 'method_signature' || m.type === 'public_field_definition') {
                const name = nameFromNode(m);
                if (name) {
                    out.push({
                        name: `${cls.name}.${name}`, kind: 'method', file,
                        startLine: m.startPosition.row + 1,
                        endLine: m.endPosition.row + 1,
                        exported: cls.exported, language: lang,
                    });
                }
            }
        }
    }
    return out;
}
function findNodeAtLine(root, row) {
    for (const c of root.children) {
        if (c.startPosition.row === row) {
            // unwrap export_statement
            if (c.type === 'export_statement' && c.children.length > 0) {
                const inner = c.children.find(x => x.type !== 'export' && x.type !== 'default');
                return inner || c;
            }
            return c;
        }
    }
    return null;
}
function pyExtract(file, root, lang) {
    const out = [];
    for (const top of root.children) {
        if (top.type === 'function_definition') {
            const name = nameFromNode(top);
            if (name)
                out.push({ name, kind: 'function', file, startLine: top.startPosition.row + 1, endLine: top.endPosition.row + 1, exported: !name.startsWith('_'), language: lang });
        }
        else if (top.type === 'class_definition') {
            const name = nameFromNode(top);
            if (name)
                out.push({ name, kind: 'class', file, startLine: top.startPosition.row + 1, endLine: top.endPosition.row + 1, exported: !name.startsWith('_'), language: lang });
            const body = top.children.find(c => c.type === 'block');
            if (body && name) {
                for (const m of body.children) {
                    if (m.type === 'function_definition') {
                        const methodName = nameFromNode(m);
                        if (methodName) {
                            out.push({
                                name: `${name}.${methodName}`, kind: 'method', file,
                                startLine: m.startPosition.row + 1,
                                endLine: m.endPosition.row + 1,
                                exported: !methodName.startsWith('_'),
                                language: lang,
                            });
                        }
                    }
                }
            }
        }
    }
    return out;
}
function extractSymbols(filePath, source) {
    const parsed = (0, TreeSitterRegistry_1.parseFile)(filePath, source);
    if (!parsed)
        return [];
    const root = parsed.rootNode;
    if (parsed.language === 'py')
        return pyExtract(filePath, root, parsed.language);
    return tsExtract(filePath, root, parsed.language);
}
