import { WorkflowTaskKind } from "@stigmer/protos/ai/stigmer/agentic/workflow/v1/enum_pb";
import { START_NODE_ID, END_NODE_ID } from "../workflow-graph-model";
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Computes port assignments for all nodes in a workflow graph.
 *
 * Port IDs are deterministic and align with the React Flow handle IDs
 * used in `WorkflowNode` (`case_{name}`, `outcome_{name}`). This ensures
 * ELK routes edges to the correct port and the postprocessor can map
 * results back to the React Flow model without translation.
 *
 * @param nodes - All nodes in the workflow graph.
 * @param edges - All edges (used to infer fork branch count).
 */
export function computePortAssignments(nodes, edges) {
    const result = new Map();
    for (const node of nodes) {
        result.set(node.id, computeNodePorts(node, edges));
    }
    return result;
}
/**
 * Computes port assignment for a single node.
 * Exported for unit testing individual cases.
 */
export function computeNodePorts(node, edges) {
    const nodeId = node.id;
    if (nodeId === START_NODE_ID) {
        return {
            nodeId,
            inputPorts: [],
            outputPorts: [makePort(`${nodeId}__out`, "SOUTH", 0)],
        };
    }
    if (nodeId === END_NODE_ID) {
        return {
            nodeId,
            inputPorts: [makePort(`${nodeId}__in`, "NORTH", 0)],
            outputPorts: [],
        };
    }
    const inputPorts = [makePort(`${nodeId}__in`, "NORTH", 0)];
    const outputPorts = computeOutputPorts(node, edges);
    return { nodeId, inputPorts, outputPorts };
}
// ---------------------------------------------------------------------------
// Output port computation per task kind
// ---------------------------------------------------------------------------
function computeOutputPorts(node, edges) {
    const config = node.config;
    if (node.kind === WorkflowTaskKind.switch_case && config) {
        return computeSwitchCasePorts(node.id, config);
    }
    if (node.kind === WorkflowTaskKind.human_input && config) {
        return computeHumanInputPorts(node.id, config);
    }
    if (node.kind === WorkflowTaskKind.fork) {
        return computeForkPorts(node.id, edges);
    }
    return [makePort(`${node.id}__out`, "SOUTH", 0)];
}
/**
 * switch_case: one output port per case entry.
 * Handle ID format matches CanvasTaskNode: `case_{caseName}`.
 */
function computeSwitchCasePorts(nodeId, config) {
    const cases = config.cases;
    if (!Array.isArray(cases) || cases.length === 0) {
        return [makePort(`${nodeId}__out`, "SOUTH", 0)];
    }
    const ports = [];
    let index = 0;
    for (const c of cases) {
        if (c != null && typeof c === "object" && typeof c.name === "string") {
            const caseName = c.name;
            ports.push(makePort(`${nodeId}__case_${caseName}`, "SOUTH", index, caseName));
            index++;
        }
    }
    return ports.length > 0 ? ports : [makePort(`${nodeId}__out`, "SOUTH", 0)];
}
/**
 * human_input: one output port per outcome entry.
 * Handle ID format matches CanvasTaskNode: `outcome_{outcomeName}`.
 */
function computeHumanInputPorts(nodeId, config) {
    const outcomes = config.outcomes;
    if (!Array.isArray(outcomes) || outcomes.length === 0) {
        return [makePort(`${nodeId}__out`, "SOUTH", 0)];
    }
    const ports = [];
    let index = 0;
    for (const o of outcomes) {
        if (o != null && typeof o === "object" && typeof o.name === "string") {
            const outcomeName = o.name;
            ports.push(makePort(`${nodeId}__outcome_${outcomeName}`, "SOUTH", index, outcomeName));
            index++;
        }
    }
    return ports.length > 0 ? ports : [makePort(`${nodeId}__out`, "SOUTH", 0)];
}
/**
 * fork: one output port per outgoing edge from this node.
 * Handle IDs use a stable index: `branch_{index}`.
 */
function computeForkPorts(nodeId, edges) {
    const outgoing = edges.filter((e) => e.source === nodeId);
    if (outgoing.length <= 1) {
        return [makePort(`${nodeId}__out`, "SOUTH", 0)];
    }
    return outgoing.map((edge, index) => {
        const handleId = edge.sourceHandle ?? `branch_${index}`;
        return makePort(`${nodeId}__${handleId}`, "SOUTH", index);
    });
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function makePort(id, side, index, label) {
    return { id, side, index, ...(label !== undefined && { label }) };
}
//# sourceMappingURL=port-assignment.js.map