use tracing_appender::non_blocking::WorkerGuard;
use tracing_appender::rolling;
use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};

/// Logging utility class
///
/// # Example
/// ```rust
/// #[cfg(test)]
/// mod tests {
///     use mitoo::LogUtil;
///     use tracing::{error, info, warn};
///     #[test]
///     fn it_works() {
///         // Please note that you must keep the log flush guard until the process ends.
///         // Otherwise, the log may not be written to the file properly, but this will not affect the console output.
///         let _guard = LogUtil::init("./logs", "app.log", "info");
///         info!("info msg");
///         error!("error msg");
///         warn!("warn msg");
///     }
/// }
/// ```
pub struct LogUtil;

impl LogUtil {
    /// 初始化日志记录器，将日志记录到文件和控制台，此方法返回日志刷新守卫，
    /// 它需要在日志写入期间保持存活（即不被提前销毁），否则日志可能无法正确写入文件
    pub fn init(directory: &str, file_name_prefix: &str, level: &str) -> WorkerGuard {
        // 1. 配置文件输出（按天滚动）
        let file_appender = rolling::daily(directory, file_name_prefix);
        let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); // 非阻塞写入
        let file_timer = fmt::time::ChronoLocal::new("%Y-%m-%dT%H:%M:%S.%f%Z".to_string());
        let console_timer = fmt::time::ChronoLocal::new("%Y-%m-%dT%H:%M:%S.%f%Z".to_string());
        let file_layer = fmt::layer()
            .with_writer(non_blocking)
            .with_ansi(false)
            .with_timer(file_timer)
            .with_level(true)
            .with_target(true)
            .with_line_number(true)
            .with_thread_names(true);

        // 2.配置控制台输出（带颜色）
        let console_layer = fmt::layer()
            .with_ansi(true) // 控制台启用颜色
            .with_level(true)
            .with_timer(console_timer)
            .with_target(true)
            .with_line_number(true);

        // 3. 配置日志过滤（通过环境变量 RUST_LOG 控制，默认 info 级别）
        let env_filter = EnvFilter::try_from_default_env()
            .unwrap_or_else(|_| EnvFilter::new(level));

        tracing_subscriber::registry()
            .with(env_filter)
            .with(console_layer)
            .with(file_layer)
            .init();
        guard
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use tracing::{error, info, warn};
    #[test]
    fn it_works() {
        let _guard = LogUtil::init("./logs", "app.log", "info");
        info!("info msg1");
        error!("error msg1");
        warn!("warn msg1");
    }
}
