import { parse } from "@babel/parser";
/**
 * Maps local binding names (default or named imports) to resolved entry paths
 * and original export names.
 * Supports `import X from './p'`, `import { A, B } from './p'`,
 * `import { A as B } from './p'`, and `import X, { A } from './p'`.
 * Skips type-only imports.
 */
async function buildImportBindingToPathMap(ast, resolveImportPath) {
    const importMap = new Map();
    for (const node of ast.program.body) {
        if (node.type !== "ImportDeclaration")
            continue;
        const decl = node;
        if (decl.importKind === "type" || decl.importKind === "typeof") {
            continue;
        }
        const source = decl.source?.value;
        if (typeof source !== "string")
            continue;
        const resolved = await resolveImportPath(source);
        if (!resolved)
            continue;
        for (const spec of decl.specifiers) {
            if (spec.type === "ImportDefaultSpecifier") {
                const name = spec.local?.name;
                if (typeof name === "string") {
                    importMap.set(name, { path: resolved });
                }
                continue;
            }
            if (spec.type === "ImportSpecifier") {
                if (spec.importKind === "type")
                    continue;
                const localName = spec.local?.name;
                const importedName = spec.imported?.name;
                if (typeof localName === "string") {
                    importMap.set(localName, {
                        path: resolved,
                        originalExportName: importedName ?? localName,
                    });
                }
            }
        }
    }
    return importMap;
}
export async function parseSdkRegistryFromContent(registryContent, resolveImportPath) {
    const entries = await parseSdkRegistryEntries(registryContent, resolveImportPath);
    const result = new Map();
    for (const [key, entry] of entries) {
        result.set(key, entry.entryPoint);
    }
    return result;
}
/**
 * Parse the SDK registry and return rich entry metadata including export names.
 * For named imports, `exportName` is the original export name in the source file
 * (handles aliased imports like `import { GetAllUsers as ListUsers }`).
 */
export async function parseSdkRegistryEntries(registryContent, resolveImportPath) {
    const result = new Map();
    if (registryContent.trim() === "") {
        return result;
    }
    let ast;
    try {
        ast = parse(registryContent, {
            sourceType: "module",
            plugins: ["typescript"],
        });
    }
    catch {
        return result;
    }
    const importMap = await buildImportBindingToPathMap(ast, resolveImportPath);
    const exportedObject = findExportedObject(ast);
    if (!exportedObject) {
        return result;
    }
    for (const prop of exportedObject.properties) {
        if (prop.type !== "ObjectProperty")
            continue;
        const key = getPropertyKey(prop);
        if (!key)
            continue;
        const value = prop.value;
        let entry;
        if (value.type === "Identifier") {
            const binding = importMap.get(value.name ?? "");
            if (binding) {
                entry = {
                    entryPoint: binding.path,
                    exportName: binding.originalExportName,
                };
            }
        }
        else if (value.type === "CallExpression") {
            const resolvedPath = await resolveImportPathFromCall(value, resolveImportPath);
            if (resolvedPath) {
                entry = { entryPoint: resolvedPath };
            }
        }
        else if (value.type === "ArrowFunctionExpression") {
            const body = value.body;
            if (body?.type === "CallExpression") {
                const resolvedPath = await resolveImportPathFromCall(body, resolveImportPath);
                if (resolvedPath) {
                    entry = { entryPoint: resolvedPath };
                }
            }
        }
        if (entry) {
            result.set(key, entry);
        }
    }
    return result;
}
async function resolveImportPathFromCall(call, resolveImportPath) {
    if (call.callee.type !== "Import") {
        return undefined;
    }
    const arg = call.arguments[0];
    if (arg?.type !== "StringLiteral" || typeof arg.value !== "string") {
        return undefined;
    }
    return resolveImportPath(arg.value);
}
function getPropertyKey(prop) {
    if (prop.key.type === "Identifier")
        return prop.key.name;
    if (prop.key.type === "StringLiteral")
        return prop.key.value;
    return undefined;
}
function findExportedObject(ast) {
    for (const node of ast.program.body) {
        if (node.type !== "ExportDefaultDeclaration")
            continue;
        const declaration = node.declaration;
        const objectExpression = getObjectExpression(declaration);
        if (objectExpression) {
            return objectExpression;
        }
        if (declaration.type !== "Identifier" || !declaration.name)
            continue;
        const variableDeclaration = findVariableDeclaration(ast, declaration.name);
        if (variableDeclaration?.init) {
            return variableDeclaration.init;
        }
    }
    return undefined;
}
function getObjectExpression(node) {
    if (node.type === "ObjectExpression") {
        return node;
    }
    if ((node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression") &&
        "expression" in node) {
        const expression = node.expression;
        if (expression?.type === "ObjectExpression") {
            return expression;
        }
    }
    return undefined;
}
function findVariableDeclaration(ast, name) {
    for (const node of ast.program.body) {
        if (node.type !== "VariableDeclaration")
            continue;
        for (const declarator of node.declarations) {
            if (declarator.id.type === "Identifier" &&
                declarator.id.name === name &&
                declarator.init) {
                const objectExpression = getObjectExpression(declarator.init);
                if (objectExpression) {
                    return { init: objectExpression };
                }
            }
        }
    }
    return undefined;
}
//# sourceMappingURL=sdk-registry.js.map