"use client";
import { useMemo } from "react";
import { parse as parseYaml } from "yaml";
import { categorizeKind } from "./kind-metadata.js";
const NODE_WIDTH = 180;
const NODE_HEIGHT = 40;
/**
 * Behavior hook that computes a DAG topology from workflow YAML.
 *
 * Parses the YAML into tasks and builds a node + edge graph suitable
 * for rendering. Handles sequential flow, explicit `flow.then` directives,
 * and `switch_case` branching edges.
 *
 * Returns stable refs (DD-010) — the result is memoized and only
 * recomputed when the YAML content changes.
 *
 * @param yaml - The current workflow YAML string (or `null`/empty to skip).
 *
 * @since T10 (YAML Editor with Graph Preview)
 */
export function useWorkflowTopology(yaml) {
    return useMemo(() => {
        if (!yaml?.trim())
            return EMPTY_TOPOLOGY;
        try {
            return computeTopology(yaml);
        }
        catch {
            return EMPTY_TOPOLOGY;
        }
    }, [yaml]);
}
const EMPTY_TOPOLOGY = { nodes: [], edges: [] };
function computeTopology(yaml) {
    let parsed;
    try {
        parsed = parseYaml(yaml);
    }
    catch {
        return EMPTY_TOPOLOGY;
    }
    if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
        return EMPTY_TOPOLOGY;
    }
    const doc = parsed;
    const spec = doc.spec;
    if (!spec)
        return EMPTY_TOPOLOGY;
    const rawTasks = spec.tasks;
    if (!Array.isArray(rawTasks) || rawTasks.length === 0)
        return EMPTY_TOPOLOGY;
    const tasks = rawTasks.filter((t) => t != null && typeof t === "object" && typeof t.name === "string");
    if (tasks.length === 0)
        return EMPTY_TOPOLOGY;
    const nodes = [];
    const edges = [];
    const taskNameSet = new Set(tasks.map((t) => t.name));
    const startNode = {
        id: "__start__",
        label: "Start",
        kind: "start",
        category: "start",
        x: 0, y: 0,
        width: NODE_WIDTH, height: NODE_HEIGHT,
    };
    nodes.push(startNode);
    for (const task of tasks) {
        nodes.push({
            id: task.name,
            label: task.name,
            kind: task.kind || "unspecified",
            category: categorizeKind(task.kind),
            x: 0, y: 0,
            width: NODE_WIDTH, height: NODE_HEIGHT,
        });
    }
    // Edge: start → first task
    edges.push({ source: "__start__", target: tasks[0].name });
    const tasksWithEndFlow = new Set();
    for (let i = 0; i < tasks.length; i++) {
        const task = tasks[i];
        const thenTarget = task.flow?.then;
        if (thenTarget === "end") {
            tasksWithEndFlow.add(task.name);
            continue;
        }
        if (thenTarget && taskNameSet.has(thenTarget)) {
            edges.push({ source: task.name, target: thenTarget });
            continue;
        }
        // switch_case: add edges for each case
        const config = task.task_config ?? task.taskConfig;
        if (task.kind === "switch_case" && config) {
            const cases = config.cases;
            if (Array.isArray(cases)) {
                let hasDefault = false;
                for (const c of cases) {
                    if (c && typeof c === "object") {
                        const caseObj = c;
                        const caseThen = caseObj.then;
                        if (caseThen && taskNameSet.has(caseThen)) {
                            edges.push({
                                source: task.name,
                                target: caseThen,
                                label: caseObj.name || undefined,
                            });
                            if (!caseObj.when)
                                hasDefault = true;
                        }
                    }
                }
                if (!hasDefault && i < tasks.length - 1) {
                    edges.push({ source: task.name, target: tasks[i + 1].name });
                }
                continue;
            }
        }
        // Default: sequential to next task
        if (i < tasks.length - 1) {
            edges.push({ source: task.name, target: tasks[i + 1].name });
        }
        else {
            tasksWithEndFlow.add(task.name);
        }
    }
    // Add end node if any tasks flow to "end" or the last task has no explicit successor
    if (tasksWithEndFlow.size > 0) {
        const endNode = {
            id: "__end__",
            label: "End",
            kind: "end",
            category: "end",
            x: 0, y: 0,
            width: NODE_WIDTH, height: NODE_HEIGHT,
        };
        nodes.push(endNode);
        for (const name of tasksWithEndFlow) {
            edges.push({ source: name, target: "__end__" });
        }
    }
    return { nodes, edges };
}
//# sourceMappingURL=useWorkflowTopology.js.map