use chrono::Utc;
use chrono_tz::Tz;
use std::path::PathBuf;
use tracing_appender::rolling::{RollingFileAppender, Rotation};
use tracing_subscriber::{
    EnvFilter, fmt, fmt::time::FormatTime, layer::SubscriberExt, util::SubscriberInitExt,
};

#[derive(Clone, Copy, Debug)]
struct ConfiguredTimestamp {
    timezone: Tz,
}

impl FormatTime for ConfiguredTimestamp {
    fn format_time(
        &self,
        writer: &mut tracing_subscriber::fmt::format::Writer<'_>,
    ) -> std::fmt::Result {
        write!(
            writer,
            "{}",
            Utc::now()
                .with_timezone(&self.timezone)
                .to_rfc3339_opts(chrono::SecondsFormat::Millis, true)
        )
    }
}

/// Get the default log directory path: ~/.picobot/logs
pub fn get_default_log_dir() -> PathBuf {
    let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
    home.join(".picobot").join("logs")
}

/// Get the default config file path: ~/.picobot/config.json
pub fn get_default_config_path() -> PathBuf {
    let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
    home.join(".picobot").join("config.json")
}

/// Initialize logging with file appender
/// Logs are written to ~/.picobot/logs/ with daily rotation
pub fn init_logging(timezone: Tz) {
    let log_dir = get_default_log_dir();

    // Create log directory if it doesn't exist
    if !log_dir.exists() {
        if let Err(e) = std::fs::create_dir_all(&log_dir) {
            eprintln!(
                "Warning: Failed to create log directory {}: {}",
                log_dir.display(),
                e
            );
        }
    }

    // Create file appender with daily rotation
    let file_appender = RollingFileAppender::new(Rotation::DAILY, &log_dir, "picobot.log");

    // Build subscriber with both console and file output
    let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));

    let file_layer = fmt::layer()
        .with_writer(file_appender)
        .with_timer(ConfiguredTimestamp { timezone })
        .with_ansi(false)
        .with_target(true)
        .with_level(true)
        .with_thread_ids(true);

    let console_layer = fmt::layer()
        .with_timer(ConfiguredTimestamp { timezone })
        .with_target(true)
        .with_level(true);

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

    tracing::info!("Logging initialized. Log directory: {}", log_dir.display());
}

/// Initialize logging without file output (console only)
pub fn init_logging_console_only(timezone: Tz) {
    let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));

    let console_layer = fmt::layer()
        .with_timer(ConfiguredTimestamp { timezone })
        .with_target(true)
        .with_level(true);

    tracing_subscriber::registry()
        .with(env_filter)
        .with(console_layer)
        .init();

    tracing::info!("Logging initialized (console only)");
}
