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";
import { writeNodeWithEdges, } from "../../../../../lib/graph-write/dist/index.js";
export async function workflowCreate(params) {
    const { accountId, name, description, steps, sessionKey, createdBy } = params;
    const workflowId = randomUUID();
    const now = new Date().toISOString();
    // Assign stepIds and positions
    const stepDefs = steps.map((s, i) => ({
        stepId: randomUUID(),
        dependsOn: s.dependsOn,
        onFailure: s.onFailure ?? "abort",
        retryLimit: s.retryLimit,
        outputKey: s.outputKey,
        timeout: s.timeout,
        position: i,
        label: s.label,
        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. 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;
            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 {
        // Write doctrine: the Workflow must be created with at least one
        // adjacency in the same transaction. Pre-resolve the admin session's
        // Conversation elementId — that is the Workflow's semantic parent
        // (PART_OF). If no Conversation resolves, the caller is invoking
        // workflow-create outside an admin session; reject loudly per doctrine.
        const relationships = [];
        if (sessionKey) {
            const r = await session.run(`MATCH (c:Conversation {sessionKey: $sessionKey}) RETURN elementId(c) AS id LIMIT 1`, { sessionKey });
            if (r.records.length > 0) {
                relationships.push({
                    type: "PART_OF",
                    direction: "outgoing",
                    targetNodeId: r.records[0].get("id"),
                });
            }
        }
        if (relationships.length === 0) {
            throw new Error("Write doctrine violated: workflow-create requires an admin session with an existing Conversation to link the Workflow (PART_OF). Invoke from inside a session.");
        }
        await writeNodeWithEdges({
            session,
            labels: ["Workflow"],
            props: {
                workflowId,
                accountId,
                name,
                description,
                status,
                embedding,
                createdAt: now,
                updatedAt: now,
            },
            relationships,
            createdBy,
        });
        // Create WorkflowStep nodes with HAS_STEP relationships
        for (const step of stepDefs) {
            await session.run(`MATCH (w:Workflow {workflowId: $workflowId})
         CREATE (w)-[:HAS_STEP]->(s:WorkflowStep $props)`, {
                workflowId,
                props: {
                    stepId: step.stepId,
                    workflowId,
                    accountId,
                    type: step.type,
                    plugin: step.plugin,
                    tool: step.tool,
                    params: step.params ? JSON.stringify(step.params) : null,
                    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,
                },
            });
        }
    }
    finally {
        await session.close();
    }
    return { workflowId, status, validationErrors };
}
//# sourceMappingURL=workflow-create.js.map