use std::time::Duration;
use graph_flow::{Graph, GraphBuilder};
use crate::{definitions::WorkflowDef, kinds::KindRegistry, platform::Platform};
pub fn compile(def: &WorkflowDef, kinds: &KindRegistry, p: &Platform) -> anyhow::Result<Graph> {
let mut b = GraphBuilder::new(def.id.clone());
let mut nodes: Vec<_> = def.nodes.iter().collect();
nodes.sort_by_key(|n| n.id != def.entry);
for n in nodes {
let factory = kinds.get(&n.kind).ok_or_else(|| {
anyhow::anyhow!("workflow `{}` node `{}`: unknown kind `{}` (known: {:?})", def.id, n.id, n.kind, kinds.names())
})?;
let task = factory(n, p).map_err(|e| anyhow::anyhow!("workflow `{}` node `{}`: {e}", def.id, n.id))?;
b = b.add_task(task);
}
for e in &def.edges {
b = match (&e.when, &e.otherwise) {
(Some(cond), Some(no)) => {
let cond = cond.clone();
b.add_conditional_edge(e.from.clone(), move |ctx| cond.eval(ctx), e.to.clone(), no.clone())
}
(Some(_), None) => anyhow::bail!("workflow `{}`: edge from `{}` has `when` without `else`", def.id, e.from),
_ => b.add_edge(e.from.clone(), e.to.clone()),
};
}
Ok(b.with_task_timeout(Duration::from_secs(def.limits.task_timeout_sec))
.with_max_execution_steps(def.limits.max_steps)
.build()?)
}