//! logs 模块 - 日志查看和分析工具
//!
//! 提供以下功能:
//! - search: 在容器日志中搜索关键词
//! - errors: 查看错误日志并聚合分析
//! - tail: 查看容器日志尾部
//! - export: 导出容器日志到本地文件
//!
//! 支持 optima-core-py 的结构化 JSON 日志格式，包括 trace_id 追踪

use crate::config::{AppConfig, Environment, ServiceType};
use crate::error::Result;
use crate::output::{
    create_table, is_json_output, output_success, print_section, print_title, Timer,
};
use crate::ssh::SSHClient;
use anyhow::Context;
use clap::{Args, Subcommand};
use colored::Colorize;
use regex::Regex;
use serde::Serialize;
use serde_json::json;
use std::collections::HashMap;
use std::fs;
use std::path::PathBuf;

/// logs 命令
#[derive(Args)]
pub struct LogsCommand {
    #[command(subcommand)]
    command: LogsSubcommand,
}

#[derive(Subcommand)]
enum LogsSubcommand {
    /// 在容器日志中搜索关键词
    Search(SearchCommand),
    /// 查看错误日志并聚合分析
    Errors(ErrorsCommand),
    /// 查看容器日志尾部
    Tail(TailCommand),
    /// 导出容器日志到本地文件
    Export(ExportCommand),
    /// 按 trace_id 追踪跨服务调用链
    Trace(TraceCommand),
}

impl LogsCommand {
    pub async fn execute(&self, config: &AppConfig) -> Result<()> {
        match &self.command {
            LogsSubcommand::Search(cmd) => cmd.execute(config).await,
            LogsSubcommand::Errors(cmd) => cmd.execute(config).await,
            LogsSubcommand::Tail(cmd) => cmd.execute(config).await,
            LogsSubcommand::Export(cmd) => cmd.execute(config).await,
            LogsSubcommand::Trace(cmd) => cmd.execute(config).await,
        }
    }
}

// ============== Search 命令 ==============

#[derive(Args)]
struct SearchCommand {
    /// 搜索模式（支持正则表达式）
    pattern: String,

    /// 指定服务名称
    #[arg(long)]
    service: Option<String>,

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

    /// 时间范围 (如: 1h, 30m, 2d)
    #[arg(long, default_value = "1h")]
    since: String,

    /// 区分大小写
    #[arg(long)]
    case_sensitive: bool,

    /// 显示匹配行前后的上下文行数
    #[arg(long, short = 'C', default_value = "0")]
    context: u32,

    /// 服务类型 (core/mcp/all)
    #[arg(long, short = 't', default_value = "all")]
    r#type: String,

    /// 最大返回行数
    #[arg(long, default_value = "100")]
    limit: usize,

    /// JSON 格式输出
    #[arg(long)]
    json: bool,
}

#[derive(Debug, Serialize)]
struct LogMatch {
    service: String,
    line: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    line_number: Option<u32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    timestamp: Option<String>,
}

