use std::collections::VecDeque;

use serde::Serialize;

const MAX_EVENTS: usize = 200;

#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ActivityLevel {
    Info,
    Warn,
    Error,
}

#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ActivityCategory {
    Growth,
    Rebalance,
    Recovery,
    Anchor,
    Connection,
    Relay,
}

#[derive(Debug, Clone, Serialize)]
pub struct ActivityEvent {
    pub timestamp_ms: u64,
    pub level: ActivityLevel,
    pub category: ActivityCategory,
    pub message: String,
    pub peer_id: Option<[u8; 32]>,
}

pub struct ActivityLog {
    events: VecDeque<ActivityEvent>,
}

impl ActivityLog {
    pub fn new() -> Self {
        Self {
            events: VecDeque::with_capacity(MAX_EVENTS),
        }
    }

    pub fn log(
        &mut self,
        level: ActivityLevel,
        cat: ActivityCategory,
        msg: String,
        peer: Option<[u8; 32]>,
    ) {
        let now = std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .unwrap_or_default()
            .as_millis() as u64;
        if self.events.len() >= MAX_EVENTS {
            self.events.pop_front();
        }
        self.events.push_back(ActivityEvent {
            timestamp_ms: now,
            level,
            category: cat,
            message: msg,
            peer_id: peer,
        });
    }

    pub fn recent(&self, limit: usize) -> Vec<ActivityEvent> {
        let start = self.events.len().saturating_sub(limit);
        self.events.iter().skip(start).cloned().collect()
    }
}
