use std::time::Duration;

use chrono::Datelike;

use crate::db::connect;
use crate::notify::{NotifyEvent, NotifySender};
use crate::settings::Settings;

/// Spawns a background task that sends a monthly stats message on the 1st of each month.
pub async fn start(
    settings: Settings,
    telegram_tx: Option<NotifySender>,
    whatsapp_tx: Option<NotifySender>,
) {
    tokio::spawn(async move {
        let mut last_sent: Option<(i32, u32)> = None;
        loop {
            tokio::time::sleep(Duration::from_secs(3600)).await;
            let now = chrono::Local::now();
            if now.day() != 1 {
                continue;
            }
            let current = (now.year(), now.month());
            if last_sent == Some(current) {
                continue;
            }

            let (prev_year, prev_month) = previous_month(now.year(), now.month());
            let from = format!("{prev_year:04}-{prev_month:02}-01T00:00:00");
            let to = format!("{:04}-{:02}-01T00:00:00", now.year(), now.month());
            let month_name = german_month_name(prev_year, prev_month);

            if let Ok(mut conn) = connect(&settings.database).await {
                let added = conn
                    .load_additions_in_period(&from, &to)
                    .unwrap_or_default();
                let total = conn.count_unique_movies().unwrap_or(0);
                let size = conn.total_movies_size().unwrap_or(0);

                let mut per_user_map: std::collections::HashMap<String, usize> = Default::default();
                for a in &added {
                    *per_user_map.entry(a.user.clone()).or_default() += 1;
                }
                let mut per_user: Vec<(String, usize)> = per_user_map.into_iter().collect();
                per_user.sort_by_key(|b| std::cmp::Reverse(b.1));

                log::info!("Sending monthly stats for {month_name}.");
                let event = NotifyEvent::MonthlyStats {
                    month_name,
                    added_count: added.len(),
                    per_user,
                    total_count: total,
                    total_size_bytes: size,
                };
                let events = vec![event];
                if let Some(ref tx) = telegram_tx {
                    let _ = tx.try_send(events.clone());
                }
                if let Some(ref tx) = whatsapp_tx {
                    let _ = tx.try_send(events);
                }
            } else {
                log::error!("Failed to connect to DB for monthly stats.");
            }

            last_sent = Some(current);
        }
    });
}

fn previous_month(year: i32, month: u32) -> (i32, u32) {
    if month == 1 {
        (year - 1, 12)
    } else {
        (year, month - 1)
    }
}

fn german_month_name(year: i32, month: u32) -> String {
    let name = match month {
        1 => "Januar",
        2 => "Februar",
        3 => "März",
        4 => "April",
        5 => "Mai",
        6 => "Juni",
        7 => "Juli",
        8 => "August",
        9 => "September",
        10 => "Oktober",
        11 => "November",
        12 => "Dezember",
        _ => "Unbekannt",
    };
    format!("{name} {year}")
}
