use crate::config::{AppConfig, Environment, ServiceType};
use crate::error::Result;
use crate::output::{create_table, is_json_output, output_success, print_title, ProgressIndicator, Timer};
use crate::ssh::{parse_container_status, SSHClient};
use clap::{Args, Subcommand};
use colored::*;
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::time::Instant;

#[derive(Args)]
pub struct ServicesCommand {
    #[command(subcommand)]
    command: ServicesSubcommand,
}

#[derive(Subcommand)]
enum ServicesSubcommand {
    /// Check service health status
    Health(HealthCommand),
    /// Get container status
    Status(StatusCommand),
    /// View container logs
    Logs(LogsCommand),
    /// Inspect container details
    Inspect(InspectCommand),
    /// Restart a container
    Restart(RestartCommand),
}

#[derive(Args)]
struct HealthCommand {
    /// Environment (production/stage/development)
    #[arg(long)]
    env: Option<String>,

    /// Specific service name
    #[arg(long)]
    service: Option<String>,

    /// Service type filter (core/mcp/all)
    #[arg(long, default_value = "all")]
    r#type: String,

    /// Output in JSON format
    #[arg(long)]
    json: bool,
}

#[derive(Args)]
struct StatusCommand {
    /// Environment (production/stage/development)
    #[arg(long)]
    env: Option<String>,

    /// Specific service name
    #[arg(long)]
    service: Option<String>,

    /// Service type filter (core/mcp/all)
    #[arg(long, default_value = "all")]
    r#type: String,

    /// Output in JSON format
    #[arg(long)]
    json: bool,
}

#[derive(Args)]
struct LogsCommand {
    /// Service name
    service: String,

    /// Environment (production/stage/development)
    #[arg(long)]
    env: Option<String>,

    /// Number of lines to show
    #[arg(long, default_value = "100")]
    tail: u32,

    /// Show logs since time (e.g., 10m, 1h, 2d)
    #[arg(long)]
    since: Option<String>,
}

#[derive(Args)]
struct InspectCommand {
    /// Service name
    service: String,

    /// Environment (production/stage/development)
    #[arg(long)]
    env: Option<String>,

    /// Output in JSON format
    #[arg(long)]
    json: bool,
}

#[derive(Args)]
struct RestartCommand {
    /// Service name
    service: String,

    /// Environment (production/stage/development)
    #[arg(long)]
    env: Option<String>,

    /// Skip confirmation
    #[arg(long, short)]
    yes: bool,
}

#[derive(Debug, Serialize, Deserialize)]
struct HealthResult {
    service: String,
    #[serde(rename = "type")]
    service_type: String,
    url: String,
    status: String,
    http_status: Option<u16>,
    response_time: String,
    container_status: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    error: Option<String>,
}

impl ServicesCommand {
    pub async fn execute(&self, config: &AppConfig) -> Result<()> {
        match &self.command {
            ServicesSubcommand::Health(cmd) => cmd.execute(config).await,
            ServicesSubcommand::Status(cmd) => cmd.execute(config).await,
            ServicesSubcommand::Logs(cmd) => cmd.execute(config).await,
            ServicesSubcommand::Inspect(cmd) => cmd.execute(config).await,
            ServicesSubcommand::Restart(cmd) => cmd.execute(config).await,
        }
    }
}

impl HealthCommand {
    async fn execute(&self, config: &AppConfig) -> Result<()> {
        let mut timer = Timer::new();

        let env = self
            .env
            .as_ref()
            .and_then(|e| Environment::from_str(e))
            .unwrap_or_else(|| config.get_environment());

        // 获取服务列表
        let services = if let Some(service_name) = &self.service {
            vec![config.get_service(service_name).ok_or_else(|| {
                crate::error::OpsCLIError::Validation(format!("未知服务: {}", service_name))
            })?]
        } else {
            match self.r#type.as_str() {
                "core" => config.get_services_by_type(ServiceType::Core),
                "mcp" => config.get_services_by_type(ServiceType::MCP),
                _ => config.get_all_services(),
            }
        };

        timer.step("加载配置");

        if !is_json_output() && !self.json {
            print_title(&format!("🏥 服务健康检查 - {} 环境", env.as_str()));
        }

        let mut results = Vec::new();
        let client = Client::builder()
            .timeout(std::time::Duration::from_secs(10))
            .build()?;

