use colored::*;
use comfy_table::{modifiers::UTF8_ROUND_CORNERS, presets::UTF8_FULL, Table};
use regex::Regex;
use serde::Serialize;
use std::io::Write;

pub fn is_json_output() -> bool {
    std::env::var("OPTIMA_OUTPUT").map(|v| v == "json").unwrap_or(false)
}

pub fn print_title(title: &str) {
    println!("\n{}\n", title.cyan().bold());
}

pub fn print_section(title: &str) {
    println!("{}", title.white().bold());
}

pub fn output_success<T: Serialize>(data: T) -> anyhow::Result<()> {
    let output = serde_json::json!({
        "success": true,
        "data": data
    });

    println!("{}", serde_json::to_string_pretty(&output)?);
    Ok(())
}

pub fn output_error(message: &str) -> anyhow::Result<()> {
    let output = serde_json::json!({
        "success": false,
        "error": {
            "message": message
        }
    });

    println!("{}", serde_json::to_string_pretty(&output)?);
    Ok(())
}

pub fn create_table() -> Table {
    let mut table = Table::new();
    table
        .load_preset(UTF8_FULL)
        .apply_modifier(UTF8_ROUND_CORNERS);
    table
}

pub fn mask_sensitive(text: &str) -> String {
    let patterns = vec![
        // 密码
        (r"password[=:](\S+)", "password=***"),
        (r"PASSWORD[=:](\S+)", "PASSWORD=***"),
        // Token
        (r"token[=:](\S+)", "token=***"),
        (r"TOKEN[=:](\S+)", "TOKEN=***"),
        // API 密钥
        (r"api[_-]?key[=:](\S+)", "api_key=***"),
        (r"API[_-]?KEY[=:](\S+)", "API_KEY=***"),
        // AWS 密钥
        (r"AKIA[A-Z0-9]{16}", "AKIA***"),
        (r"aws[_-]?secret[=:](\S+)", "aws_secret=***"),
        // 数据库连接字符串
        (
            r"(postgresql://[^:]+:)([^@]+)(@)",
            "$1***$3",
        ),
        (r"(mysql://[^:]+:)([^@]+)(@)", "$1***$3"),
    ];

    let mut result = text.to_string();
    for (pattern, replacement) in patterns {
        if let Ok(re) = Regex::new(pattern) {
            result = re.replace_all(&result, replacement).to_string();
        }
    }

    result
}

pub struct ProgressIndicator {
    message: String,
}

impl ProgressIndicator {
    pub fn new(message: &str) -> Self {
        if !is_json_output() {
            print!("{}... ", message);
            std::io::stdout().flush().unwrap();
        }

        Self {
            message: message.to_string(),
        }
    }

    pub fn success(&self, detail: Option<&str>) {
        if !is_json_output() {
            if let Some(d) = detail {
                println!("{} ({})", "✓".green().bold(), d);
            } else {
                println!("{}", "✓".green().bold());
            }
        }
    }

    pub fn error(&self, detail: Option<&str>) {
        if !is_json_output() {
            if let Some(d) = detail {
                println!("{} {}", "✗".red().bold(), d);
            } else {
                println!("{}", "✗".red().bold());
            }
        }
    }
}

#[derive(Debug, Clone)]
pub struct Timer {
    start: std::time::Instant,
    steps: Vec<(String, std::time::Duration)>,
}

impl Timer {
    pub fn new() -> Self {
        Self {
            start: std::time::Instant::now(),
            steps: Vec::new(),
        }
    }

    pub fn step(&mut self, name: &str) {
        let duration = self.start.elapsed();
        self.steps.push((name.to_string(), duration));
        self.start = std::time::Instant::now();
    }

    pub fn print_summary(&self) {
        if !is_timing_enabled() || is_json_output() {
            return;
        }

        println!("\n{}", "⏱️  执行时间:".cyan());

        let mut total = std::time::Duration::ZERO;
        for (name, duration) in &self.steps {
            println!("  {}: {:.2}s", name, duration.as_secs_f64());
            total += *duration;
        }

        println!("  {}: {:.2}s", "总计".bold(), total.as_secs_f64());
    }

    pub fn get_timing_data(&self) -> serde_json::Value {
        serde_json::json!({
            "steps": self.steps.iter().map(|(name, duration)| {
                serde_json::json!({
                    "name": name,
                    "duration_ms": duration.as_millis()
                })
            }).collect::<Vec<_>>(),
            "total_ms": self.steps.iter().map(|(_, d)| d.as_millis()).sum::<u128>()
        })
    }
}

pub fn is_timing_enabled() -> bool {
    std::env::var("OPTIMA_TIMING").map(|v| v == "1").unwrap_or(false)
}
