//! Rate counters and colored CLI lines (mirrors Python `[GLOBAL-REG]` / `[DEXTER]`).

use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::time::Instant;

use colored::Colorize;

pub static TELEMETRY: AtomicBool = AtomicBool::new(false);

static RATE_SCRAPED: AtomicU64 = AtomicU64::new(0);
static RATE_INSERTED: AtomicU64 = AtomicU64::new(0);

pub fn rate_reset() {
    RATE_SCRAPED.store(0, Ordering::Relaxed);
    RATE_INSERTED.store(0, Ordering::Relaxed);
}

pub fn rate_add_scraped(n: u64) {
    RATE_SCRAPED.fetch_add(n, Ordering::Relaxed);
}

pub fn rate_add_inserted(n: u64) {
    RATE_INSERTED.fetch_add(n, Ordering::Relaxed);
}

pub async fn rate_logger_loop_global() {
    rate_logger_loop_inner("[GLOBAL-REG]").await;
}

pub async fn rate_logger_loop_nl() {
    rate_logger_loop_inner("[DEXTER]").await;
}

async fn rate_logger_loop_inner(tag: &'static str) {
    let mut last_t = Instant::now();
    let mut last_s = RATE_SCRAPED.load(Ordering::Relaxed);
    let mut last_i = RATE_INSERTED.load(Ordering::Relaxed);
    loop {
        tokio::time::sleep(std::time::Duration::from_secs(15)).await;
        let now = Instant::now();
        let elapsed = now.duration_since(last_t).as_secs_f64();
        if elapsed <= 0.0 {
            continue;
        }
        let s = RATE_SCRAPED.load(Ordering::Relaxed);
        let i = RATE_INSERTED.load(Ordering::Relaxed);
        let ds = (s - last_s) as f64;
        let di = (i - last_i) as f64;
        let scrapes_per_min = (ds / elapsed) * 60.0;
        let inserts_per_min = (di / elapsed) * 60.0;
        ansi_info(
            tag,
            &format!(
                "Rate (last {:.0}s): scrapes {:.1}/min, inserts {:.1}/min",
                elapsed, scrapes_per_min, inserts_per_min
            ),
        );
        last_t = now;
        last_s = s;
        last_i = i;
    }
}

pub fn ansi_info(tag: &str, msg: &str) {
    println!(
        "{} {} {}",
        tag.magenta(),
        "[INFO]".cyan(),
        msg
    );
}

pub fn ansi_success(tag: &str, msg: &str) {
    println!(
        "{} {} {}",
        tag.magenta(),
        "[SUCCESS]".green(),
        msg
    );
}

pub fn ansi_warning(tag: &str, msg: &str) {
    println!(
        "{} {} {}",
        tag.magenta(),
        "[WARNING]".yellow(),
        msg
    );
}

pub fn ansi_error(tag: &str, msg: &str) {
    eprintln!(
        "{} {} {}",
        tag.magenta(),
        "[ERROR]".red(),
        msg
    );
}
