"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SDK_FUNCTIONS = void 0;
exports.emitInstanceAi = emitInstanceAi;
exports.buildImports = buildImports;
exports.hoistSharedCredentials = hoistSharedCredentials;
exports.uniqueConstName = uniqueConstName;
const code_generator_1 = require("./code-generator");
const composite_builder_1 = require("./composite-builder");
const graph_annotator_1 = require("./graph-annotator");
const semantic_graph_1 = require("./semantic-graph");
function generateWorkflowCode(workflow) {
    const graph = (0, semantic_graph_1.buildSemanticGraph)(workflow);
    (0, graph_annotator_1.annotateGraph)(graph);
    const tree = (0, composite_builder_1.buildCompositeTree)(graph);
    return (0, code_generator_1.generateCode)(tree, workflow, graph, {});
}
exports.SDK_FUNCTIONS = [
    'workflow',
    'trigger',
    'node',
    'sticky',
    'placeholder',
    'merge',
    'ifElse',
    'switchCase',
    'newCredential',
    'languageModel',
    'memory',
    'tool',
    'outputParser',
    'embedding',
    'embeddings',
    'vectorStore',
    'retriever',
    'documentLoader',
    'textSplitter',
    'fromAi',
    'splitInBatches',
    'nextBatch',
    'expr',
];
function emitInstanceAi(workflow, opts = {}) {
    const body = generateWorkflowCode(workflow);
    const dedupedBody = hoistSharedCredentials(body);
    const importLine = buildImports(dedupedBody);
    const sections = [];
    if (opts.jsdocHeader)
        sections.push(opts.jsdocHeader.trim());
    if (importLine)
        sections.push(importLine);
    sections.push(dedupedBody);
    return sections.join('\n\n') + '\n';
}
function buildImports(body) {
    const used = [];
    for (const fn of exports.SDK_FUNCTIONS) {
        if (containsCall(body, fn))
            used.push(fn);
    }
    if (used.length === 0)
        return '';
    return `import { ${used.join(', ')} } from '@n8n/workflow-sdk';`;
}
function containsCall(body, fnName) {
    const pattern = new RegExp(`\\b${fnName}\\(`);
    return pattern.test(body);
}
function hoistSharedCredentials(body) {
    const callPattern = /newCredential\('([^'\\]*)',\s*'([^'\\]*)'\)/g;
    const groups = new Map();
    let m;
    while ((m = callPattern.exec(body)) !== null) {
        const [match, name, id] = m;
        const key = `${name}::${id}`;
        const existing = groups.get(key);
        if (existing) {
            existing.count++;
        }
        else {
            groups.set(key, { match, name, id, count: 1 });
        }
    }
    const usedNames = collectExistingIdentifiers(body);
    const hoists = [];
    let result = body;
    const dedupable = Array.from(groups.values())
        .filter((g) => g.count >= 2)
        .sort((a, b) => body.indexOf(a.match) - body.indexOf(b.match));
    for (const group of dedupable) {
        const constName = uniqueConstName(group.name, usedNames);
        hoists.push(`const ${constName} = ${group.match};`);
        result = splitJoin(result, group.match, constName);
    }
    if (hoists.length === 0)
        return body;
    return `${hoists.join('\n')}\n\n${result}`;
}
function splitJoin(haystack, needle, replacement) {
    return haystack.split(needle).join(replacement);
}
function uniqueConstName(credName, used) {
    const sanitised = credName
        .replace(/[^a-zA-Z0-9]+/g, ' ')
        .trim()
        .split(/\s+/)
        .filter(Boolean);
    let camel;
    if (sanitised.length === 0) {
        camel = 'shared';
    }
    else {
        camel =
            sanitised[0].charAt(0).toLowerCase() +
                sanitised[0].slice(1) +
                sanitised
                    .slice(1)
                    .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
                    .join('');
    }
    const base = `${camel}Cred`;
    let candidate = base;
    let i = 1;
    while (used.has(candidate)) {
        i++;
        candidate = `${base}${i}`;
    }
    used.add(candidate);
    return candidate;
}
function collectExistingIdentifiers(body) {
    const ids = new Set();
    const pattern = /\b([a-zA-Z_][a-zA-Z0-9_]*)\b/g;
    let m;
    while ((m = pattern.exec(body)) !== null)
        ids.add(m[1]);
    return ids;
}
//# sourceMappingURL=emit-instance-ai.js.map