#![allow(
    dead_code,
    unused_imports,
    unused_variables,
    unused_assignments,
    unused,
    clippy::excessive_nesting
)]

//! Core provisioning engine for executing infrastructure commands

use std::process::Stdio;

use anyhow::{Context, Result};
use serde_json::Value;
use tracing::{debug, info};

use crate::config::Config;
use crate::errors::ProvisioningError;

#[derive(Debug, Clone)]
pub struct ServerConfig {
    pub hostname: String,
    pub instance_type: String,
    pub count: u32,
    pub provider: String,
    pub region: Option<String>,
    pub purpose: Option<String>,
}

pub struct ProvisioningEngine {
    config: Config,
}

impl ProvisioningEngine {
    pub fn new(config: &Config) -> Result<Self> {
        Ok(Self {
            config: config.clone(),
        })
    }

    /// Create servers based on parsed configuration
    pub fn create_server(&self, server_config: &ServerConfig, check_mode: bool) -> Result<String> {
        info!("Creating server: {:?}", server_config);

        let mut args = vec![
            "server".to_string(),
            "create".to_string(),
            "--infra".to_string(),
            format!("ai-{}", server_config.hostname),
        ];

        if check_mode {
            args.push("--check".to_string());
        }

        if let Some(region) = &server_config.region {
            args.extend(vec!["--region".to_string(), region.clone()]);
        }

        args.push("--out".to_string());
        args.push("json".to_string());

        let result = self.execute_provisioning_command(&args)?;

        // Parse and format the result
        if let Ok(json_result) = serde_json::from_str::<Value>(&result) {
            Ok(self.format_server_result(&json_result, check_mode))
        } else {
            Ok(result)
        }
    }

    /// Process natural language infrastructure queries
    pub fn process_query(
        &self,
        query: &str,
        infra_name: Option<&str>,
        output_format: &str,
    ) -> Result<String> {
        info!("Processing query: {}", query);

        let mut args = vec!["show".to_string()];

        // Determine what to show based on the query
        if query.to_lowercase().contains("server") || query.to_lowercase().contains("instance") {
            args.push("servers".to_string());
        } else if query.to_lowercase().contains("cost") || query.to_lowercase().contains("price") {
            args.push("costs".to_string());
        } else if query.to_lowercase().contains("status") {
            args.push("data".to_string());
        } else {
            args.push("settings".to_string());
        }

        if let Some(infra) = infra_name {
            args.extend(vec!["--infra".to_string(), infra.to_string()]);
        }

        args.extend(vec!["--out".to_string(), output_format.to_string()]);

        let result = self.execute_provisioning_command(&args)?;

        // Add natural language interpretation
        Ok(format!(
            "Based on your query: \"{}\"\n\n{}",
            query,
            self.interpret_query_result(query, &result)
        ))
    }

    /// Deploy a task service
    pub fn deploy_taskserv(
        &self,
        service_name: &str,
        infra_name: &str,
        _configuration: &Value,
        check_mode: bool,
    ) -> Result<String> {
        info!("Deploying service {} to {}", service_name, infra_name);

        let mut args = vec![
            "taskserv".to_string(),
            "create".to_string(),
            service_name.to_string(),
            "--infra".to_string(),
            infra_name.to_string(),
        ];

        if check_mode {
            args.push("--check".to_string());
        }

        args.extend(vec!["--out".to_string(), "json".to_string()]);

        let result = self.execute_provisioning_command(&args)?;

        Ok(format!(
            "🚀 Service '{}' deployment on '{}' infrastructure:\n\n{}",
            service_name, infra_name, result
        ))
    }

    /// Create a complete cluster
    pub fn create_cluster(
        &self,
        description: &str,
        cluster_type: &str,
        services: &[&str],
        infra_name: &str,
    ) -> Result<String> {
        info!("Creating {} cluster: {}", cluster_type, description);

        // First create the infrastructure
        let mut results = Vec::new();

        // Generate infrastructure
        let gen_args = vec![
            "generate".to_string(),
            "infra".to_string(),
            "--new".to_string(),
            infra_name.to_string(),
            "--template".to_string(),
            format!("{}-cluster", cluster_type),
        ];

        match self.execute_provisioning_command(&gen_args) {
            Ok(result) => results.push(format!("📋 Infrastructure generated:\n{}", result)),
            Err(e) => results.push(format!("⚠️ Infrastructure generation: {}", e)),
        }

        // Create servers
        let server_args = vec![
            "server".to_string(),
            "create".to_string(),
            "--infra".to_string(),
            infra_name.to_string(),
        ];

        match self.execute_provisioning_command(&server_args) {
            Ok(result) => results.push(format!("🖥️ Servers created:\n{}", result)),
            Err(e) => results.push(format!("⚠️ Server creation: {}", e)),
        }

        // Deploy each service
        for service in services {
            let service_args = vec![
                "taskserv".to_string(),
                "create".to_string(),
                service.to_string(),
                "--infra".to_string(),
                infra_name.to_string(),
            ];

            match self.execute_provisioning_command(&service_args) {
                Ok(result) => {
                    results.push(format!("⚙️ Service '{}' deployed:\n{}", service, result))
                }
                Err(e) => results.push(format!("⚠️ Service '{}': {}", service, e)),
            }
        }

        Ok(results.join("\n\n"))
    }

