use crate::config::{get_biovault_home, is_syftbox_env, Config};
use crate::Result;
use dialoguer::{theme::ColorfulTheme, Confirm, Input};
use std::env;
use std::fs;
use std::io::IsTerminal;
use tracing::info;
pub async fn execute(email: Option<&str>) -> Result<()> {
let biovault_dir = get_biovault_home()?;
let email = if let Some(email) = email {
email.to_string()
} else if let Ok(syftbox_email) = env::var("SYFTBOX_EMAIL") {
if std::io::stdin().is_terminal() {
println!("Detected SyftBox environment email: {}", syftbox_email);
let use_syftbox = Confirm::with_theme(&ColorfulTheme::default())
.with_prompt("Use this email for BioVault?")
.default(true)
.interact()
.map_err(|e| anyhow::anyhow!("Prompt error: {}", e))?;
if use_syftbox {
syftbox_email
} else {
Input::with_theme(&ColorfulTheme::default())
.with_prompt("Enter email address")
.interact_text()
.map_err(|e| anyhow::anyhow!("Prompt error: {}", e))?
}
} else {
syftbox_email
}
} else if std::io::stdin().is_terminal() {
Input::with_theme(&ColorfulTheme::default())
.with_prompt("Enter email address")
.interact_text()
.map_err(|e| anyhow::anyhow!("Prompt error: {}", e))?
} else {
return Err(anyhow::anyhow!(
"email is required. Provide as 'bv init <email>' or set SYFTBOX_EMAIL"
)
.into());
};
if !biovault_dir.exists() {
fs::create_dir_all(&biovault_dir)?;
info!("Created directory: {:?}", biovault_dir);
}
let config_file = biovault_dir.join("config.yaml");
if config_file.exists() {
println!(
"Configuration file already exists at: {}",
config_file.display()
);
println!("Skipping initialization.");
} else {
if is_syftbox_env() {
println!("✓ Running in SyftBox virtualenv");
if let Ok(data_dir) = env::var("SYFTBOX_DATA_DIR") {
println!(" SyftBox data directory: {}", data_dir);
}
println!(" BioVault home: {}", biovault_dir.display());
}
let syftbox_config = if let Ok(config_path) = env::var("SYFTBOX_CONFIG_PATH") {
if std::path::Path::new(&config_path).exists() {
println!("✓ Detected SyftBox config at: {}", config_path);
Some(config_path)
} else {
None
}
} else {
let home_dir = dirs::home_dir()
.ok_or_else(|| anyhow::anyhow!("Could not determine home directory"))?;
let default_syftbox = home_dir.join(".syftbox").join("config.json");
if default_syftbox.exists() {
Some(default_syftbox.to_string_lossy().to_string())
} else {
None
}
};
let config = Config {
email: email.to_string(),
syftbox_config: syftbox_config.clone(),
};
config.save(&config_file)?;
println!("✓ BioVault initialized successfully!");
println!(" Configuration saved to: {}", config_file.display());
println!(" Email: {}", email);
if let Some(ref syftbox_cfg) = syftbox_config {
println!(" SyftBox config: {}", syftbox_cfg);
}
let env_dir = biovault_dir.join("env").join("default");
if !env_dir.exists() {
fs::create_dir_all(&env_dir)?;
info!("Created environment directory: {:?}", env_dir);
}
let template_nf_content = include_str!("../../templates/template.nf");
let template_nf_path = env_dir.join("template.nf");
fs::write(&template_nf_path, template_nf_content)?;
info!("Created template.nf at: {:?}", template_nf_path);
let nextflow_config_content = include_str!("../../templates/nextflow.config");
let nextflow_config_path = env_dir.join("nextflow.config");
fs::write(&nextflow_config_path, nextflow_config_content)?;
info!("Created nextflow.config at: {:?}", nextflow_config_path);
println!("✓ Nextflow templates installed to: {}", env_dir.display());
}
Ok(())
}