"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.findCallSites = findCallSites;
const typescript_1 = __importDefault(require("typescript"));
const utils_js_1 = require("./utils.js");
// ---------------------------------------------------------------------------
// Discovery
// ---------------------------------------------------------------------------
/**
 * Find all step function declarations in a source file.
 *
 * Detects two patterns:
 * 1. `Steps.createFunction(fn)` — call expression
 * 2. `@stepFunction` — method decorator
 */
function findCallSites(context, intrinsics, file) {
    const callSites = [];
    const visit = (node) => {
        // Pattern 1: Steps.createFunction(fn)
        if (typescript_1.default.isCallExpression(node) &&
            context.checker.getSymbolAtLocation(node.expression) === intrinsics.createFunction) {
            const factory = extractFactoryFromCreateFunction(context, node);
            if (factory) {
                callSites.push({
                    file,
                    origin: { kind: 'createFunction', call: node },
                    factoryFunction: factory,
                });
            }
            // Don't descend into the factory function body here — it will be
            // analyzed by the call graph builder.
            return;
        }
        // Pattern 2: @stepFunction decorator on a method
        if (typescript_1.default.isMethodDeclaration(node) && node.modifiers) {
            for (const mod of node.modifiers) {
                if (!typescript_1.default.isDecorator(mod))
                    continue;
                const expr = mod.expression;
                const symbol = typescript_1.default.isIdentifier(expr)
                    ? context.checker.getSymbolAtLocation(expr)
                    : typescript_1.default.isCallExpression(expr) && typescript_1.default.isIdentifier(expr.expression)
                        ? context.checker.getSymbolAtLocation(expr.expression)
                        : undefined;
                if (symbol && symbol.getName() === 'stepFunction') {
                    const factory = {
                        factory: node,
                    };
                    callSites.push({
                        file,
                        origin: { kind: 'decorator', decorator: mod, method: node },
                        factoryFunction: factory,
                    });
                    break;
                }
            }
        }
        typescript_1.default.forEachChild(node, visit);
    };
    typescript_1.default.forEachChild(file, visit);
    return callSites;
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function extractFactoryFromCreateFunction(context, callExpr) {
    const arg = callExpr.arguments[0];
    if (!arg)
        return null;
    let factory = null;
    if ((0, utils_js_1.isFunctionLikeDeclarationBase)(arg)) {
        factory = arg;
    }
    else if (typescript_1.default.isIdentifier(arg)) {
        factory = (0, utils_js_1.getFunctionDeclarationFromNode)(context.checker, arg);
    }
    if (!factory)
        return null;
    // Extract type parameters from the generic: Steps.createFunction<TInput, TOutput>(fn)
    const typeArgs = callExpr.typeArguments;
    return {
        inputType: typeArgs?.[0],
        contextType: undefined,
        factory,
    };
}
//# sourceMappingURL=callSiteLocator.js.map