impl SearchCommand {
    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());

        if !is_json_output() && !self.json {
            let service_text = self
                .service
                .as_ref()
                .map(|s| format!(" - {}", s))
                .unwrap_or_else(|| " - 所有服务".to_string());
            print_title(&format!(
                "🔍 日志搜索{} ({} 环境)",
                service_text,
                env.as_str()
            ));
            println!("{}", format!("搜索模式: {}", self.pattern).bright_black());
            println!("{}", format!("时间范围: {}", self.since).bright_black());
            println!();
        }

        let mut ssh_client = SSHClient::new(config, Some(env));
        ssh_client.connect().await?;
        timer.step("SSH 连接");

        let mut matches: Vec<LogMatch> = Vec::new();

        // 获取要搜索的服务列表
        let services = self.get_services(config);

        for service in &services {
            if let Some(target) = &self.service {
                if &service.name != target {
                    continue;
                }
            }

            let container_name = get_container_name(&service.name, env);

            // 使用 docker logs 获取日志（不用管道符，因为 SSH 白名单禁止）
            // 限制最大行数避免传输过多数据
            let logs_cmd = format!(
                "docker logs {} --since {} --tail 5000 2>&1",
                container_name, self.since
            );

            match ssh_client.execute_command(&logs_cmd, true, None).await {
                Ok(result) => {
                    if !result.stdout.trim().is_empty() {
                        // 在 Rust 端做正则匹配
                        let pattern_regex = if self.case_sensitive {
                            Regex::new(&self.pattern)
                        } else {
                            Regex::new(&format!("(?i){}", self.pattern))
                        };

                        if let Ok(re) = pattern_regex {
                            let lines: Vec<&str> = result.stdout.lines().collect();
                            let context = self.context as usize;

                            for (i, line) in lines.iter().enumerate() {
                                if re.is_match(line) && matches.len() < self.limit {
                                    // 添加上下文行
                                    if context > 0 {
                                        // 前文
                                        let start = i.saturating_sub(context);
                                        for j in start..i {
                                            let timestamp = extract_timestamp(lines[j]);
                                            matches.push(LogMatch {
                                                service: service.name.clone(),
                                                line: lines[j].to_string(),
                                                line_number: Some((j + 1) as u32),
                                                timestamp,
                                            });
                                        }
                                    }

                                    // 匹配行
                                    let timestamp = extract_timestamp(line);
                                    matches.push(LogMatch {
                                        service: service.name.clone(),
                                        line: line.to_string(),
                                        line_number: Some((i + 1) as u32),
                                        timestamp,
                                    });

                                    // 后文
                                    if context > 0 {
                                        let end = (i + context + 1).min(lines.len());
                                        for j in (i + 1)..end {
                                            let timestamp = extract_timestamp(lines[j]);
                                            matches.push(LogMatch {
                                                service: service.name.clone(),
                                                line: lines[j].to_string(),
                                                line_number: Some((j + 1) as u32),
                                                timestamp,
                                            });
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                Err(_) => {
                    // 容器不存在或没有日志，继续
                }
            }
        }

        timer.step("搜索日志");

        // 输出结果
        if is_json_output() || self.json {
            output_success(json!({
                "environment": env.as_str(),
                "pattern": self.pattern,
                "service": self.service,
                "since": self.since,
                "matches": matches,
                "total_matches": matches.len(),
            }))?;
        } else {
            if matches.is_empty() {
                println!("{}", "未找到匹配的日志".yellow());
            } else {
                println!(
                    "{}",
                    format!("找到 {} 条匹配记录:\n", matches.len()).green()
                );

                let mut current_service = String::new();
                for m in &matches {
                    // 显示服务分隔
                    if m.service != current_service {
                        if !current_service.is_empty() {
                            println!();
                        }
                        current_service = m.service.clone();
                        println!("{}", format!("[{}]", m.service).cyan().bold());
                    }

                    // 高亮显示匹配的模式
                    let display_line = highlight_pattern(&m.line, &self.pattern, self.case_sensitive);

                    // 显示行号（如果有）
                    if let Some(num) = m.line_number {
                        println!(
                            "{}  {}",
                            format!("{}:", num).bright_black(),
                            display_line
                        );
                    } else {
                        println!("  {}", display_line);
                    }
                }
            }

            println!();
            println!("{}", "💡 提示:".bright_black());
            println!(
                "{}",
                "  - 使用 --context 3 显示匹配行前后 3 行上下文".bright_black()
            );
            println!(
                "{}",
                "  - 使用 --case-sensitive 进行区分大小写搜索".bright_black()
            );
            println!(
                "{}",
                "  - 使用 --since 2h 扩大时间范围".bright_black()
            );

            timer.print_summary();
        }

        Ok(())
    }

    fn get_services(&self, config: &AppConfig) -> Vec<crate::config::ServiceConfig> {
        match self.r#type.as_str() {
            "core" => config
                .get_services_by_type(ServiceType::Core)
                .into_iter()
                .cloned()
                .collect(),
            "mcp" => config
                .get_services_by_type(ServiceType::MCP)
                .into_iter()
                .cloned()
                .collect(),
            _ => config.get_all_services().into_iter().cloned().collect(),
        }
    }
}

// ============== Errors 命令 ==============

#[derive(Args)]
struct ErrorsCommand {
    /// 指定服务名称
    #[arg(long)]
    service: Option<String>,

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

    /// 时间范围 (如: 1h, 30m, 2d)
    #[arg(long, default_value = "1h")]
    since: String,

    /// 错误级别 (error/critical/warning)
    #[arg(long, default_value = "error")]
    level: String,

    /// 聚合相似错误
    #[arg(long)]
    aggregate: bool,

    /// 服务类型 (core/mcp/all)
    #[arg(long, short = 't', default_value = "all")]
    r#type: String,

    /// JSON 格式输出
    #[arg(long)]
    json: bool,
}

#[derive(Debug, Serialize, Clone)]
struct ErrorLog {
    service: String,
    level: String,
    message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    timestamp: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    line_number: Option<u32>,
}

#[derive(Debug, Serialize)]
struct ErrorAggregation {
    pattern: String,
    count: usize,
    #[serde(skip_serializing_if = "Option::is_none")]
    first_seen: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    last_seen: Option<String>,
    services: Vec<String>,
    sample_message: String,
}

impl ErrorsCommand {
    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());

        if !is_json_output() && !self.json {
            let service_text = self
                .service
                .as_ref()
                .map(|s| format!(" - {}", s))
                .unwrap_or_else(|| " - 所有服务".to_string());
            print_title(&format!(
                "🔴 错误日志{} ({} 环境)",
                service_text,
                env.as_str()
            ));
            println!("{}", format!("错误级别: {}", self.level).bright_black());
            println!("{}", format!("时间范围: {}", self.since).bright_black());
            println!();
        }

        let mut ssh_client = SSHClient::new(config, Some(env));
        ssh_client.connect().await?;
        timer.step("SSH 连接");

        let mut errors: Vec<ErrorLog> = Vec::new();

        // 根据级别构建搜索模式
        let search_pattern = match self.level.as_str() {
            "critical" => "CRITICAL|Critical|critical|FATAL|Fatal|fatal",
            "warning" => "WARNING|Warning|warning|WARN|Warn|warn",
            _ => "ERROR|Error|error|FATAL|Fatal|fatal",
        };

        // 获取要搜索的服务列表
        let services: Vec<_> = match self.r#type.as_str() {
            "core" => config
                .get_services_by_type(ServiceType::Core)
                .into_iter()
                .cloned()
                .collect(),
            "mcp" => config
                .get_services_by_type(ServiceType::MCP)
                .into_iter()
                .cloned()
                .collect(),
            _ => config.get_all_services().into_iter().cloned().collect(),
        };

        for service in &services {
            if let Some(target) = &self.service {
                if &service.name != target {
                    continue;
                }
            }

            let container_name = get_container_name(&service.name, env);

            // 使用 docker logs 获取日志（不用管道符，在 Rust 端过滤）
            let logs_cmd = format!(
                "docker logs {} --since {} --tail 5000 2>&1",
                container_name, self.since
            );

            match ssh_client.execute_command(&logs_cmd, true, None).await {
                Ok(result) => {
                    if !result.stdout.trim().is_empty() {
                        // 在 Rust 端做正则匹配
                        if let Ok(re) = Regex::new(&format!("(?i){}", search_pattern)) {
                            for (i, line) in result.stdout.lines().enumerate() {
                                if re.is_match(line) && errors.len() < 200 {
                                    // 提取时间戳和级别
                                    let timestamp = extract_timestamp(line);
                                    let level = extract_level(line).unwrap_or_else(|| self.level.to_uppercase());

                                    errors.push(ErrorLog {
                                        service: service.name.clone(),
                                        level,
                                        message: line.to_string(),
                                        timestamp,
                                        line_number: Some((i + 1) as u32),
                                    });
                                }
                            }
                        }
                    }
                }
                Err(_) => {
                    // 容器不存在或没有日志，继续
                }
            }
        }

        timer.step("搜索错误");

        // 聚合分析
        let aggregation = if self.aggregate && !errors.is_empty() {
            Some(aggregate_errors(&errors))
        } else {
            None
        };

        // 输出结果
        if is_json_output() || self.json {
            output_success(json!({
                "environment": env.as_str(),
                "service": self.service,
                "since": self.since,
                "errors": errors,
                "total_errors": errors.len(),
                "aggregation": aggregation,
            }))?;
        } else {
            if errors.is_empty() {
                println!("{}", "✓ 未发现错误日志".green());
            } else if let Some(agg) = &aggregation {
                print_section("错误聚合分析");
                println!(
                    "{}",
                    format!(
                        "发现 {} 种不同类型的错误 (共 {} 条):\n",
                        agg.len(),
                        errors.len()
                    )
                    .red()
                );

                for a in agg.iter().take(10) {
                    println!("{}", format!("[{}x] {}", a.count, a.services.join(", ")).yellow());
                    let truncated = if a.sample_message.len() > 150 {
                        format!("{}...", &a.sample_message[..150])
                    } else {
                        a.sample_message.clone()
                    };
                    println!("  {}", truncated.bright_black());
                    if let Some(first) = &a.first_seen {
                        let last = a.last_seen.as_deref().unwrap_or(first);
                        println!("  {}", format!("首次: {} | 最近: {}", first, last).bright_black());
                    }
                    println!();
                }

                if agg.len() > 10 {
                    println!("{}", format!("... 还有 {} 种错误类型", agg.len() - 10).bright_black());
                }
            } else {
                print_section("错误日志");
                println!(
                    "{}",
                    format!("发现 {} 条错误:\n", errors.len()).red()
                );

                let mut current_service = String::new();
                let max_errors = 50;

                for error in errors.iter().take(max_errors) {
                    if error.service != current_service {
                        if !current_service.is_empty() {
                            println!();
                        }
                        current_service = error.service.clone();
                        println!("{}", format!("[{}]", error.service).cyan().bold());
                    }

                    let level_color = match error.level.as_str() {
                        "CRITICAL" | "FATAL" => error.level.red().bold(),
                        "ERROR" => error.level.red(),
                        _ => error.level.yellow(),
                    };

                    let prefix = error
                        .line_number
                        .map(|n| format!("{}:", n).bright_black().to_string())
                        .unwrap_or_else(|| "  ".to_string());

                    let truncated = if error.message.len() > 150 {
                        format!("{}...", &error.message[..150])
                    } else {
                        error.message.clone()
                    };

                    println!("{} [{}] {}", prefix, level_color, truncated);
                }

                if errors.len() > max_errors {
                    println!();
                    println!(
                        "{}",
                        format!(
                            "... 还有 {} 条错误 (使用 --json 查看全部)",
                            errors.len() - max_errors
                        )
                        .bright_black()
                    );
                }
            }

            println!();
            println!("{}", "💡 提示:".bright_black());
            println!("{}", "  - 使用 --aggregate 聚合相似错误".bright_black());
            println!("{}", "  - 使用 --level critical 只看严重错误".bright_black());
            println!("{}", "  - 使用 --since 2h 扩大时间范围".bright_black());
            println!("{}", "  - 使用 logs search <pattern> 进行精确搜索".bright_black());

            timer.print_summary();
        }

        Ok(())
    }
}

// ============== Tail 命令 ==============

#[derive(Args)]
struct TailCommand {
    /// 服务名称
    service: String,

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

    /// 显示最后 N 行日志
    #[arg(long, default_value = "100")]
    tail: u32,

    /// 时间范围 (如: 1h, 30m, 2d)
    #[arg(long)]
    since: Option<String>,

    /// JSON 格式输出
    #[arg(long)]
    json: bool,
}

impl TailCommand {
    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());

        if !is_json_output() && !self.json {
            print_title(&format!(
                "📜 容器日志 - {} ({} 环境)",
                self.service,
                env.as_str()
            ));
            if let Some(since) = &self.since {
                println!("{}", format!("时间范围: {}", since).bright_black());
            }
            println!("{}", format!("显示行数: {}", self.tail).bright_black());
            println!();
        }

        let mut ssh_client = SSHClient::new(config, Some(env));
        ssh_client.connect().await?;
        timer.step("SSH 连接");

        let container_name = get_container_name(&self.service, env);

        // 构建 docker logs 命令
        let mut logs_cmd = format!("docker logs {} --tail {}", container_name, self.tail);
        if let Some(since) = &self.since {
            logs_cmd = format!("docker logs {} --since {} --tail {}", container_name, since, self.tail);
        }
        logs_cmd.push_str(" 2>&1");

        let result = ssh_client.execute_command(&logs_cmd, true, None).await?;
        timer.step("获取日志");

        let logs: Vec<&str> = result.stdout.lines().collect();

        // 输出结果
        if is_json_output() || self.json {
            output_success(json!({
                "environment": env.as_str(),
                "service": self.service,
                "lines": self.tail,
                "since": self.since,
                "logs": logs,
            }))?;
        } else {
            if logs.is_empty() {
                println!("{}", "暂无日志".yellow());
            } else {
                println!("{}", "─".repeat(80).bright_black());

                for line in &logs {
                    // 高亮不同级别的日志
                    if Regex::new(r"\b(ERROR|CRITICAL|FATAL)\b")
                        .ok()
                        .map(|re| re.is_match(line))
                        .unwrap_or(false)
                    {
                        println!("{}", line.red());
                    } else if Regex::new(r"\b(WARNING|WARN)\b")
                        .ok()
                        .map(|re| re.is_match(line))
                        .unwrap_or(false)
                    {
                        println!("{}", line.yellow());
                    } else if Regex::new(r"\bINFO\b")
                        .ok()
                        .map(|re| re.is_match(line))
                        .unwrap_or(false)
                    {
                        println!("{}", line.cyan());
                    } else if Regex::new(r"\bDEBUG\b")
                        .ok()
                        .map(|re| re.is_match(line))
                        .unwrap_or(false)
                    {
                        println!("{}", line.bright_black());
                    } else {
                        println!("{}", line);
                    }
                }

                println!("{}", "─".repeat(80).bright_black());
                println!(
                    "{}",
                    format!("\n显示了最后 {} 行日志", logs.len()).bright_black()
                );
            }

            println!();
            println!("{}", "💡 提示:".bright_black());
            println!("{}", "  - 使用 --tail 200 显示更多行数".bright_black());
            println!("{}", "  - 使用 --since 1h 限制时间范围".bright_black());
            println!("{}", "  - 使用 logs search <pattern> 搜索特定内容".bright_black());

            timer.print_summary();
        }

        Ok(())
    }
}

