use crate::Result;
use tracing::Level;
use tracing_subscriber::{EnvFilter, fmt, prelude::*};

#[derive(Clone, Debug, Default)]
pub struct LogConfig {
    pub quiet: bool,
    pub debug: bool,
    pub json: bool,
    pub verbosity: u8,
}

impl LogConfig {
    pub fn level(&self) -> Level {
        if self.quiet {
            return Level::ERROR;
        }
        if self.debug {
            return Level::DEBUG;
        }
        match self.verbosity {
            0 => Level::INFO,
            1 => Level::DEBUG,
            _ => Level::TRACE,
        }
    }
}

pub fn init_logging(cfg: &LogConfig) -> Result<()> {
    let level = cfg.level();

    let env_filter =
        EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(level.to_string()));

    let registry = tracing_subscriber::registry().with(env_filter);

    let init_result = if cfg.json {
        registry
            .with(
                fmt::layer()
                    .with_target(false)
                    .with_level(true)
                    .with_ansi(atty::is(atty::Stream::Stdout))
                    .with_timer(fmt::time::SystemTime)
                    .json(),
            )
            .try_init()
    } else {
        registry
            .with(
                fmt::layer()
                    .with_target(false)
                    .with_level(true)
                    .with_ansi(atty::is(atty::Stream::Stdout))
                    .with_timer(fmt::time::SystemTime),
            )
            .try_init()
    };

    init_result.map_err(|err| err.into())
}