        // 检查每个服务
        for service in &services {
            let indicator = ProgressIndicator::new(&format!("检查 {}", service.name));
            let start_time = Instant::now();

            match client.get(&service.health_endpoint).send().await {
                Ok(response) => {
                    let response_time = start_time.elapsed();
                    let status_code = response.status().as_u16();

                    // MCP 服务的 404 也视为健康
                    let is_healthy = status_code == 200
                        || (matches!(service.service_type, ServiceType::MCP) && status_code == 404);

                    results.push(HealthResult {
                        service: service.name.clone(),
                        service_type: match service.service_type {
                            ServiceType::Core => "core".to_string(),
                            ServiceType::MCP => "mcp".to_string(),
                        },
                        url: service.health_endpoint.clone(),
                        status: if is_healthy {
                            "healthy".to_string()
                        } else {
                            "unhealthy".to_string()
                        },
                        http_status: Some(status_code),
                        response_time: format!("{}ms", response_time.as_millis()),
                        container_status: None,
                        error: None,
                    });

                    if is_healthy {
                        indicator.success(Some(&format!("{}ms", response_time.as_millis())));
                    } else {
                        indicator.error(Some(&format!("状态码: {}", status_code)));
                    }
                }
                Err(e) => {
                    let response_time = start_time.elapsed();
                    results.push(HealthResult {
                        service: service.name.clone(),
                        service_type: match service.service_type {
                            ServiceType::Core => "core".to_string(),
                            ServiceType::MCP => "mcp".to_string(),
                        },
                        url: service.health_endpoint.clone(),
                        status: "error".to_string(),
                        http_status: None,
                        response_time: format!("{}ms", response_time.as_millis()),
                        container_status: None,
                        error: Some(e.to_string()),
                    });

                    indicator.error(Some(&e.to_string()));
                }
            }
        }

        timer.step("健康检查");

        // 检查容器状态
        if !is_json_output() && !self.json {
            println!("\n{}", "检查容器状态...".white());
        }

        match SSHClient::new(config, Some(env)).get_container_status(None).await {
            Ok(result) => {
                let containers = parse_container_status(&result.stdout);
                for health_result in &mut results {
                    let container_name = format!(
                        "optima-{}-{}",
                        health_result.service,
                        if env == Environment::Production {
                            "prod"
                        } else {
                            env.as_str()
                        }
                    );

                    if let Some(container) = containers.iter().find(|c| c.name == container_name) {
                        health_result.container_status = Some(container.status.clone());
                    }
                }
            }
            Err(e) => {
                if !is_json_output() && !self.json {
                    println!("  {} 无法获取容器状态: {}", "⚠".yellow(), e);
                }
            }
        }

        timer.step("容器状态");

        // 输出结果
        if is_json_output() || self.json {
            let healthy_count = results.iter().filter(|r| r.status == "healthy").count();
            let unhealthy_count = results.iter().filter(|r| r.status == "unhealthy").count();
            let error_count = results.iter().filter(|r| r.status == "error").count();

            output_success(serde_json::json!({
                "environment": env.as_str(),
                "services": results,
                "summary": {
                    "total": results.len(),
                    "healthy": healthy_count,
                    "unhealthy": unhealthy_count,
                    "error": error_count,
                },
                "_timing": if crate::output::is_timing_enabled() {
                    Some(timer.get_timing_data())
                } else {
                    None
                }
            }))?;
        } else {
            println!("\n{}", "总结:".white());
            let healthy = results.iter().filter(|r| r.status == "healthy").count();
            let total = results.len();

            if healthy == total {
                println!("  {} 所有服务健康 ({}/{})", "✓".green(), healthy, total);
            } else {
                println!("  {} {}/{} 服务健康", "⚠".yellow(), healthy, total);
            }
            println!();

            timer.print_summary();
        }

        Ok(())
    }
}

impl StatusCommand {
    async fn execute(&self, config: &AppConfig) -> Result<()> {
        let env = self
            .env
            .as_ref()
            .and_then(|e| Environment::from_str(e))
            .unwrap_or_else(|| config.get_environment());

        // 获取服务列表
        let services = if let Some(service_name) = &self.service {
            vec![config.get_service(service_name).ok_or_else(|| {
                crate::error::OpsCLIError::Validation(format!("未知服务: {}", service_name))
            })?]
        } else {
            match self.r#type.as_str() {
                "core" => config.get_services_by_type(ServiceType::Core),
                "mcp" => config.get_services_by_type(ServiceType::MCP),
                _ => config.get_all_services(),
            }
        };

        if !is_json_output() && !self.json {
            print_title(&format!("📦 容器状态 - {} 环境", env.as_str()));
        }