// ============== Export 命令 ==============

#[derive(Args)]
struct ExportCommand {
    /// 服务名称
    service: String,

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

    /// 输出文件路径
    #[arg(long, short = 'o')]
    output: Option<PathBuf>,

    /// 时间范围 (如: 1h, 30m, 2d)
    #[arg(long, default_value = "24h")]
    since: String,

    /// 只导出最后 N 行
    #[arg(long)]
    tail: Option<u32>,

    /// 输出格式 (text/json)
    #[arg(long, default_value = "text")]
    format: String,

    /// JSON 格式输出命令结果
    #[arg(long)]
    json: bool,
}

impl ExportCommand {
    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 timestamp = chrono::Local::now().format("%Y-%m-%dT%H-%M-%S").to_string();
        let default_output = PathBuf::from(format!(
            "logs/{}-{}-{}.log",
            self.service,
            env.as_str(),
            timestamp
        ));
        let output_file = self.output.clone().unwrap_or(default_output);

        // 确保 logs 目录存在
        if let Some(parent) = output_file.parent() {
            fs::create_dir_all(parent).context("无法创建日志目录")?;
        }

        if !is_json_output() && !self.json {
            print_title(&format!(
                "💾 导出日志 - {} ({} 环境)",
                self.service,
                env.as_str()
            ));
            println!("{}", format!("时间范围: {}", self.since).bright_black());
            println!(
                "{}",
                format!("输出文件: {}", output_file.display()).bright_black()
            );
            println!();
        }

