//! Event Bus - Real-time broadcast messaging for agents.
//!
//! Provides pub/sub functionality for MemorySignal events across
//! the MimirsWell cluster using tokio broadcast channels.

use crate::signal::MemorySignal;
use mimirs_core::{AgentId, MimirError};
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::RwLock;
use tokio::sync::broadcast;

/// EventBus - Broadcast messaging for agent coordination.
#[derive(Clone)]
pub struct EventBus {
    /// Broadcast sender for signals.
    sender: broadcast::Sender<MemorySignal>,
    /// Track subscribers by agent.
    subscribers: Arc<RwLock<HashMap<AgentId, usize>>>,
}

impl EventBus {
    /// Creates a new EventBus with default capacity.
    pub fn new() -> Self {
        let (tx, _) = broadcast::channel(1024);
        Self {
            sender: tx,
            subscribers: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// Creates a new EventBus with custom capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        let (tx, _) = broadcast::channel(capacity);
        Self {
            sender: tx,
            subscribers: Arc::new(RwLock::new(HashMap::new())),
        }
    }

    /// Subscribe to signals for a specific agent.
    pub fn subscribe(&self, agent_id: AgentId) -> broadcast::Receiver<MemorySignal> {
        let rx = self.sender.subscribe();
        if let Ok(mut subs) = self.subscribers.write() {
            *subs.entry(agent_id).or_insert(0) += 1;
        }
        rx
    }

    /// Broadcast a signal to all subscribers.
    pub fn broadcast(&self, signal: MemorySignal) -> Result<(), MimirError> {
        self.sender
            .send(signal)
            .map_err(|e| MimirError::Internal(e.to_string()))?;
        Ok(())
    }

    /// Broadcast a signal to a specific agent.
    pub fn send_to_agent(
        &self,
        _agent_id: AgentId,
        signal: MemorySignal,
    ) -> Result<(), MimirError> {
        // For targeted sends, we still broadcast but the receiver filters
        self.broadcast(signal)
    }

    /// Get subscriber count.
    pub fn subscriber_count(&self) -> usize {
        self.subscribers.read().map(|s| s.len()).unwrap_or(0)
    }
}

impl Default for EventBus {
    fn default() -> Self {
        Self::new()
    }
}
