import { MarkerType, Position } from "../../../node_modules/@xyflow/system/dist/esm/index.js";
import dagre_esm_default from "../../../node_modules/@dagrejs/dagre/dist/dagre.esm.js";
var NODE_WIDTH = 130, NODE_HEIGHT = 70, CONDITION_OPERATORS = {
	gt: ">",
	lt: "<",
	eq: "==",
	ne: "!=",
	ge: ">=",
	le: "<="
};
function getLayoutedElements(e, d, f = "LR") {
	let p = new dagre_esm_default.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
	p.setGraph({
		rankdir: f,
		nodesep: 100,
		ranksep: 200
	});
	for (let s of e) p.setNode(s.id, {
		width: NODE_WIDTH,
		height: NODE_HEIGHT
	});
	for (let e of d) p.setEdge(e.source, e.target);
	return dagre_esm_default.layout(p), {
		nodes: e.map((e) => {
			let c = p.node(e.id);
			return {
				...e,
				targetPosition: f === "LR" ? Position.Left : Position.Top,
				sourcePosition: f === "LR" ? Position.Right : Position.Bottom,
				position: {
					x: c.x - NODE_WIDTH / 2,
					y: c.y - NODE_HEIGHT / 2
				}
			};
		}),
		edges: d
	};
}
function getTransitions(e, s = /* @__PURE__ */ new Set()) {
	if (!e || typeof e != "object" || s.has(e)) return [];
	try {
		s.add(e);
	} catch {
		return [];
	}
	let c = e;
	if (Array.isArray(c.transitions)) return c.transitions;
	if (c.definition) {
		let e = getTransitions(c.definition, s);
		if (e.length > 0) return e;
	}
	if (c.specification) {
		let e = getTransitions(c.specification, s);
		if (e.length > 0) return e;
	}
	for (let e in c) {
		if (e === "history" || e === "data") continue;
		let l = c[e];
		if (l && typeof l == "object") {
			let e = getTransitions(l, s);
			if (e.length > 0) return e;
		} else if (typeof l == "string" && l.includes("\"transitions\":")) try {
			let e = getTransitions(JSON.parse(l), s);
			if (e.length > 0) return e;
		} catch {}
	}
	return [];
}
function formatCondition(e) {
	if (!e) return "";
	let s = e.replace(/\{\{|\}\}/g, "").trim(), c = s.split(/\s+/);
	if (c.length === 3) {
		let [e, s, l] = c, u = CONDITION_OPERATORS[e];
		if (u) return `${s} ${u} ${l}`;
	}
	return s;
}
function buildWorkflowGraph(e, s, c, l = [], u, d = !1) {
	let p = collectTransitions(e, s, l), m = extractHistory(s), h = collectStates(p, m), x = buildExecutedMap(m), S = resolveTransitions(p, m), C = findEndStates(h, S), w = findVisitedStates(m), T = computeStateRanks(S), E = buildNodes(h, {
		workflowId: c,
		currentPlace: s?.place,
		endStates: C,
		visitedStates: w,
		visitCounts: buildVisitCounts(m),
		direction: u,
		forceVisible: d
	}), D = buildEdges(S, {
		workflowId: c,
		executedMap: x,
		stateRanks: T,
		forceVisible: d
	});
	return E.length > 1 ? getLayoutedElements(E, D, u) : {
		nodes: E,
		edges: D
	};
}
function collectTransitions(e, s, c) {
	let l = [...c];
	e && l.push(...getTransitions(e)), s && l.push(...getTransitions(s));
	let u = /* @__PURE__ */ new Set();
	return l.filter((e) => {
		let s = Array.isArray(e.from) ? e.from.join(",") : e.from, c = `${e.id}-${s}-${e.to}`;
		return u.has(c) ? !1 : (u.add(c), !0);
	});
}
function extractHistory(e) {
	return e?.history ?? [];
}
function collectStates(e, s) {
	let c = new Set(["start"]);
	for (let s of e) {
		let e = Array.isArray(s.from) ? s.from : [s.from];
		for (let s of e) c.add(s ?? "start");
		c.add(s.to);
	}
	for (let e of s) e.data?.place && c.add(e.data.place), e.data?.transition && (c.add(e.data.transition.from ?? "start"), c.add(e.data.transition.to));
	return c;
}
function buildVisitCounts(e) {
	let s = new Map([["start", 1]]);
	for (let c of e) {
		let e = c.data?.place;
		e && s.set(e, (s.get(e) ?? 0) + 1);
	}
	return s;
}
function buildExecutedMap(e) {
	let s = /* @__PURE__ */ new Map();
	for (let c of e) {
		let e = c.data?.transition;
		if (!e) continue;
		let l = `${e.from ?? "start"}->${e.to}:${e.id}`;
		s.set(l, (s.get(l) ?? 0) + 1);
	}
	return s;
}
function resolveTransitions(e, s) {
	let c = [];
	for (let s of e) {
		let e = Array.isArray(s.from) ? s.from : [s.from], l = s;
		for (let u of e) c.push({
			id: s.id,
			from: u ?? "start",
			to: s.to,
			condition: l.if ?? l.condition,
			trigger: s.trigger,
			call: s.call
		});
	}
	for (let e of s) {
		let s = e.data?.transition;
		if (!s?.id) continue;
		let l = s.from ?? "start";
		c.some((e) => e.from === l && e.to === s.to && e.id === s.id) || c.push({
			id: s.id,
			from: l,
			to: s.to
		});
	}
	return c;
}
function findEndStates(e, s) {
	let c = new Set(s.map((e) => e.from)), l = /* @__PURE__ */ new Set();
	for (let s of e) !c.has(s) && s !== "start" && l.add(s);
	return l;
}
function findVisitedStates(e) {
	let s = new Set(["start"]);
	for (let c of e) c.data?.place && s.add(c.data.place), c.data?.transition?.to && s.add(c.data.transition.to);
	return s;
}
function computeStateRanks(e) {
	let s = /* @__PURE__ */ new Map();
	for (let c of e) {
		if (c.from === c.to) continue;
		let e = s.get(c.from) ?? [];
		e.push(c.to), s.set(c.from, e);
	}
	let c = new Map([["start", 0]]), l = ["start"];
	for (; l.length > 0;) {
		let e = l.shift(), u = c.get(e);
		for (let d of s.get(e) ?? []) c.has(d) || (c.set(d, u + 1), l.push(d));
	}
	return c;
}
function buildNodes(e, s) {
	return Array.from(e).map((e) => ({
		id: `${s.workflowId}-${e}`,
		type: "stateNode",
		position: {
			x: 0,
			y: 0
		},
		data: {
			label: e,
			isStart: e === "start",
			isEnd: s.endStates.has(e),
			isCurrent: e === s.currentPlace,
			isVisited: s.visitedStates.has(e),
			visitCount: s.visitCounts.get(e) ?? 0,
			direction: s.direction,
			forceVisible: s.forceVisible
		}
	}));
}
function buildEdges(s, c) {
	let l = /* @__PURE__ */ new Set(), u = [], d = 0;
	for (let f of s) {
		let s = `${f.from}->${f.to}:${f.id}`;
		if (l.has(s)) continue;
		l.add(s);
		let p = c.executedMap.has(s), m = f.trigger === "onEntry", h = f.from === f.to, g = c.stateRanks.get(f.from) ?? 0, _ = c.stateRanks.get(f.to) ?? 0, v = !h && _ <= g, y = p ? "var(--primary)" : "var(--muted-foreground)", b = {
			...f,
			isExecuted: p,
			isSelfLoop: h,
			isBackEdge: v,
			forceVisible: c.forceVisible
		};
		u.push({
			id: `edge-${c.workflowId}-${d++}`,
			source: `${c.workflowId}-${f.from}`,
			target: `${c.workflowId}-${f.to}`,
			...v && {
				sourceHandle: "bottom-source",
				targetHandle: "bottom-target"
			},
			type: "workflowTransition",
			animated: !1,
			style: {
				strokeWidth: p ? 2.5 : 1.5,
				stroke: y,
				strokeDasharray: m ? "4,4" : p ? void 0 : "5,5",
				opacity: p || c.forceVisible ? 1 : .3
			},
			markerEnd: {
				type: MarkerType.ArrowClosed,
				width: 18,
				height: 18,
				color: y
			},
			data: b
		});
	}
	return u;
}
export { buildWorkflowGraph, formatCondition, getTransitions };