        let mut ssh_client = SSHClient::new(config, Some(env));
        ssh_client.connect().await?;
        timer.step("SSH 连接");

        let container_name = get_container_name(&self.service, env);

        // 构建 docker logs 命令
        let mut logs_cmd = format!("docker logs {} --since {} 2>&1", container_name, self.since);
        if let Some(tail) = self.tail {
            logs_cmd = format!(
                "docker logs {} --since {} --tail {} 2>&1",
                container_name, self.since, tail
            );
        }

        let result = ssh_client.execute_command(&logs_cmd, true, None).await?;
        timer.step("获取日志");

        if result.stdout.trim().is_empty() {
            return Err(anyhow::anyhow!("没有日志可导出").into());
        }

        let log_lines: Vec<&str> = result.stdout.lines().collect();
        let lines_count = log_lines.len();

        // 根据格式写入文件
        let content = if self.format == "json" {
            // JSON 格式
            let json_logs: Vec<serde_json::Value> = log_lines
                .iter()
                .enumerate()
                .map(|(i, line)| {
                    let timestamp = extract_timestamp(line);
                    let level = extract_level(line).unwrap_or_else(|| "UNKNOWN".to_string());
                    json!({
                        "line_number": i + 1,
                        "timestamp": timestamp,
                        "level": level,
                        "message": line,
                    })
                })
                .collect();

            serde_json::to_string_pretty(&json!({
                "service": self.service,
                "environment": env.as_str(),
                "exported_at": chrono::Utc::now().to_rfc3339(),
                "since": self.since,
                "total_lines": lines_count,
                "logs": json_logs,
            }))
            .context("无法序列化 JSON")?
        } else {
            // Text 格式
            let header = format!(
                "# Optima Ops CLI - Log Export\n\
                 # Service: {}\n\
                 # Environment: {}\n\
                 # Exported at: {}\n\
                 # Since: {}\n\
                 # Total lines: {}\n\
                 # ────────────────────────────────────────────────────────────────\n\n",
                self.service,
                env.as_str(),
                chrono::Utc::now().to_rfc3339(),
                self.since,
                lines_count
            );
            format!("{}{}", header, result.stdout)
        };

