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 workflowUpdate(params) {
    const { workflowId, accountId, name, description, steps, status } = params;
    const session = getSession();
    try {
        const existing = await session.run(`MATCH (w:Workflow {workflowId: $workflowId, accountId: $accountId})
       RETURN w`, { workflowId, accountId });
        if (existing.records.length === 0) {
            throw new Error(`Workflow not found: ${workflowId}`);
        }
        const now = new Date().toISOString();
        // If steps are provided, replace all step nodes
        if (steps) {
            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,
            }));
            // Resolve numeric dependsOn refs to stepIds
            for (const step of stepDefs) {
                if (!step.dependsOn)
                    continue;
                step.dependsOn = step.dependsOn.map((ref) => {
                    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;
                });
            }
            resolveOrder(stepDefs);
            // Replace old steps. Hard-delete is deliberate: step replacement during
            // workflow edit is not a user-facing delete — old definitions are
            // semantically overwritten by the new ones, so there is no restore
            // expectation. The corresponding user-facing action (workflow-delete)
            // does soft-delete via trashNode.
            await session.run(`MATCH (w:Workflow {workflowId: $workflowId, accountId: $accountId})-[:HAS_STEP]->(s:WorkflowStep)
         DETACH DELETE s`, { workflowId, accountId });
            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,
                    },
                });
            }
            // Re-validate capabilities and set status accordingly
            const platformRoot = process.env.PLATFORM_ROOT;
            if (platformRoot) {
                const validation = validateCapabilities(stepDefs, platformRoot);
                const validatedStatus = validation.valid ? (status ?? "active") : "draft";
                await session.run(`MATCH (w:Workflow {workflowId: $workflowId, accountId: $accountId})
           SET w.status = $status, w.updatedAt = $now`, { workflowId, accountId, status: validatedStatus, now });
            }
        }
        // Build SET clauses for non-step fields
        const setClauses = ["w.updatedAt = $updatedAt"];
        const queryParams = {
            workflowId,
            accountId,
            updatedAt: now,
        };
        if (name !== undefined) {
            setClauses.push("w.name = $name");
            queryParams.name = name;
        }
        if (description !== undefined) {
            setClauses.push("w.description = $description");
            queryParams.description = description;
        }
        if (status !== undefined && !steps) {
            // Setting status without new steps — if activating, re-validate
            // existing steps to prevent bypassing capability checks on draft workflows
            if (status === "active") {
                const platformRoot = process.env.PLATFORM_ROOT;
                if (platformRoot) {
                    const stepsResult = await session.run(`MATCH (w:Workflow {workflowId: $workflowId, accountId: $accountId})-[:HAS_STEP]->(s:WorkflowStep)
             RETURN s`, { workflowId, accountId });
                    if (stepsResult.records.length > 0) {
                        const existingSteps = stepsResult.records.map((r) => {
                            const s = r.get("s").properties;
                            return {
                                stepId: s.stepId,
                                position: s.position ?? 0,
                                label: s.label,
                                type: "tool",
                                plugin: s.plugin,
                                tool: s.tool,
                            };
                        });
                        const validation = validateCapabilities(existingSteps, platformRoot);
                        if (!validation.valid) {
                            throw new Error(`Cannot activate workflow — missing capabilities: ${validation.errors.map((e) => e.reason).join("; ")}`);
                        }
                    }
                }
            }
            setClauses.push("w.status = $status");
            queryParams.status = status;
        }
        // Re-embed if name or description changed
        if (name !== undefined || description !== undefined) {
            const current = existing.records[0].get("w").properties;
            const embName = name ?? current.name;
            const embDesc = description ?? current.description;
            const embedding = await embed(`${embName} ${embDesc}`);
            setClauses.push("w.embedding = $embedding");
            queryParams.embedding = embedding;
        }
        if (setClauses.length > 1 || name !== undefined || description !== undefined) {
            await session.run(`MATCH (w:Workflow {workflowId: $workflowId, accountId: $accountId})
         SET ${setClauses.join(", ")}`, queryParams);
        }
    }
    finally {
        await session.close();
    }
}
//# sourceMappingURL=workflow-update.js.map