        let mut ssh_client = SSHClient::new(config, Some(env));
        ssh_client.connect().await?;

        let result = ssh_client.get_container_status(None).await?;
        let containers = parse_container_status(&result.stdout);

        // 创建表格
        if !is_json_output() && !self.json {
            let mut table = create_table();
            table.set_header(vec!["服务", "状态", "容器名称", "端口"]);

            for service in &services {
                let container_name = format!(
                    "optima-{}-{}",
                    service.name,
                    if env == Environment::Production {
                        "prod"
                    } else {
                        env.as_str()
                    }
                );

                if let Some(container) = containers.iter().find(|c| c.name == container_name) {
                    table.add_row(vec![
                        &service.name,
                        &container.status,
                        &container.name,
                        &container.ports,
                    ]);
                } else {
                    table.add_row(vec![&service.name, "未找到", &container_name, "-"]);
                }
            }

            println!("{}\n", table);
        } else {
            let status_data: Vec<_> = services
                .iter()
                .map(|service| {
                    let container_name = format!(
                        "optima-{}-{}",
                        service.name,
                        if env == Environment::Production {
                            "prod"
                        } else {
                            env.as_str()
                        }
                    );

                    let container = containers.iter().find(|c| c.name == container_name);

                    serde_json::json!({
                        "service": service.name,
                        "type": match service.service_type {
                            ServiceType::Core => "core",
                            ServiceType::MCP => "mcp",
                        },
                        "container_name": container_name,
                        "status": container.map(|c| c.status.as_str()).unwrap_or("not_found"),
                        "ports": container.map(|c| c.ports.as_str()).unwrap_or(""),
                    })
                })
                .collect();

            output_success(serde_json::json!({
                "environment": env.as_str(),
                "containers": status_data,
            }))?;
        }

        Ok(())
    }
}

impl LogsCommand {
    async fn execute(&self, config: &AppConfig) -> Result<()> {
        let env = self
            .env
            .as_ref()
            .and_then(|e| Environment::from_str(e))
            .unwrap_or_else(|| config.get_environment());

        // 验证服务存在
        let _service = config.get_service(&self.service).ok_or_else(|| {
            crate::error::OpsCLIError::Validation(format!("未知服务: {}", self.service))
        })?;

        let container_name = format!(
            "optima-{}-{}",
            self.service,
            if env == Environment::Production {
                "prod"
            } else {
                env.as_str()
            }
        );

        print_title(&format!("📝 {} 容器日志 - {} 环境", self.service, env.as_str()));

        // 构建 docker logs 命令
        let mut command = format!("docker logs --tail {}", self.tail);

        if let Some(since) = &self.since {
            command.push_str(&format!(" --since {}", since));
        }

        command.push_str(&format!(" {}", container_name));

        println!("{}", format!("执行命令: {}", command).white());
        println!("{}", "─".repeat(80).white());

        let mut ssh_client = SSHClient::new(config, Some(env));
        ssh_client.connect().await?;

        let result = ssh_client.execute_command(&command, false, None).await?;

        if result.exit_code != 0 {
            println!("{}", format!("错误: {}", result.stderr).red());
            return Ok(());
        }

        if result.stdout.is_empty() {
            println!("{}", "没有日志输出".yellow());
        } else {
            println!("{}", result.stdout);
        }

        println!("{}", "─".repeat(80).white());
        println!("{}", format!("显示最后 {} 行", self.tail).white());

        if let Some(since) = &self.since {
            println!("{}", format!("时间范围: 最近 {}", since).white());
        }

        Ok(())
    }
}

