use std::path::Path;
use std::process::Command;

use crate::error::{ConfigError, Result};

/// Verifica si el CLI de Nickel está disponible
pub fn is_nickel_available() -> bool {
    Command::new("nickel")
        .arg("--version")
        .output()
        .map(|output| output.status.success())
        .unwrap_or(false)
}

/// Exporta un archivo NCL a JSON usando el CLI de Nickel
///
/// # Arguments
/// - `ncl_path`: Ruta al archivo .ncl a exportar
///
/// # Returns
/// String con el JSON resultante de la exportación
///
/// # Errors
/// - `NickelNotInstalled` si el CLI no está disponible
/// - `NickelExportFailed` si la exportación falla
pub fn export_to_json<P: AsRef<Path>>(ncl_path: P) -> Result<String> {
    let ncl_path = ncl_path.as_ref();

    if !is_nickel_available() {
        tracing::warn!("Nickel CLI not installed - cannot load {:?}", ncl_path);
        return Err(ConfigError::NickelNotInstalled);
    }

    tracing::debug!("Exporting NCL config to JSON: {:?}", ncl_path);

    let output = Command::new("nickel")
        .arg("export")
        .arg("--format")
        .arg("json")
        .arg(ncl_path)
        .env("NICKEL_IMPORT_PATH", "provisioning/schemas")
        .output()
        .map_err(|e| ConfigError::io_error(format!("Failed to execute nickel CLI: {}", e)))?;

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        tracing::error!("Nickel export failed for {:?}: {}", ncl_path, stderr);
        return Err(ConfigError::nickel_failed(stderr.to_string()));
    }

    let json_string = String::from_utf8(output.stdout).map_err(|e| {
        ConfigError::deserialization_failed(format!("Invalid UTF-8 in nickel output: {}", e))
    })?;

    tracing::debug!(
        "Successfully exported NCL config ({} bytes)",
        json_string.len()
    );

    Ok(json_string)
}

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

    #[test]
    fn test_is_nickel_available() {
        // This test just verifies the function doesn't panic
        let _ = is_nickel_available();
    }
}