    /// Get status of infrastructure
    pub fn get_status(&self, infra_name: Option<&str>, detailed: bool) -> Result<String> {
        let mut args = vec!["show".to_string()];

        if detailed {
            args.push("alldata".to_string());
        } else {
            args.push("data".to_string());
        }

        if let Some(infra) = infra_name {
            args.extend(vec!["--infra".to_string(), infra.to_string()]);
        }

        args.extend(vec!["--out".to_string(), "json".to_string()]);

        let result = self.execute_provisioning_command(&args)?;

        // Parse and format the status
        if let Ok(json_result) = serde_json::from_str::<Value>(&result) {
            Ok(self.format_status_result(&json_result, detailed))
        } else {
            Ok(result)
        }
    }

    /// Execute a provisioning command
    fn execute_provisioning_command(&self, args: &[String]) -> Result<String> {
        debug!("Executing command: {:?}", args);

        let cmd_path = "provisioning"; // Use default command name

        let output = std::process::Command::new(cmd_path)
            .args(args)
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .output()
            .with_context(|| format!("Failed to execute command: {}", cmd_path))?;

        if !output.status.success() {
            let stderr = String::from_utf8_lossy(&output.stderr);
            return Err(ProvisioningError::command_failed(format!(
                "Command failed with status {}: {}",
                output.status.code().unwrap_or(-1),
                stderr
            ))
            .into());
        }

        let stdout = String::from_utf8_lossy(&output.stdout);
        Ok(stdout.to_string())
    }

    /// Format server creation result
    fn format_server_result(&self, result: &Value, check_mode: bool) -> String {
        let prefix = if check_mode {
            "🔍 Check mode result"
        } else {
            "✅ Server creation result"
        };

        if let Some(servers) = result.get("servers").and_then(|s| s.as_array()) {
            let mut output = format!("{}\n\n", prefix);

            for server in servers {
                if let (Some(hostname), Some(status)) = (
                    server.get("hostname").and_then(|h| h.as_str()),
                    server.get("status").and_then(|s| s.as_str()),
                ) {
                    output.push_str(&format!("• {}: {}\n", hostname, status));

                    if let Some(ip) = server.get("public_ip").and_then(|ip| ip.as_str()) {
                        output.push_str(&format!("  IP: {}\n", ip));
                    }

                    if let Some(cost) = server.get("cost_hour").and_then(|c| c.as_str()) {
                        output.push_str(&format!("  Cost: {}/hour\n", cost));
                    }
                }
            }

            output
        } else {
            format!(
                "{}\n\n{}",
                prefix,
                serde_json::to_string_pretty(result).unwrap_or_default()
            )
        }
    }

    /// Format status result
    fn format_status_result(&self, result: &Value, detailed: bool) -> String {
        let mut output = String::new();

        if let Some(main_name) = result.get("main_name").and_then(|n| n.as_str()) {
            output.push_str(&format!("📊 Infrastructure: {}\n\n", main_name));
        }

        if let Some(servers) = result.get("servers").and_then(|s| s.as_array()) {
            output.push_str("🖥️ Servers:\n");
            for server in servers {
                if let Some(hostname) = server.get("hostname").and_then(|h| h.as_str()) {
                    let status = server
                        .get("status")
                        .and_then(|s| s.as_str())
                        .unwrap_or("unknown");
                    let emoji = match status {
                        "running" => "🟢",
                        "stopped" => "🔴",
                        "pending" => "🟡",
                        _ => "⚪",
                    };
                    output.push_str(&format!("  {} {}: {}\n", emoji, hostname, status));
                }
            }
            output.push('\n');
        }

        if detailed {
            if let Some(costs) = result.get("costs") {
                output.push_str(&format!(
                    "💰 Costs: {}\n",
                    serde_json::to_string_pretty(costs).unwrap_or_default()
                ));
            }
        }

        output
    }

    /// Interpret query result with natural language
    fn interpret_query_result(&self, query: &str, result: &str) -> String {
        // Simple interpretation based on query keywords
        if query.to_lowercase().contains("cost") || query.to_lowercase().contains("price") {
            format!("💰 Cost analysis:\n{}", result)
        } else if query.to_lowercase().contains("status") || query.to_lowercase().contains("health")
        {
            format!("📊 System status:\n{}", result)
        } else if query.to_lowercase().contains("problem") || query.to_lowercase().contains("error")
        {
            format!("🔍 Issue analysis:\n{}", result)
        } else {
            result.to_string()
        }
    }
}
