import { randomUUID } from "node:crypto";
import { getSession } from "../lib/neo4j.js";
import { embed } from "../lib/embeddings.js";
import { validateCapabilities } from "../lib/validate-capabilities.js";
import { resolveOrder } from "../lib/step-resolver.js";
export async function workflowCreate(params) {
    const { accountId, name, description, steps } = params;
    const workflowId = randomUUID();
    const now = new Date().toISOString();
    // Assign stepIds and positions
    const stepDefs = steps.map((s, i) => {
        const base = {
            stepId: randomUUID(),
            dependsOn: s.dependsOn,
            onFailure: s.onFailure ?? "abort",
            retryLimit: s.retryLimit,
            outputKey: s.outputKey,
            timeout: s.timeout,
            position: i,
            label: s.label,
        };
        if (s.type === "llm") {
            return {
                ...base,
                type: "llm",
                prompt: s.prompt,
                model: s.model,
                maxTokens: s.maxTokens,
                fallbackMode: s.fallbackMode,
                fallbackTemplate: s.fallbackTemplate,
            };
        }
        return { ...base, type: "tool", plugin: s.plugin, tool: s.tool, params: s.params };
    });
    // Map user-provided dependsOn labels/positions to stepIds
    // dependsOn references come in as stepIds from prior steps in the array.
    // Since we just generated stepIds, the agent must reference steps by their
    // position index. We resolve numeric string refs to actual stepIds.
    for (const step of stepDefs) {
        if (!step.dependsOn)
            continue;
        step.dependsOn = step.dependsOn.map((ref) => {
            // If it's already a UUID (36 chars with dashes), pass through
            if (ref.length === 36 && ref.includes("-"))
                return ref;
            // If it's a numeric index, resolve to the stepId at that position
            const idx = parseInt(ref, 10);
            if (!isNaN(idx) && idx >= 0 && idx < stepDefs.length) {
                return stepDefs[idx].stepId;
            }
            return ref;
        });
    }
    // Validate dependency graph (detect cycles, unknown refs)
    resolveOrder(stepDefs);
    // Validate capabilities
    const platformRoot = process.env.PLATFORM_ROOT;
    let status = "active";
    const validationErrors = [];
    if (platformRoot) {
        const validation = validateCapabilities(stepDefs, platformRoot);
        if (!validation.valid) {
            status = "draft";
            for (const err of validation.errors) {
                validationErrors.push(`Step "${err.label}": ${err.reason}`);
            }
        }
    }
    // Compute embedding for discovery
    const embeddingText = `${name} ${description}`;
    const embedding = await embed(embeddingText);
    const session = getSession();
    try {
        // Create Workflow node
        await session.run(`CREATE (w:Workflow $props)`, {
            props: {
                workflowId,
                accountId,
                name,
                description,
                status,
                embedding,
                createdAt: now,
                updatedAt: now,
            },
        });
        // Create WorkflowStep nodes with HAS_STEP relationships
        for (const step of stepDefs) {
            const baseProps = {
                stepId: step.stepId,
                workflowId,
                accountId,
                type: step.type,
                dependsOn: step.dependsOn && step.dependsOn.length > 0
                    ? JSON.stringify(step.dependsOn)
                    : null,
                onFailure: step.onFailure ?? "abort",
                retryLimit: step.retryLimit ?? null,
                outputKey: step.outputKey ?? null,
                timeout: step.timeout ?? null,
                position: step.position,
                label: step.label,
            };
            const typeProps = step.type === "llm"
                ? {
                    prompt: step.prompt,
                    model: step.model ?? null,
                    maxTokens: step.maxTokens ?? null,
                    fallbackMode: step.fallbackMode ?? null,
                    fallbackTemplate: step.fallbackTemplate ?? null,
                    // LLM steps don't have plugin/tool/params
                    plugin: null,
                    tool: null,
                    params: null,
                }
                : {
                    plugin: step.plugin,
                    tool: step.tool,
                    params: step.params ? JSON.stringify(step.params) : null,
                    // Tool steps don't have prompt/model/maxTokens/fallback*
                    prompt: null,
                    model: null,
                    maxTokens: null,
                    fallbackMode: null,
                    fallbackTemplate: null,
                };
            await session.run(`MATCH (w:Workflow {workflowId: $workflowId})
         CREATE (w)-[:HAS_STEP]->(s:WorkflowStep $props)`, { workflowId, props: { ...baseProps, ...typeProps } });
        }
    }
    finally {
        await session.close();
    }
    return { workflowId, status, validationErrors };
}
//# sourceMappingURL=workflow-create.js.map