use std::path::PathBuf;
use anyhow::Result;
use clap::Args;
use offline_registry::{architecture_markdown, implementation_plan_markdown, Registry};
use serde_json::json;
use crate::output;
#[derive(Args)]
pub struct PlanArgs {
pub prompt: String,
#[arg(long)]
pub platform: Option<String>,
#[arg(long)]
pub out: Option<PathBuf>,
#[arg(long)]
pub json: bool,
}
pub fn run(args: PlanArgs) -> Result<()> {
let registry = Registry::load_default()?;
let plan = registry.plan(&args.prompt, args.platform.as_deref())?;
let architecture = architecture_markdown(&plan);
let implementation = implementation_plan_markdown(&plan);
if let Some(out) = &args.out {
std::fs::create_dir_all(out)?;
std::fs::write(out.join("architecture.md"), &architecture)?;
std::fs::write(out.join("implementation-plan.md"), &implementation)?;
}
if args.json {
return output::json(&json!({
"plan": plan,
"documents": {
"architecture.md": architecture,
"implementation-plan.md": implementation,
}
}));
}
output::success(&format!(
"{} ({}) on {}",
plan.workflow_title, plan.workflow, plan.platform
));
output::heading("Packages");
for p in &plan.resolution.packages {
output::item(&p.name, &format!("v{} — {}", p.version, p.reason));
}
for w in &plan.resolution.warnings {
output::warn(w);
}
output::heading("Install");
for cmd in &plan.resolution.install_commands {
println!(" {cmd}");
}
if let Some(t) = &plan.template {
output::heading("Scaffold");
println!(
" offline create {} --platform {} --name <name>",
plan.workflow, plan.platform
);
output::note(&format!("template: {t}"));
}
if !plan.alternatives.is_empty() {
output::heading("Alternatives considered");
for alt in &plan.alternatives {
output::item(&alt.workflow, &format!("score {:.1}", alt.score));
}
}
if let Some(out) = &args.out {
output::note(&format!(
"architecture.md and implementation-plan.md written to {}",
out.display()
));
} else {
output::note("add --out <dir> to write architecture.md / implementation-plan.md");
}
Ok(())
}