        fs::write(&output_file, &content).context("无法写入日志文件")?;
        timer.step("写入文件");

        // 获取文件大小
        let metadata = fs::metadata(&output_file)?;
        let file_size = if metadata.len() < 1024 * 1024 {
            format!("{:.2} KB", metadata.len() as f64 / 1024.0)
        } else {
            format!("{:.2} MB", metadata.len() as f64 / 1024.0 / 1024.0)
        };

        // 输出结果
        if is_json_output() || self.json {
            output_success(json!({
                "environment": env.as_str(),
                "service": self.service,
                "output_file": output_file.to_string_lossy(),
                "lines_exported": lines_count,
                "file_size": file_size,
                "since": self.since,
            }))?;
        } else {
            println!("{}", "✓ 日志导出成功!\n".green());
            println!("{}", "导出信息:".cyan());
            println!(
                "  {}: {}",
                "文件".bright_black(),
                output_file.display()
            );
            println!(
                "  {}: {}",
                "行数".bright_black(),
                lines_count.to_string().green()
            );
            println!("  {}: {}", "大小".bright_black(), file_size);
            println!("  {}: {}", "格式".bright_black(), self.format);

            println!();
            println!("{}", "💡 提示:".bright_black());
            println!("{}", "  - 使用 --format json 导出为 JSON 格式".bright_black());
            println!("{}", "  - 使用 --tail 1000 只导出最后 1000 行".bright_black());
            println!("{}", "  - 使用 --since 7d 导出最近 7 天的日志".bright_black());
            println!(
                "{}",
                format!("  - 查看文件: cat {}", output_file.display()).bright_black()
            );

            timer.print_summary();
        }