impl InspectCommand {
    async fn execute(&self, config: &AppConfig) -> Result<()> {
        let env = self
            .env
            .as_ref()
            .and_then(|e| Environment::from_str(e))
            .unwrap_or_else(|| config.get_environment());

        // 验证服务存在
        let _service = config.get_service(&self.service).ok_or_else(|| {
            crate::error::OpsCLIError::Validation(format!("未知服务: {}", self.service))
        })?;

        let container_name = format!(
            "optima-{}-{}",
            self.service,
            if env == Environment::Production {
                "prod"
            } else {
                env.as_str()
            }
        );

        if !is_json_output() && !self.json {
            print_title(&format!("🔍 {} 容器详情 - {} 环境", self.service, env.as_str()));
        }

        let mut ssh_client = SSHClient::new(config, Some(env));
        ssh_client.connect().await?;

        let result = ssh_client
            .docker_command(&format!("inspect {}", container_name))
            .await?;

        if result.exit_code != 0 {
            return Err(crate::error::OpsCLIError::CommandExecution(format!(
                "容器不存在或无法访问: {}",
                container_name
            )));
        }

        if is_json_output() || self.json {
            // 直接输出 JSON
            println!("{}", result.stdout);
        } else {
            // 解析并显示关键信息
            if let Ok(inspect_data) = serde_json::from_str::<Vec<serde_json::Value>>(&result.stdout) {
                if let Some(container) = inspect_data.first() {
                    // 基本信息
                    println!("{}", "基本信息:".cyan().bold());
                    if let Some(id) = container.get("Id").and_then(|v| v.as_str()) {
                        println!("  ID: {}", &id[..12]);
                    }
                    if let Some(name) = container.get("Name").and_then(|v| v.as_str()) {
                        println!("  名称: {}", name.trim_start_matches('/'));
                    }
                    if let Some(created) = container.get("Created").and_then(|v| v.as_str()) {
                        println!("  创建时间: {}", created);
                    }

                    // 状态信息
                    if let Some(state) = container.get("State") {
                        println!("\n{}", "状态:".cyan().bold());
                        if let Some(status) = state.get("Status").and_then(|v| v.as_str()) {
                            let status_colored = if status == "running" {
                                status.green().to_string()
                            } else {
                                status.red().to_string()
                            };
                            println!("  状态: {}", status_colored);
                        }
                        if let Some(started) = state.get("StartedAt").and_then(|v| v.as_str()) {
                            println!("  启动时间: {}", started);
                        }
                    }

                    // 镜像信息
                    if let Some(image) = container.get("Config").and_then(|c| c.get("Image")).and_then(|v| v.as_str()) {
                        println!("\n{}", "镜像:".cyan().bold());
                        println!("  {}", image);
                    }

                    // 环境变量数量
                    if let Some(envs) = container.get("Config").and_then(|c| c.get("Env")).and_then(|v| v.as_array()) {
                        println!("\n{}", "环境变量:".cyan().bold());
                        println!("  共 {} 个", envs.len());
                    }

                    // 端口映射
                    if let Some(ports) = container.get("NetworkSettings").and_then(|n| n.get("Ports")) {
                        println!("\n{}", "端口映射:".cyan().bold());
                        if let Some(obj) = ports.as_object() {
                            for (port, bindings) in obj {
                                if let Some(bindings) = bindings.as_array() {
                                    for binding in bindings {
                                        if let Some(host_port) = binding.get("HostPort").and_then(|v| v.as_str()) {
                                            println!("  {} -> {}", host_port, port);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            } else {
                println!("{}", result.stdout);
            }
        }

        Ok(())
    }
}

impl RestartCommand {
    async fn execute(&self, config: &AppConfig) -> Result<()> {
        let env = self
            .env
            .as_ref()
            .and_then(|e| Environment::from_str(e))
            .unwrap_or_else(|| config.get_environment());

        // 验证服务存在
        let _service = config.get_service(&self.service).ok_or_else(|| {
            crate::error::OpsCLIError::Validation(format!("未知服务: {}", self.service))
        })?;

        let container_name = format!(
            "optima-{}-{}",
            self.service,
            if env == Environment::Production {
                "prod"
            } else {
                env.as_str()
            }
        );

        print_title(&format!("🔄 重启 {} - {} 环境", self.service, env.as_str()));

        // 确认操作
        if !self.yes {
            println!("{}", format!("即将重启容器: {}", container_name).yellow());
            println!("{}", "确认重启? [y/N]: ".white());

            use std::io::{self, BufRead};
            let stdin = io::stdin();
            let line = stdin.lock().lines().next().unwrap_or(Ok(String::new()))?;

            if !line.trim().eq_ignore_ascii_case("y") && !line.trim().eq_ignore_ascii_case("yes") {
                println!("{}", "已取消".yellow());
                return Ok(());
            }
        }

        let indicator = ProgressIndicator::new(&format!("重启 {}", container_name));

        let mut ssh_client = SSHClient::new(config, Some(env));
        ssh_client.connect().await?;

        let result = ssh_client
            .execute_command(&format!("docker restart {}", container_name), false, None)
            .await?;

        if result.exit_code == 0 {
            indicator.success(Some("重启成功"));
            println!("{}", format!("容器 {} 已重启", container_name).green());
        } else {
            indicator.error(Some(&result.stderr));
            return Err(crate::error::OpsCLIError::CommandExecution(format!(
                "重启失败: {}",
                result.stderr
            )));
        }

        Ok(())
    }
}
