use std::path::PathBuf;

/// Environment variable names used by the FireCracker backend.
pub const ENV_FIRECRACKER_PATH: &str = "PLASMAVMC_FIRECRACKER_PATH";
pub const ENV_FIRECRACKER_JAILER_PATH: &str = "PLASMAVMC_FIRECRACKER_JAILER_PATH";
pub const ENV_FIRECRACKER_RUNTIME_DIR: &str = "PLASMAVMC_FIRECRACKER_RUNTIME_DIR";
pub const ENV_FIRECRACKER_SOCKET_BASE_PATH: &str = "PLASMAVMC_FIRECRACKER_SOCKET_BASE_PATH";
pub const ENV_FIRECRACKER_KERNEL_PATH: &str = "PLASMAVMC_FIRECRACKER_KERNEL_PATH";
pub const ENV_FIRECRACKER_ROOTFS_PATH: &str = "PLASMAVMC_FIRECRACKER_ROOTFS_PATH";
pub const ENV_FIRECRACKER_INITRD_PATH: &str = "PLASMAVMC_FIRECRACKER_INITRD_PATH";
pub const ENV_FIRECRACKER_BOOT_ARGS: &str = "PLASMAVMC_FIRECRACKER_BOOT_ARGS";
pub const ENV_FIRECRACKER_USE_JAILER: &str = "PLASMAVMC_FIRECRACKER_USE_JAILER";

/// Resolve FireCracker binary path, falling back to default.
pub fn resolve_firecracker_path() -> PathBuf {
    std::env::var_os(ENV_FIRECRACKER_PATH)
        .map(PathBuf::from)
        .unwrap_or_else(|| PathBuf::from("/usr/bin/firecracker"))
}

/// Resolve optional Jailer binary path from env.
pub fn resolve_jailer_path() -> Option<PathBuf> {
    std::env::var_os(ENV_FIRECRACKER_JAILER_PATH).map(PathBuf::from)
}

/// Resolve runtime directory, falling back to default.
pub fn resolve_runtime_dir() -> PathBuf {
    std::env::var_os(ENV_FIRECRACKER_RUNTIME_DIR)
        .map(PathBuf::from)
        .unwrap_or_else(|| PathBuf::from("/var/run/plasmavmc/firecracker"))
}

/// Resolve socket base path, falling back to default.
pub fn resolve_socket_base_path() -> PathBuf {
    std::env::var_os(ENV_FIRECRACKER_SOCKET_BASE_PATH)
        .map(PathBuf::from)
        .unwrap_or_else(|| PathBuf::from("/tmp/firecracker"))
}

/// Resolve kernel image path from env (required).
pub fn resolve_kernel_path() -> Option<PathBuf> {
    std::env::var_os(ENV_FIRECRACKER_KERNEL_PATH).map(PathBuf::from)
}

/// Resolve rootfs image path from env (required).
pub fn resolve_rootfs_path() -> Option<PathBuf> {
    std::env::var_os(ENV_FIRECRACKER_ROOTFS_PATH).map(PathBuf::from)
}

/// Resolve optional initrd image path from env.
pub fn resolve_initrd_path() -> Option<PathBuf> {
    std::env::var_os(ENV_FIRECRACKER_INITRD_PATH).map(PathBuf::from)
}

/// Resolve boot arguments, falling back to default.
pub fn resolve_boot_args() -> String {
    std::env::var(ENV_FIRECRACKER_BOOT_ARGS)
        .unwrap_or_else(|_| "console=ttyS0".to_string())
}

/// Resolve whether to use jailer, falling back to checking if jailer exists.
pub fn resolve_use_jailer() -> bool {
    match std::env::var(ENV_FIRECRACKER_USE_JAILER) {
        Ok(val) => val == "1" || val.to_lowercase() == "true",
        Err(_) => {
            // Default to true if jailer binary exists
            resolve_jailer_path()
                .map(|p| p.exists())
                .unwrap_or(false)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn resolve_firecracker_default_when_unset() {
        std::env::remove_var(ENV_FIRECRACKER_PATH);
        let path = resolve_firecracker_path();
        assert_eq!(path, PathBuf::from("/usr/bin/firecracker"));
    }

    #[test]
    fn resolve_firecracker_from_env() {
        std::env::set_var(ENV_FIRECRACKER_PATH, "/tmp/firecracker");
        let path = resolve_firecracker_path();
        assert_eq!(path, PathBuf::from("/tmp/firecracker"));
        std::env::remove_var(ENV_FIRECRACKER_PATH);
    }

    #[test]
    fn resolve_boot_args_default() {
        std::env::remove_var(ENV_FIRECRACKER_BOOT_ARGS);
        let args = resolve_boot_args();
        assert_eq!(args, "console=ttyS0");
    }

    #[test]
    fn resolve_boot_args_from_env() {
        std::env::set_var(ENV_FIRECRACKER_BOOT_ARGS, "console=ttyS0 reboot=k");
        let args = resolve_boot_args();
        assert_eq!(args, "console=ttyS0 reboot=k");
        std::env::remove_var(ENV_FIRECRACKER_BOOT_ARGS);
    }
}