        Ok(())
    }
}

// ============== Trace 命令 (新增 - 利用 optima-core-py 的 trace_id) ==============

#[derive(Args)]
struct TraceCommand {
    /// Trace ID（跨服务追踪标识）
    trace_id: String,

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

    /// 时间范围 (如: 1h, 30m, 2d)
    #[arg(long, default_value = "1h")]
    since: String,

    /// JSON 格式输出
    #[arg(long)]
    json: bool,
}

#[derive(Debug, Serialize)]
struct TraceLog {
    service: String,
    timestamp: Option<String>,
    level: String,
    message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    request_id: Option<String>,
}

impl TraceCommand {
    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());

        if !is_json_output() && !self.json {
            print_title(&format!(
                "🔗 追踪调用链 ({} 环境)",
                env.as_str()
            ));
            println!("{}", format!("Trace ID: {}", self.trace_id).cyan());
            println!("{}", format!("时间范围: {}", self.since).bright_black());
            println!();
        }

        let mut ssh_client = SSHClient::new(config, Some(env));
        ssh_client.connect().await?;
        timer.step("SSH 连接");

        let mut trace_logs: Vec<TraceLog> = Vec::new();

        // 在所有服务中搜索 trace_id
        let services = config.get_all_services();

        for service in &services {
            let container_name = get_container_name(&service.name, env);

            // 使用 docker logs 获取日志（不用管道符，在 Rust 端过滤）
            let logs_cmd = format!(
                "docker logs {} --since {} --tail 5000 2>&1",
                container_name, self.since
            );

            match ssh_client.execute_command(&logs_cmd, true, None).await {
                Ok(result) => {
                    if !result.stdout.trim().is_empty() {
                        let trace_id_lower = self.trace_id.to_lowercase();
                        for line in result.stdout.lines() {
                            // 在 Rust 端匹配 trace_id
                            if line.to_lowercase().contains(&trace_id_lower) {
                                // 尝试解析 JSON 日志
                                if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(line) {
                                    trace_logs.push(TraceLog {
                                        service: service.name.clone(),
                                        timestamp: parsed["timestamp"].as_str().map(|s| s.to_string()),
                                        level: parsed["level"]
                                            .as_str()
                                            .unwrap_or("INFO")
                                            .to_string(),
                                        message: parsed["message"]
                                            .as_str()
                                            .unwrap_or(line)
                                            .to_string(),
                                        request_id: parsed["request_id"].as_str().map(|s| s.to_string()),
                                    });
                                } else {
                                    // 非 JSON 格式的日志
                                    trace_logs.push(TraceLog {
                                        service: service.name.clone(),
                                        timestamp: extract_timestamp(line),
                                        level: extract_level(line).unwrap_or_else(|| "INFO".to_string()),
                                        message: line.to_string(),
                                        request_id: None,
                                    });
                                }
                            }
                        }
                    }
                }
                Err(_) => {
                    // 容器不存在或没有日志，继续
                }
            }
        }

        timer.step("搜索日志");

        // 按时间排序
        trace_logs.sort_by(|a, b| {
            let ts_a = a.timestamp.as_deref().unwrap_or("");
            let ts_b = b.timestamp.as_deref().unwrap_or("");
            ts_a.cmp(ts_b)
        });

        // 输出结果
        if is_json_output() || self.json {
            output_success(json!({
                "environment": env.as_str(),
                "trace_id": self.trace_id,
                "since": self.since,
                "logs": trace_logs,
                "services_involved": trace_logs.iter().map(|l| &l.service).collect::<std::collections::HashSet<_>>(),
                "total_logs": trace_logs.len(),
            }))?;
        } else {
            if trace_logs.is_empty() {
                println!("{}", format!("未找到 trace_id: {} 的日志", self.trace_id).yellow());
            } else {
                // 统计涉及的服务
                let services_involved: std::collections::HashSet<_> =
                    trace_logs.iter().map(|l| &l.service).collect();

                println!(
                    "{}",
                    format!(
                        "找到 {} 条日志，涉及 {} 个服务:\n",
                        trace_logs.len(),
                        services_involved.len()
                    )
                    .green()
                );

                // 显示调用链
                let mut table = create_table();
                table.set_header(vec!["时间", "服务", "级别", "消息"]);

                for log in &trace_logs {
                    let timestamp = log.timestamp.as_deref().unwrap_or("-");
                    let level_display = match log.level.as_str() {
                        "ERROR" | "CRITICAL" | "FATAL" => log.level.red().to_string(),
                        "WARNING" | "WARN" => log.level.yellow().to_string(),
                        "INFO" => log.level.cyan().to_string(),
                        _ => log.level.bright_black().to_string(),
                    };

                    let truncated_msg = if log.message.len() > 60 {
                        format!("{}...", &log.message[..60])
                    } else {
                        log.message.clone()
                    };

                    table.add_row(vec![timestamp, &log.service, &level_display, &truncated_msg]);
                }

                println!("{}\n", table);
            }

            println!("{}", "💡 提示:".bright_black());
            println!("{}", "  - Trace ID 由 optima-core 在入口服务自动生成".bright_black());
            println!("{}", "  - 使用 --since 2h 扩大时间范围".bright_black());
            println!("{}", "  - 使用 --json 查看完整日志内容".bright_black());

            timer.print_summary();
        }

        Ok(())
    }
}

