use std::io::{self, Write as _};
use std::path::PathBuf;
use anyhow::Result;
use crate::cli_args::Cli;
use crate::cli_i18n::CliI18n;
use crate::discovery;
use super::bundle::resolve_bundle_source;
use super::bundle::{detect_domain_from_filename, resolve_pack_source};
pub struct SetupParams {
pub bundle: PathBuf,
pub tenant: String,
pub team: Option<String>,
pub env: String,
pub advanced: bool,
}
pub fn prompt_setup_params(cli: &Cli, i18n: &CliI18n) -> Result<SetupParams> {
println!();
println!("Greentic Setup");
println!("==============");
println!();
println!("Configure a bundle for deployment. A bundle is a directory or");
println!(".gtbundle archive containing provider packs and configuration.");
println!();
println!(" Bundle name (required)");
println!(" A short name for this bundle (used as the directory name).");
println!(" Examples: my-demo telecom-bot customer-support");
print!(" > ");
io::stdout().flush()?;
let mut name_input = String::new();
io::stdin().read_line(&mut name_input)?;
let bundle_name = name_input.trim().to_string();
if bundle_name.is_empty() {
anyhow::bail!("Bundle name is required.");
}
println!();
let default_path = format!("./{bundle_name}");
println!(" Bundle path");
println!(" Path to a bundle directory or .gtbundle file.");
println!(" Press Enter to use: {default_path}");
print!(" > ");
io::stdout().flush()?;
let mut bundle_input = String::new();
io::stdin().read_line(&mut bundle_input)?;
let bundle_str = bundle_input.trim();
let bundle = if bundle_str.is_empty() {
PathBuf::from(&default_path)
} else {
PathBuf::from(bundle_str)
};
let bundle_dir = resolve_bundle_source(&bundle, i18n)?;
let discovered =
discovery::discover(&bundle_dir).unwrap_or_else(|_| discovery::DiscoveryResult {
domains: discovery::DetectedDomains {
messaging: false,
events: false,
oauth: false,
state: false,
secrets: false,
},
providers: Vec::new(),
app_packs: Vec::new(),
});
println!();
let setup_targets = discovered.setup_targets();
if setup_targets.is_empty() {
println!(" No packs found in bundle.");
} else {
println!(" Found {} pack(s) in bundle:", setup_targets.len());
for p in setup_targets {
println!(" - {} ({})", p.provider_id, p.domain);
}
}
println!();
println!(" Add packs to bundle");
println!(" Enter path to a .gtpack file or OCI reference, or press Enter to skip.");
println!(" Local: ./messaging-telegram.gtpack ../packs/state-redis.gtpack");
println!(" OCI: oci://ghcr.io/greentic-ai-org/packs/mcp-github.gtpack:latest");
loop {
print!(" add pack> ");
io::stdout().flush()?;
let mut pack_input = String::new();
io::stdin().read_line(&mut pack_input)?;
let pack_str = pack_input.trim();
if pack_str.is_empty() {
break;
}
match resolve_pack_source(pack_str) {
Ok(pack_path) => {
let filename = pack_path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("pack.gtpack");
let domain = detect_domain_from_filename(filename);
let target_dir = bundle_dir.join("providers").join(domain);
std::fs::create_dir_all(&target_dir)?;
let target = target_dir.join(filename);
std::fs::copy(&pack_path, &target)?;
println!(" Added {filename} -> providers/{domain}/");
}
Err(e) => {
println!(" Error: {e}");
continue;
}
}
}
let default_tenant = &cli.tenant;
println!();
println!(" Tenant (optional)");
println!(" Tenant identifier for multi-tenant isolation.");
print!(" > (default: {default_tenant}) ");
io::stdout().flush()?;
let mut tenant_input = String::new();
io::stdin().read_line(&mut tenant_input)?;
let tenant = if tenant_input.trim().is_empty() {
default_tenant.clone()
} else {
tenant_input.trim().to_string()
};
println!();
println!(" Team (optional)");
println!(" Team within the tenant. Leave blank for default.");
print!(" > ");
io::stdout().flush()?;
let mut team_input = String::new();
io::stdin().read_line(&mut team_input)?;
let team = if team_input.trim().is_empty() {
None
} else {
Some(team_input.trim().to_string())
};
let default_env = &cli.env;
println!();
println!(" Environment (optional)");
println!(" Deployment environment for secrets and configuration.");
print!(" > (default: {default_env}) ");
io::stdout().flush()?;
let mut env_input = String::new();
io::stdin().read_line(&mut env_input)?;
let env = if env_input.trim().is_empty() {
default_env.clone()
} else {
env_input.trim().to_string()
};
println!();
println!(" Advanced mode");
println!(" Show all configuration options including optional ones.");
print!(" > [y/N] ");
io::stdout().flush()?;
let mut adv_input = String::new();
io::stdin().read_line(&mut adv_input)?;
let advanced = matches!(
adv_input.trim().to_ascii_lowercase().as_str(),
"y" | "yes" | "true" | "1"
);
println!();
Ok(SetupParams {
bundle,
tenant,
team,
env,
advanced,
})
}