use anyhow::{Context, Result};
use console::{style, Emoji};
use std::collections::HashMap;
use std::path::Path;
pub fn env(json: bool) -> Result<()> {
if json {
env_json()?;
} else {
env_pretty()?;
}
Ok(())
}
fn env_pretty() -> Result<()> {
println!();
println!("{} {}", Emoji("🔍", ""), style("Kegani Environment").bold());
println!("{}", style("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━").dim());
println!();
let rust_version = std::process::Command::new("rustc")
.arg("--version")
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.unwrap_or_else(|| "not found".to_string());
print_env_line("Rust", rust_version.trim());
let cargo_version = std::process::Command::new("cargo")
.arg("--version")
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.unwrap_or_else(|| "not found".to_string());
print_env_line("Cargo", cargo_version.trim());
let target = std::env::consts::ARCH;
let family = std::env::consts::FAMILY;
let os = std::env::consts::OS;
print_env_line("Target", &format!("{}/{} ({})", target, family, os));
print_env_line("Kegani", env!("CARGO_PKG_VERSION"));
let has_cargo = Path::new("Cargo.toml").exists();
let has_manifest = Path::new("manifest/config/config.yaml").exists();
println!();
println!(" {} {}", style("Project:").dim(), if has_cargo { style("✓ Cargo.toml found").green() } else { style("✗ No Cargo.toml").red() });
println!(" {} {}", style("Config:").dim(), if has_manifest { style("✓ manifest/config found").green() } else { style("✗ No manifest/config").yellow() });
let db_url = std::env::var("DATABASE_URL").ok();
println!();
print_env_line("DATABASE_URL", db_url.as_deref().unwrap_or("(not set)"));
print_env_line("REDIS_URL", std::env::var("REDIS_URL").ok().as_deref().unwrap_or("(not set)"));
print_env_line("RUST_LOG", std::env::var("RUST_LOG").ok().as_deref().unwrap_or("(not set)"));
print_env_line("APP_ENV", std::env::var("APP_ENV").ok().as_deref().unwrap_or("dev"));
println!();
println!("{} {}", Emoji("✨", ""), style("Done").dim());
println!();
Ok(())
}
fn env_json() -> Result<()> {
let mut env_map = HashMap::new();
let rust_version = std::process::Command::new("rustc")
.arg("--version")
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.map(|s| s.trim().to_string())
.unwrap_or_else(|| "not found".to_string());
env_map.insert("rust".to_string(), rust_version);
let cargo_version = std::process::Command::new("cargo")
.arg("--version")
.output()
.ok()
.and_then(|o| String::from_utf8(o.stdout).ok())
.map(|s| s.trim().to_string())
.unwrap_or_else(|| "not found".to_string());
env_map.insert("cargo".to_string(), cargo_version);
let target = format!("{}/{}/{}", std::env::consts::ARCH, std::env::consts::FAMILY, std::env::consts::OS);
env_map.insert("target".to_string(), target);
env_map.insert("kegani".to_string(), env!("CARGO_PKG_VERSION").to_string());
env_map.insert("has_cargo".to_string(), Path::new("Cargo.toml").exists().to_string());
env_map.insert("has_manifest".to_string(), Path::new("manifest/config/config.yaml").exists().to_string());
if let Ok(v) = std::env::var("DATABASE_URL") {
env_map.insert("database_url".to_string(), v);
}
if let Ok(v) = std::env::var("REDIS_URL") {
env_map.insert("redis_url".to_string(), v);
}
if let Ok(v) = std::env::var("RUST_LOG") {
env_map.insert("rust_log".to_string(), v);
}
if let Ok(v) = std::env::var("APP_ENV") {
env_map.insert("app_env".to_string(), v);
}
let json = serde_json::to_string_pretty(&env_map).context("Failed to serialize to JSON")?;
println!("{}", json);
Ok(())
}
fn print_env_line(key: &str, value: &str) {
println!(" {} {}", style(format!("{key:16}")).dim(), style(value).cyan());
}