//! [TSM.ID].[11031972] — Platform X Ecosystem
//! IPC Router with priority-based message routing

use crate::{IpcMessage, IpcError, Result};
use std::collections::{BinaryHeap, HashMap};
use std::cmp::Ordering;
use std::sync::{Arc, Mutex};

#[derive(Eq, PartialEq)]
struct PriorityMessage { msg: Vec<u8>, priority: u8, seq: u64 }

impl Ord for PriorityMessage {
    fn cmp(&self, other: &Self) -> Ordering {
        self.priority.cmp(&other.priority).then_with(|| other.seq.cmp(&self.seq))
    }
}
impl PartialOrd for PriorityMessage {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
}

pub struct IpcRouter {
    routes: Arc<Mutex<HashMap<String, String>>>,
    priority_queue: Arc<Mutex<BinaryHeap<PriorityMessage>>>,
    seq: Arc<Mutex<u64>>,
    max_queue: usize,
}

impl IpcRouter {
    pub fn new(max_queue: usize) -> Self {
        Self {
            routes: Arc::new(Mutex::new(HashMap::new())),
            priority_queue: Arc::new(Mutex::new(BinaryHeap::new())),
            seq: Arc::new(Mutex::new(0)),
            max_queue,
        }
    }

    pub fn add_route(&self, source: &str, target: &str) -> Result<()> {
        let mut r = self.routes.lock().map_err(|e| IpcError::LockPoisoned(e.to_string()))?;
        r.insert(source.to_string(), target.to_string());
        Ok(())
    }

    pub fn resolve(&self, source: &str) -> Result<String> {
        let r = self.routes.lock().map_err(|e| IpcError::LockPoisoned(e.to_string()))?;
        r.get(source).cloned().ok_or_else(|| IpcError::ChannelNotFound(source.to_string()))
    }

    pub fn enqueue(&self, msg: IpcMessage) -> Result<()> {
        let mut pq = self.priority_queue.lock().map_err(|e| IpcError::LockPoisoned(e.to_string()))?;
        if pq.len() >= self.max_queue { return Err(IpcError::BufferFull); }
        let mut s = self.seq.lock().map_err(|e| IpcError::LockPoisoned(e.to_string()))?;
        *s += 1;
        pq.push(PriorityMessage { msg: msg.payload, priority: msg.priority, seq: *s });
        Ok(())
    }

    pub fn dequeue(&self) -> Result<Option<Vec<u8>>> {
        let mut pq = self.priority_queue.lock().map_err(|e| IpcError::LockPoisoned(e.to_string()))?;
        Ok(pq.pop().map(|pm| pm.msg))
    }
}
