"use strict";
// src/orchestrator/graph/DependencyExtractor.ts
// v1.14.0 — Extract import/export edges. Relative paths are resolved
// to absolute file paths; bare specifiers stay unresolved.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractDependencies = extractDependencies;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const TreeSitterRegistry_1 = require("./TreeSitterRegistry");
const RESOLVE_EXTS = ['', '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.py', '/index.ts', '/index.js'];
function stripQuotes(s) {
    return s.replace(/^['"`]|['"`]$/g, '');
}
function resolveModule(fromFile, spec) {
    if (!spec.startsWith('.') && !spec.startsWith('/'))
        return undefined;
    const fromDir = path.dirname(fromFile);
    const base = path.resolve(fromDir, spec);
    for (const ext of RESOLVE_EXTS) {
        const candidate = base + ext;
        try {
            if (fs.existsSync(candidate) && fs.statSync(candidate).isFile())
                return candidate;
        }
        catch { /* ignore */ }
    }
    return undefined;
}
function tsExtractEdges(file, root, lang) {
    const out = [];
    for (const top of root.children) {
        if (top.type === 'import_statement') {
            const str = top.children.find(c => c.type === 'string');
            if (!str)
                continue;
            const spec = stripQuotes(str.text);
            out.push({ from: file, toModule: spec, resolvedFile: resolveModule(file, spec), kind: 'import', language: lang });
        }
        else if (top.type === 'export_statement') {
            const str = top.children.find(c => c.type === 'string');
            if (str) {
                const spec = stripQuotes(str.text);
                out.push({ from: file, toModule: spec, resolvedFile: resolveModule(file, spec), kind: 'reexport', language: lang });
            }
        }
    }
    // require('x') — scan call expressions one level deep.
    function visit(node) {
        if (node.type === 'call_expression') {
            const callee = node.children[0];
            if (callee && callee.text === 'require' && node.children.length >= 2) {
                const args = node.children[1];
                if (args && args.children) {
                    const str = args.children.find(c => c.type === 'string');
                    if (str) {
                        const spec = stripQuotes(str.text);
                        out.push({ from: file, toModule: spec, resolvedFile: resolveModule(file, spec), kind: 'require', language: lang });
                    }
                }
            }
        }
        for (const c of node.children)
            visit(c);
    }
    visit(root);
    return out;
}
function pyExtractEdges(file, root, lang) {
    const out = [];
    for (const top of root.children) {
        if (top.type === 'import_statement' || top.type === 'import_from_statement') {
            // crude: collect dotted_name nodes
            function collectNames(n) {
                if (n.type === 'dotted_name')
                    return [n.text];
                const acc = [];
                for (const c of n.children)
                    acc.push(...collectNames(c));
                return acc;
            }
            const names = collectNames(top);
            for (const spec of names) {
                out.push({ from: file, toModule: spec, kind: 'import', language: lang });
            }
        }
    }
    return out;
}
function extractDependencies(filePath, source) {
    const parsed = (0, TreeSitterRegistry_1.parseFile)(filePath, source);
    if (!parsed)
        return [];
    const root = parsed.rootNode;
    if (parsed.language === 'py')
        return pyExtractEdges(filePath, root, parsed.language);
    return tsExtractEdges(filePath, root, parsed.language);
}
