use std::path::PathBuf;
use tracing::{info, warn, error, debug, Level};
use tracing_subscriber::{
    fmt::{self, time::ChronoUtc},
    layer::SubscriberExt,
    util::SubscriberInitExt,
    EnvFilter,
};
use std::fs;

/// 日志配置
#[derive(Debug, Clone)]
pub struct LogConfig {
    pub level: Level,
    pub log_to_file: bool,
    pub log_file_path: Option<PathBuf>,
    pub max_file_size: u64, // MB
    pub max_files: usize,
    pub include_timestamps: bool,
    pub include_thread_ids: bool,
    pub include_targets: bool,
}

impl Default for LogConfig {
    fn default() -> Self {
        Self {
            level: Level::INFO,
            log_to_file: true,
            log_file_path: None,
            max_file_size: 10, // 10MB
            max_files: 5,
            include_timestamps: true,
            include_thread_ids: false,
            include_targets: true,
        }
    }
}

/// 初始化日志系统
pub fn init_logging(config: LogConfig) -> Result<(), Box<dyn std::error::Error>> {
    let env_filter = EnvFilter::from_default_env()
        .add_directive(format!("mixvideo_desktop={}", config.level).parse()?);

    let fmt_layer = fmt::layer()
        .with_timer(ChronoUtc::rfc_3339())
        .with_target(config.include_targets)
        .with_thread_ids(config.include_thread_ids)
        .with_ansi(false); // 禁用 ANSI 颜色代码，适合文件输出

    if config.log_to_file {
        let log_file_path = config.log_file_path.clone().unwrap_or_else(|| {
            get_default_log_path()
        });

        // 确保日志目录存在
        if let Some(parent) = log_file_path.parent() {
            fs::create_dir_all(parent)?;
        }

        // 清理旧日志文件
        cleanup_old_logs(&log_file_path, config.max_files)?;

        let file_appender = tracing_appender::rolling::daily(
            log_file_path.parent().unwrap(),
            log_file_path.file_name().unwrap()
        );

        // 同时输出到控制台和文件
        let console_layer = fmt::layer()
            .with_timer(ChronoUtc::rfc_3339())
            .with_target(config.include_targets)
            .with_thread_ids(config.include_thread_ids)
            .with_ansi(true); // 控制台启用颜色

        let file_layer = fmt::layer()
            .with_timer(ChronoUtc::rfc_3339())
            .with_target(config.include_targets)
            .with_thread_ids(config.include_thread_ids)
            .with_ansi(false)
            .with_writer(file_appender);

        tracing_subscriber::registry()
            .with(env_filter)
            .with(console_layer)
            .with(file_layer)
            .init();
    } else {
        tracing_subscriber::registry()
            .with(env_filter)
            .with(fmt_layer)
            .init();
    }

    info!("日志系统初始化完成");
    info!("日志级别: {:?}", config.level);
    if config.log_to_file {
        info!("日志文件路径: {:?}", config.log_file_path);
    }

    Ok(())
}

/// 获取默认日志文件路径
fn get_default_log_path() -> PathBuf {
    let app_data_dir = dirs::data_dir()
        .unwrap_or_else(|| PathBuf::from("."))
        .join("mixvideo");
    
    app_data_dir.join("logs").join("app.log")
}

/// 清理旧日志文件
fn cleanup_old_logs(log_path: &PathBuf, max_files: usize) -> Result<(), Box<dyn std::error::Error>> {
    if let Some(log_dir) = log_path.parent() {
        if log_dir.exists() {
            let mut log_files: Vec<_> = fs::read_dir(log_dir)?
                .filter_map(|entry| {
                    let entry = entry.ok()?;
                    let path = entry.path();
                    if path.is_file() && path.extension().map_or(false, |ext| ext == "log") {
                        Some((path, entry.metadata().ok()?.modified().ok()?))
                    } else {
                        None
                    }
                })
                .collect();

            // 按修改时间排序，最新的在前
            log_files.sort_by(|a, b| b.1.cmp(&a.1));

            // 删除超出限制的文件
            for (path, _) in log_files.iter().skip(max_files) {
                if let Err(e) = fs::remove_file(path) {
                    warn!("删除旧日志文件失败: {:?} - {}", path, e);
                }
            }
        }
    }
    Ok(())
}

/// 日志宏扩展
#[macro_export]
macro_rules! log_operation {
    ($level:ident, $operation:expr, $($arg:tt)*) => {
        tracing::$level!(
            operation = $operation,
            $($arg)*
        );
    };
}

