use crate::commands::{print_banner, resolve_workflow};
use anyhow::{Context, Result};
use colored::Colorize;
use oxo_flow_core::config::WorkflowConfig;
use oxo_flow_core::dag::WorkflowDag;
use std::path::PathBuf;
pub fn handle_graph(workflow: PathBuf, format: String, output: Option<PathBuf>) -> Result<()> {
print_banner();
let workflow = resolve_workflow(Some(workflow))?;
let config = WorkflowConfig::from_file(&workflow)
.with_context(|| format!("failed to parse {}", workflow.display()))?;
let dag = WorkflowDag::from_rules(&config.rules).context("failed to build workflow DAG")?;
let result = match format.as_str() {
"ascii" => dag.to_ascii().map_err(|e| anyhow::anyhow!(e)),
"dot" => Ok(dag.to_dot()),
"dot-clustered" => dag.to_dot_clustered().map_err(|e| anyhow::anyhow!(e)),
"tree" => dag.to_ascii_tree().map_err(|e| anyhow::anyhow!(e)),
_ => Err(anyhow::anyhow!("unsupported graph format: {}", format)),
}?;
if let Some(path) = output {
std::fs::write(&path, result)?;
eprintln!("{} Graph saved to {}", "✓".green(), path.display());
} else {
println!("{}", result);
}
Ok(())
}
pub fn handle_report(workflow: PathBuf, format: String, output: Option<PathBuf>) -> Result<()> {
print_banner();
let workflow = resolve_workflow(Some(workflow))?;
let config = WorkflowConfig::from_file(&workflow)
.with_context(|| format!("failed to parse {}", workflow.display()))?;
let mut report = oxo_flow_core::report::Report::new(
&format!("{} Report", config.workflow.name),
&config.workflow.name,
&config.workflow.version,
);
report.add_section(oxo_flow_core::report::ReportSection {
title: "Workflow Information".to_string(),
id: "workflow-info".to_string(),
content: oxo_flow_core::report::ReportContent::KeyValue {
pairs: vec![
("Name".to_string(), config.workflow.name.clone()),
("Version".to_string(), config.workflow.version.clone()),
("Rules".to_string(), config.rules.len().to_string()),
],
},
subsections: vec![],
});
let content = match format.as_str() {
"json" => report.to_json().map_err(|e| anyhow::anyhow!(e))?,
_ => report.to_html(),
};
match output {
Some(path) => {
std::fs::write(&path, &content)?;
eprintln!("Report written to {}", path.display());
}
None => {
println!("{content}");
}
}
Ok(())
}
pub fn handle_diff(workflow_a: PathBuf, workflow_b: PathBuf) -> Result<()> {
print_banner();
let config_a = WorkflowConfig::from_file(&workflow_a)
.with_context(|| format!("failed to parse {}", workflow_a.display()))?;
let config_b = WorkflowConfig::from_file(&workflow_b)
.with_context(|| format!("failed to parse {}", workflow_b.display()))?;
let diffs = oxo_flow_core::format::diff_workflows(&config_a, &config_b);
if diffs.is_empty() {
eprintln!("{} Workflows are identical", "✓".green().bold());
} else {
eprintln!(
"{} {} difference(s) between {} and {}:",
"Diff:".bold().yellow(),
diffs.len(),
workflow_a.display(),
workflow_b.display()
);
for diff in &diffs {
eprintln!(" {} [{}] {}", "•".cyan(), diff.category, diff.description);
}
}
Ok(())
}
pub fn handle_export(workflow: PathBuf, format: String, output: Option<PathBuf>) -> Result<()> {
print_banner();
let workflow = resolve_workflow(Some(workflow))?;
let config = WorkflowConfig::from_file(&workflow)
.with_context(|| format!("failed to parse {}", workflow.display()))?;
let content = match format.as_str() {
"singularity" => {
let pkg = oxo_flow_core::container::PackageConfig {
format: oxo_flow_core::container::ContainerFormat::Singularity,
..Default::default()
};
oxo_flow_core::container::generate_singularity_def(&config, &pkg)
.map_err(|e| anyhow::anyhow!(e))?
}
"toml" => oxo_flow_core::format::format_workflow(&config),
_ => {
let pkg = oxo_flow_core::container::PackageConfig::default();
oxo_flow_core::container::generate_dockerfile(&config, &pkg)
.map_err(|e| anyhow::anyhow!(e))?
}
};
match output {
Some(path) => {
std::fs::write(&path, &content)?;
eprintln!(
"{} Exported {} to {}",
"✓".green().bold(),
format,
path.display()
);
}
None => {
println!("{content}");
}
}
Ok(())
}