//! `keg env` command — Print environment diagnostics

use anyhow::{Context, Result};
use console::{style, Emoji};
use std::collections::HashMap;
use std::path::Path;

/// Print environment information
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!();

    // Rust version
    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());

    // Cargo version
    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());

    // Target triple
    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));

    // Kegani version
    print_env_line("Kegani", env!("CARGO_PKG_VERSION"));

    // Project check
    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() });

    // Database URL check
    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();

    // Rust version
    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);

    // Cargo 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);

    // Target
    let target = format!("{}/{}/{}", std::env::consts::ARCH, std::env::consts::FAMILY, std::env::consts::OS);
    env_map.insert("target".to_string(), target);

    // Kegani version
    env_map.insert("kegani".to_string(), env!("CARGO_PKG_VERSION").to_string());

    // Project status
    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());

    // Environment variables
    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());
}