#[macro_export]
macro_rules! log_performance {
    ($operation:expr, $duration:expr, $success:expr) => {
        if $success {
            tracing::info!(
                operation = $operation,
                duration_ms = $duration.as_millis(),
                status = "success",
                "操作完成"
            );
        } else {
            tracing::warn!(
                operation = $operation,
                duration_ms = $duration.as_millis(),
                status = "failed",
                "操作失败"
            );
        }
    };
}

#[macro_export]
macro_rules! log_error_with_context {
    ($error:expr, $context:expr) => {
        tracing::error!(
            error = %$error,
            context = $context,
            "错误发生"
        );
    };
    ($error:expr, $context:expr, $($field:tt)*) => {
        tracing::error!(
            error = %$error,
            context = $context,
            $($field)*,
            "错误发生"
        );
    };
}

/// 结构化日志记录器
pub struct StructuredLogger;

impl StructuredLogger {
    /// 记录用户操作
    pub fn log_user_action(action: &str, user_id: Option<&str>, details: Option<&str>) {
        info!(
            action = action,
            user_id = user_id.unwrap_or("anonymous"),
            details = details.unwrap_or(""),
            "用户操作"
        );
    }

    /// 记录系统事件
    pub fn log_system_event(event: &str, component: &str, details: Option<&str>) {
        info!(
            event = event,
            component = component,
            details = details.unwrap_or(""),
            "系统事件"
        );
    }

    /// 记录性能指标
    pub fn log_performance_metric(metric_name: &str, value: f64, unit: &str) {
        info!(
            metric = metric_name,
            value = value,
            unit = unit,
            "性能指标"
        );
    }

    /// 记录错误详情
    pub fn log_error_details(
        error: &dyn std::error::Error,
        operation: &str,
        file_path: Option<&str>,
        additional_context: Option<&str>,
    ) {
        error!(
            error = %error,
            operation = operation,
            file_path = file_path.unwrap_or(""),
            context = additional_context.unwrap_or(""),
            "详细错误信息"
        );
    }

    /// 记录安全事件
    pub fn log_security_event(event_type: &str, severity: &str, details: &str) {
        warn!(
            event_type = event_type,
            severity = severity,
            details = details,
            "安全事件"
        );
    }

    /// 记录数据库操作
    pub fn log_database_operation(operation: &str, table: &str, duration: std::time::Duration, success: bool) {
        if success {
            debug!(
                operation = operation,
                table = table,
                duration_ms = duration.as_millis(),
                "数据库操作成功"
            );
        } else {
            warn!(
                operation = operation,
                table = table,
                duration_ms = duration.as_millis(),
                "数据库操作失败"
            );
        }
    }

    /// 记录文件操作
    pub fn log_file_operation(operation: &str, file_path: &str, file_size: Option<u64>, success: bool) {
        if success {
            info!(
                operation = operation,
                file_path = file_path,
                file_size = file_size.unwrap_or(0),
                "文件操作成功"
            );
        } else {
            error!(
                operation = operation,
                file_path = file_path,
                "文件操作失败"
            );
        }
    }
}

/// 日志级别辅助函数
pub fn set_log_level(_level: Level) {
    // 注意：tracing 不支持运行时动态修改日志级别
    // 这里提供接口，实际实现可能需要重新初始化
    warn!("动态修改日志级别功能需要重新初始化日志系统");
}

/// 获取当前日志配置
pub fn get_log_config() -> LogConfig {
    // 返回当前配置，实际实现中应该从配置文件或环境变量读取
    LogConfig::default()
}

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

    #[test]
    fn test_log_config_default() {
        let config = LogConfig::default();
        assert_eq!(config.level, Level::INFO);
        assert!(config.log_to_file);
        assert_eq!(config.max_file_size, 10);
        assert_eq!(config.max_files, 5);
    }

    #[test]
    fn test_get_default_log_path() {
        let path = get_default_log_path();
        assert!(path.to_string_lossy().contains("mixvideo"));
        assert!(path.to_string_lossy().contains("logs"));
        assert!(path.to_string_lossy().contains("app.log"));
    }

    #[test]
    fn test_cleanup_old_logs() {
        let temp_dir = tempdir().unwrap();
        let log_path = temp_dir.path().join("test.log");
        
        // 创建一些测试日志文件
        for i in 0..10 {
            let file_path = temp_dir.path().join(format!("test_{}.log", i));
            std::fs::write(&file_path, "test log content").unwrap();
        }

        let result = cleanup_old_logs(&log_path, 5);
        assert!(result.is_ok());

        // 检查文件数量
        let remaining_files = std::fs::read_dir(temp_dir.path())
            .unwrap()
            .filter(|entry| {
                entry.as_ref().unwrap().path().extension()
                    .map_or(false, |ext| ext == "log")
            })
            .count();
        
        assert!(remaining_files <= 5);
    }
}