// ============== 辅助函数 ==============

/// 获取容器名称
fn get_container_name(service: &str, env: Environment) -> String {
    match env {
        Environment::Production => format!("optima-{}-prod", service),
        Environment::Stage => format!("optima-{}-stage", service),
        Environment::Shared => format!("optima-{}-shared", service),
        Environment::Development => format!("optima-{}-dev", service),
    }
}

/// 提取时间戳
fn extract_timestamp(line: &str) -> Option<String> {
    // 匹配常见的时间戳格式
    let patterns = [
        r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z?",  // ISO 8601
        r"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}",           // 简单格式
    ];

    for pattern in &patterns {
        if let Ok(re) = Regex::new(pattern) {
            if let Some(caps) = re.captures(line) {
                return caps.get(0).map(|m| m.as_str().to_string());
            }
        }
    }
    None
}

/// 提取日志级别
fn extract_level(line: &str) -> Option<String> {
    let re = Regex::new(r"\b(ERROR|CRITICAL|WARNING|WARN|INFO|DEBUG|FATAL)\b").ok()?;
    re.captures(line)
        .and_then(|caps| caps.get(1))
        .map(|m| m.as_str().to_uppercase())
}

/// 高亮显示匹配的模式
fn highlight_pattern(line: &str, pattern: &str, case_sensitive: bool) -> String {
    let flags = if case_sensitive { "" } else { "(?i)" };
    if let Ok(re) = Regex::new(&format!("{}{}", flags, regex::escape(pattern))) {
        re.replace_all(line, |caps: &regex::Captures| {
            caps[0].yellow().bold().to_string()
        })
        .to_string()
    } else {
        line.to_string()
    }
}

