#![deny(warnings)]
#![allow(dead_code)]
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-pc24 -- PrismCellular P2P Mesh (aarch64 compatible)
use std::collections::{HashMap, VecDeque};

#[derive(Debug)]
pub enum Pc24Error { NoPeer(String), NoRoute(String), TtlExpired(String) }
impl std::fmt::Display for Pc24Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::NoPeer(e)|Self::NoRoute(e)|Self::TtlExpired(e) => write!(f, "{e}") } } }
impl std::error::Error for Pc24Error {}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum CellularBand { Band24Ghz, Band5Ghz, Band60Ghz, Ultrasonic }
impl CellularBand {
    pub fn attenuation_db_per_meter(&self) -> f64 { match self { Self::Band24Ghz => 0.05, Self::Band5Ghz => 0.12, Self::Band60Ghz => 0.8, Self::Ultrasonic => 0.3 } }
    pub fn max_range_m(&self) -> f64 { match self { Self::Band24Ghz => 100.0, Self::Band5Ghz => 50.0, Self::Band60Ghz => 10.0, Self::Ultrasonic => 5.0 } }
}

#[derive(Debug, Clone)]
pub struct PeerNode { pub id: String, pub addr: String, pub signal_dbm: i32, pub band: CellularBand, pub last_seen: u64, pub neighbors: Vec<String> }

#[derive(Debug, Clone)]
pub struct MeshPacket { pub src: String, pub dst: String, pub payload: Vec<u8>, pub hop_count: u8, pub max_ttl: u8, pub path: Vec<String> }

pub struct MeshRouter { peers: HashMap<String, PeerNode> }
impl MeshRouter {
    pub fn new() -> Self { Self { peers: HashMap::new() } }
    pub fn add_peer(&mut self, peer: PeerNode) { self.peers.insert(peer.id.clone(), peer); }
    pub fn remove_peer(&mut self, id: &str) -> bool { self.peers.remove(id).is_some() }

    /// BFS multi-hop route finding
    pub fn find_route(&self, from: &str, to: &str) -> Result<Vec<String>, Pc24Error> {
        if !self.peers.contains_key(from) { return Err(Pc24Error::NoPeer(from.into())); }
        if !self.peers.contains_key(to) { return Err(Pc24Error::NoPeer(to.into())); }
        let mut visited: HashMap<String, String> = HashMap::new();
        let mut queue = VecDeque::new();
        queue.push_back(from.to_string());
        visited.insert(from.into(), String::new());
        while let Some(current) = queue.pop_front() {
            if current == to {
                let mut path = vec![to.to_string()];
                let mut c = to.to_string();
                while let Some(prev) = visited.get(&c) { if prev.is_empty() { break; } path.push(prev.clone()); c = prev.clone(); }
                path.reverse(); return Ok(path);
            }
            if let Some(peer) = self.peers.get(&current) {
                for neighbor in &peer.neighbors {
                    if !visited.contains_key(neighbor) { visited.insert(neighbor.clone(), current.clone()); queue.push_back(neighbor.clone()); }
                }
            }
        }
        Err(Pc24Error::NoRoute(format!("{from}->{to}")))
    }

    pub fn forward_packet(&self, pkt: &mut MeshPacket) -> Result<String, Pc24Error> {
        if pkt.hop_count >= pkt.max_ttl { return Err(Pc24Error::TtlExpired(format!("TTL {} reached", pkt.max_ttl))); }
        let route = self.find_route(pkt.path.last().map(|s| s.as_str()).unwrap_or(&pkt.src), &pkt.dst)?;
        if route.len() > 1 { let next = route[1].clone(); pkt.hop_count += 1; pkt.path.push(next.clone()); Ok(next) }
        else { Err(Pc24Error::NoRoute("No next hop".into())) }
    }

    /// Broadcast to all peers within signal range
    pub fn broadcast(&self, from: &str, payload: &[u8]) -> Vec<String> {
        let mut reached = Vec::new();
        if let Some(src) = self.peers.get(from) {
            for (id, peer) in &self.peers {
                if id != from && src.neighbors.contains(id) { let _ = peer; reached.push(id.clone()); }
            }
        }
        let _ = payload;
        reached
    }
    pub fn peer_count(&self) -> usize { self.peers.len() }
    pub fn signal_quality(dbm: i32) -> &'static str { if dbm > -50 { "Excellent" } else if dbm > -70 { "Good" } else if dbm > -85 { "Fair" } else { "Poor" } }
}

#[cfg(test)]
mod tests {
    use super::*;
    fn mesh() -> MeshRouter {
        let mut m = MeshRouter::new();
        m.add_peer(PeerNode { id: "A".into(), addr: "10.0.0.1".into(), signal_dbm: -40, band: CellularBand::Band24Ghz, last_seen: 0, neighbors: vec!["B".into(), "C".into()] });
        m.add_peer(PeerNode { id: "B".into(), addr: "10.0.0.2".into(), signal_dbm: -60, band: CellularBand::Band5Ghz, last_seen: 0, neighbors: vec!["A".into(), "D".into()] });
        m.add_peer(PeerNode { id: "C".into(), addr: "10.0.0.3".into(), signal_dbm: -55, band: CellularBand::Band24Ghz, last_seen: 0, neighbors: vec!["A".into()] });
        m.add_peer(PeerNode { id: "D".into(), addr: "10.0.0.4".into(), signal_dbm: -70, band: CellularBand::Band60Ghz, last_seen: 0, neighbors: vec!["B".into()] });
        m
    }
    #[test] fn test_route() { let m = mesh(); let r = m.find_route("A", "D").unwrap(); assert_eq!(r, vec!["A","B","D"]); }
    #[test] fn test_broadcast() { let m = mesh(); let r = m.broadcast("A", b"hello"); assert_eq!(r.len(), 2); }
    #[test] fn test_no_route() { let m = mesh(); assert!(m.find_route("C", "D").is_ok()); } // C->A->B->D
    #[test] fn test_signal() { assert_eq!(MeshRouter::signal_quality(-40), "Excellent"); }
}