/// 聚合相似错误
fn aggregate_errors(errors: &[ErrorLog]) -> Vec<ErrorAggregation> {
    let mut aggregation_map: HashMap<String, ErrorAggregation> = HashMap::new();

    for error in errors {
        // 标准化错误消息（去除动态内容）
        let normalized = normalize_error_message(&error.message);

        if let Some(existing) = aggregation_map.get_mut(&normalized) {
            existing.count += 1;
            existing.last_seen = error.timestamp.clone().or(existing.last_seen.clone());
            if !existing.services.contains(&error.service) {
                existing.services.push(error.service.clone());
            }
        } else {
            aggregation_map.insert(
                normalized.clone(),
                ErrorAggregation {
                    pattern: normalized,
                    count: 1,
                    first_seen: error.timestamp.clone(),
                    last_seen: error.timestamp.clone(),
                    services: vec![error.service.clone()],
                    sample_message: error.message.clone(),
                },
            );
        }
    }

    let mut result: Vec<_> = aggregation_map.into_values().collect();
    result.sort_by(|a, b| b.count.cmp(&a.count));
    result
}

/// 标准化错误消息（去除动态内容）
fn normalize_error_message(message: &str) -> String {
    let mut normalized = message.to_string();

    // 替换时间戳
    if let Ok(re) = Regex::new(r"\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}:\d{2}(\.\d+)?") {
        normalized = re.replace_all(&normalized, "<TIMESTAMP>").to_string();
    }

    // 替换 UUID
    if let Ok(re) =
        Regex::new(r"\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b")
    {
        normalized = re.replace_all(&normalized, "<UUID>").to_string();
    }

    // 替换数字
    if let Ok(re) = Regex::new(r"\b\d+\b") {
        normalized = re.replace_all(&normalized, "<NUM>").to_string();
    }

    // 截断到合理长度
    if normalized.len() > 200 {
        normalized.truncate(200);
    }

    normalized
}
