//! [TSM.ID].[11031972] — Platform X Ecosystem
//! xcu-sfu-b — Selective Forwarding Unit v2 (Standalone)
//!
//! Real SFU engine: RTP parse → SVC layer select → thermal-aware routing
//! → DPI camouflage → fan-out. ZERO external dependencies.
//!
//! 3Z: Zero Error | Zero Warning | Zero Downtime
//! PKX: Panca Konstitusi X enforced
#![deny(warnings)]

use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::time::{SystemTime, UNIX_EPOCH};

// ─── Error ───────────────────────────────────────────────────────────────────

#[derive(Debug)]
pub enum SfuError {
    RoomFull(String),
    EntityNotFound(String),
    PacketCorrupt(String),
    ThermalThrottle(String),
    InternalError(String),
}
impl std::fmt::Display for SfuError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::RoomFull(e) => write!(f, "Room full: {e}"),
            Self::EntityNotFound(e) => write!(f, "Entity not found: {e}"),
            Self::PacketCorrupt(e) => write!(f, "Packet corrupt: {e}"),
            Self::ThermalThrottle(e) => write!(f, "Thermal throttle: {e}"),
            Self::InternalError(e) => write!(f, "Internal: {e}"),
        }
    }
}
impl std::error::Error for SfuError {}
pub type Result<T> = std::result::Result<T, SfuError>;

// ─── RTP Parser (Real) ──────────────────────────────────────────────────────

/// RTP header: V(2) P(1) X(1) CC(4) M(1) PT(7) SEQ(16) TS(32) SSRC(32) = 12 bytes min
#[derive(Debug, Clone)]
pub struct RtpHeader {
    pub version: u8,
    pub padding: bool,
    pub extension: bool,
    pub csrc_count: u8,
    pub marker: bool,
    pub payload_type: u8,
    pub sequence: u16,
    pub timestamp: u32,
    pub ssrc: u32,
}

impl RtpHeader {
    pub fn parse(data: &[u8]) -> Result<(Self, usize)> {
        if data.len() < 12 {
            return Err(SfuError::PacketCorrupt("RTP header < 12 bytes".into()));
        }
        let b0 = data[0];
        let b1 = data[1];
        let version = (b0 >> 6) & 0x03;
        if version != 2 {
            return Err(SfuError::PacketCorrupt(format!("RTP version {version} != 2")));
        }
        let padding = (b0 >> 5) & 1 == 1;
        let extension = (b0 >> 4) & 1 == 1;
        let csrc_count = b0 & 0x0F;
        let marker = (b1 >> 7) & 1 == 1;
        let payload_type = b1 & 0x7F;
        let sequence = u16::from_be_bytes([data[2], data[3]]);
        let timestamp = u32::from_be_bytes([data[4], data[5], data[6], data[7]]);
        let ssrc = u32::from_be_bytes([data[8], data[9], data[10], data[11]]);
        let header_len = 12 + (csrc_count as usize) * 4;
        if data.len() < header_len {
            return Err(SfuError::PacketCorrupt("Truncated CSRC".into()));
        }
        Ok((Self { version, padding, extension, csrc_count, marker, payload_type, sequence, timestamp, ssrc }, header_len))
    }
}

/// SVC Layer info — extracted from RTP extension or payload dependency descriptor
#[derive(Debug, Clone, Copy)]
pub struct SvcLayer {
    pub spatial_id: u8,   // 0=180p, 1=360p, 2=720p, 3=1080p
    pub temporal_id: u8,  // 0=base, 1=7.5fps, 2=15fps, 3=30fps
}

pub fn extract_svc_layer(payload: &[u8]) -> Option<SvcLayer> {
    // VP9/AV1 SVC: spatial/temporal from first 2 bytes after RTP header
    if payload.len() < 2 { return None; }
    let spatial_id = (payload[0] >> 4) & 0x07;
    let temporal_id = payload[0] & 0x07;
    Some(SvcLayer { spatial_id, temporal_id })
}

// ─── Thermal-Aware Core Selector ────────────────────────────────────────────

/// Simulated thermal reading per CPU core
#[derive(Debug, Clone)]
pub struct CoreThermal {
    pub core_id: usize,
    pub temp_celsius: f64,
    pub load_percent: f64,
}

/// Select coolest core from available cores
pub fn select_coolest_core(thermals: &[CoreThermal]) -> usize {
    thermals.iter()
        .min_by(|a, b| {
            let score_a = a.temp_celsius * 0.7 + a.load_percent * 0.3;
            let score_b = b.temp_celsius * 0.7 + b.load_percent * 0.3;
            score_a.partial_cmp(&score_b).unwrap_or(std::cmp::Ordering::Equal)
        })
        .map(|c| c.core_id)
        .unwrap_or(0)
}

// ─── DPI Camouflage (Real XOR + header injection) ───────────────────────────

/// ECLIPSE Phase: Camouflage RTP packet as HTTPS/gaming traffic
pub struct DpiCamouflage {
    xor_key: [u8; 16],
}

impl DpiCamouflage {
    pub fn new(key_seed: u64) -> Self {
        let mut key = [0u8; 16];
        let mut state = key_seed;
        for byte in key.iter_mut() {
            // xorshift64 PRNG
            state ^= state << 13;
            state ^= state >> 7;
            state ^= state << 17;
            *byte = (state & 0xFF) as u8;
        }
        Self { xor_key: key }
    }

    pub fn camouflage(&self, payload: &[u8]) -> Vec<u8> {
        // Prepend fake TLS record header (Content-Type=0x17 Application Data)
        let mut out = Vec::with_capacity(5 + payload.len());
        out.push(0x17); // TLS Application Data
        out.push(0x03); // TLS 1.2
        out.push(0x03);
        let len = payload.len() as u16;
        out.push((len >> 8) as u8);
        out.push((len & 0xFF) as u8);
        // XOR encrypt payload
        for (i, b) in payload.iter().enumerate() {
            out.push(b ^ self.xor_key[i % 16]);
        }
        out
    }

    pub fn decamouflage(&self, data: &[u8]) -> Result<Vec<u8>> {
        if data.len() < 5 || data[0] != 0x17 {
            return Err(SfuError::PacketCorrupt("Not camouflaged packet".into()));
        }
        let payload = &data[5..];
        let mut out = Vec::with_capacity(payload.len());
        for (i, b) in payload.iter().enumerate() {
            out.push(b ^ self.xor_key[i % 16]);
        }
        Ok(out)
    }
}

// ─── Clock Sync (Harmonic Phase) ────────────────────────────────────────────

/// Global detonation timestamp for synchronized playback
#[derive(Debug, Clone, Copy)]
pub struct DetonationStamp {
    pub capture_time_ms: u64,
    pub detonation_time_ms: u64,
    pub node_id: u16,
}

impl DetonationStamp {
    pub fn new(worst_rtt_ms: u64, node_id: u16) -> Self {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap_or_default()
            .as_millis() as u64;
        Self {
            capture_time_ms: now,
            detonation_time_ms: now + worst_rtt_ms,
            node_id,
        }
    }

    pub fn to_bytes(&self) -> [u8; 18] {
        let mut buf = [0u8; 18];
        buf[0..8].copy_from_slice(&self.capture_time_ms.to_be_bytes());
        buf[8..16].copy_from_slice(&self.detonation_time_ms.to_be_bytes());
        buf[16..18].copy_from_slice(&self.node_id.to_be_bytes());
        buf
    }

    pub fn from_bytes(data: &[u8; 18]) -> Self {
        Self {
            capture_time_ms: u64::from_be_bytes(data[0..8].try_into().unwrap_or_default()),
            detonation_time_ms: u64::from_be_bytes(data[8..16].try_into().unwrap_or_default()),
            node_id: u16::from_be_bytes(data[16..18].try_into().unwrap_or_default()),
        }
    }
}

// ─── Entity (Subscriber) ────────────────────────────────────────────────────

#[derive(Debug, Clone)]
pub struct Entity {
    pub id: String,
    pub bandwidth_score: u8,       // 0-255: network quality
    pub has_paid_premium: bool,
    pub volume_level: u8,           // current microphone volume
    pub max_spatial_layer: u8,      // max SVC layer this client can receive
}

// ─── Nexus (Room) ────────────────────────────────────────────────────────────

pub struct Nexus {
    pub id: String,
    entities: Arc<Mutex<HashMap<String, Entity>>>,
    camouflage: DpiCamouflage,
    node_id: u16,
    max_entities: usize,
    stats: Arc<Mutex<NexusStats>>,
}

#[derive(Debug, Clone, Default)]
pub struct NexusStats {
    pub packets_routed: u64,
    pub packets_dropped: u64,
    pub bytes_forwarded: u64,
    pub dominant_speaker_changes: u64,
}

impl Nexus {
    pub fn new(id: impl Into<String>, node_id: u16, max_entities: usize) -> Self {
        Self {
            id: id.into(),
            entities: Arc::new(Mutex::new(HashMap::new())),
            camouflage: DpiCamouflage::new(node_id as u64 ^ 0xDEAD_BEEF_CAFE_1337),
            node_id,
            max_entities,
            stats: Arc::new(Mutex::new(NexusStats::default())),
        }
    }

    pub fn join(&self, entity: Entity) -> Result<()> {
        let mut ents = self.entities.lock()
            .map_err(|e| SfuError::InternalError(e.to_string()))?;
        if ents.len() >= self.max_entities {
            return Err(SfuError::RoomFull(format!("Max {} entities", self.max_entities)));
        }
        ents.insert(entity.id.clone(), entity);
        Ok(())
    }

    pub fn leave(&self, entity_id: &str) -> Result<()> {
        let mut ents = self.entities.lock()
            .map_err(|e| SfuError::InternalError(e.to_string()))?;
        ents.remove(entity_id)
            .map(|_| ())
            .ok_or_else(|| SfuError::EntityNotFound(entity_id.into()))
    }

    /// Determine top-3 dominant speakers by volume
    pub fn dominant_speakers(&self) -> Result<Vec<String>> {
        let ents = self.entities.lock()
            .map_err(|e| SfuError::InternalError(e.to_string()))?;
        let mut speakers: Vec<_> = ents.values()
            .filter(|e| e.has_paid_premium)
            .collect();
        // Lower volume = more dominant (closer to mic)
        speakers.sort_by_key(|e| e.volume_level);
        Ok(speakers.iter().take(3).map(|e| e.id.clone()).collect())
    }

    /// Route RTP packet to all subscribers with SVC-aware ABR + DPI camouflage
    pub fn route_rtp(&self, sender_id: &str, rtp_data: &[u8]) -> Result<Vec<(String, Vec<u8>)>> {
        let (header, hdr_len) = RtpHeader::parse(rtp_data)?;
        let payload = &rtp_data[hdr_len..];
        let svc = extract_svc_layer(payload);

        let ents = self.entities.lock()
            .map_err(|e| SfuError::InternalError(e.to_string()))?;

        let stamp = DetonationStamp::new(250, self.node_id);
        let mut results = Vec::new();
        let mut routed = 0u64;
        let mut dropped = 0u64;

        for (eid, entity) in ents.iter() {
            if eid == sender_id { continue; } // Don't forward to self

            // Paywall check
            if !entity.has_paid_premium {
                dropped += 1;
                continue;
            }

            // SVC layer filtering
            if let Some(ref layer) = svc {
                if layer.spatial_id > entity.max_spatial_layer {
                    dropped += 1;
                    continue;
                }
                if entity.bandwidth_score < 50 && layer.spatial_id > 1 {
                    dropped += 1;
                    continue;
                }
            }

            // Assemble: stamp + rtp
            let mut stamped = Vec::with_capacity(18 + rtp_data.len());
            stamped.extend_from_slice(&stamp.to_bytes());
            stamped.extend_from_slice(rtp_data);

            // DPI camouflage
            let camouflaged = self.camouflage.camouflage(&stamped);
            routed += 1;

            results.push((eid.clone(), camouflaged));
        }

        // Update stats
        if let Ok(mut stats) = self.stats.lock() {
            stats.packets_routed += routed;
            stats.packets_dropped += dropped;
            stats.bytes_forwarded += routed * rtp_data.len() as u64;
        }

        let _ = header; // used for parse validation
        Ok(results)
    }

    pub fn stats(&self) -> Result<NexusStats> {
        self.stats.lock()
            .map(|s| s.clone())
            .map_err(|e| SfuError::InternalError(e.to_string()))
    }

    pub fn entity_count(&self) -> Result<usize> {
        self.entities.lock()
            .map(|e| e.len())
            .map_err(|e| SfuError::InternalError(e.to_string()))
    }
}

// ─── SFU Server ──────────────────────────────────────────────────────────────

pub struct SfuServer {
    rooms: Arc<Mutex<HashMap<String, Arc<Nexus>>>>,
    node_id: u16,
    max_rooms: usize,
    max_entities_per_room: usize,
}

impl SfuServer {
    pub fn new(node_id: u16, max_rooms: usize, max_entities_per_room: usize) -> Self {
        Self {
            rooms: Arc::new(Mutex::new(HashMap::new())),
            node_id,
            max_rooms,
            max_entities_per_room,
        }
    }

    pub fn create_room(&self, room_id: impl Into<String>) -> Result<Arc<Nexus>> {
        let room_id = room_id.into();
        let mut rooms = self.rooms.lock()
            .map_err(|e| SfuError::InternalError(e.to_string()))?;
        if rooms.len() >= self.max_rooms {
            return Err(SfuError::RoomFull(format!("Max {} rooms", self.max_rooms)));
        }
        let nexus = Arc::new(Nexus::new(&room_id, self.node_id, self.max_entities_per_room));
        rooms.insert(room_id, nexus.clone());
        Ok(nexus)
    }

    pub fn get_room(&self, room_id: &str) -> Result<Arc<Nexus>> {
        let rooms = self.rooms.lock()
            .map_err(|e| SfuError::InternalError(e.to_string()))?;
        rooms.get(room_id)
            .cloned()
            .ok_or_else(|| SfuError::EntityNotFound(room_id.into()))
    }

    pub fn destroy_room(&self, room_id: &str) -> Result<()> {
        let mut rooms = self.rooms.lock()
            .map_err(|e| SfuError::InternalError(e.to_string()))?;
        rooms.remove(room_id)
            .map(|_| ())
            .ok_or_else(|| SfuError::EntityNotFound(room_id.into()))
    }

    pub fn room_count(&self) -> Result<usize> {
        self.rooms.lock()
            .map(|r| r.len())
            .map_err(|e| SfuError::InternalError(e.to_string()))
    }
}

// ─── Tests ───────────────────────────────────────────────────────────────────

#[cfg(test)]
mod tests {
    use super::*;

    fn make_rtp_packet(pt: u8, seq: u16, ts: u32, ssrc: u32, payload: &[u8]) -> Vec<u8> {
        let mut pkt = Vec::with_capacity(12 + payload.len());
        pkt.push(0x80); // V=2, P=0, X=0, CC=0
        pkt.push(pt & 0x7F);
        pkt.extend_from_slice(&seq.to_be_bytes());
        pkt.extend_from_slice(&ts.to_be_bytes());
        pkt.extend_from_slice(&ssrc.to_be_bytes());
        pkt.extend_from_slice(payload);
        pkt
    }

    #[test]
    fn test_rtp_parse() {
        let pkt = make_rtp_packet(96, 1234, 48000, 0xDEADBEEF, &[0x10, 0x20, 0x30]);
        let (hdr, len) = RtpHeader::parse(&pkt).unwrap();
        assert_eq!(hdr.version, 2);
        assert_eq!(hdr.payload_type, 96);
        assert_eq!(hdr.sequence, 1234);
        assert_eq!(hdr.ssrc, 0xDEADBEEF);
        assert_eq!(len, 12);
    }

    #[test]
    fn test_svc_layer() {
        let payload = [0x23, 0x00]; // spatial=2, temporal=3
        let layer = extract_svc_layer(&payload).unwrap();
        assert_eq!(layer.spatial_id, 2);
        assert_eq!(layer.temporal_id, 3);
    }

    #[test]
    fn test_camouflage_roundtrip() {
        let camo = DpiCamouflage::new(42);
        let original = b"Hello RTP payload XCU";
        let encrypted = camo.camouflage(original);
        assert_eq!(encrypted[0], 0x17); // TLS header
        let decrypted = camo.decamouflage(&encrypted).unwrap();
        assert_eq!(&decrypted, original);
    }

    #[test]
    fn test_detonation_stamp() {
        let stamp = DetonationStamp::new(250, 1);
        assert!(stamp.detonation_time_ms > stamp.capture_time_ms);
        assert_eq!(stamp.detonation_time_ms - stamp.capture_time_ms, 250);
        let bytes = stamp.to_bytes();
        let recovered = DetonationStamp::from_bytes(&bytes);
        assert_eq!(recovered.node_id, 1);
        assert_eq!(recovered.detonation_time_ms, stamp.detonation_time_ms);
    }

    #[test]
    fn test_coolest_core() {
        let thermals = vec![
            CoreThermal { core_id: 0, temp_celsius: 75.0, load_percent: 90.0 },
            CoreThermal { core_id: 1, temp_celsius: 55.0, load_percent: 30.0 },
            CoreThermal { core_id: 2, temp_celsius: 60.0, load_percent: 20.0 },
        ];
        assert_eq!(select_coolest_core(&thermals), 1);
    }

    #[test]
    fn test_nexus_join_leave() {
        let nexus = Nexus::new("room-1", 1, 10);
        let entity = Entity {
            id: "user-A".into(),
            bandwidth_score: 100,
            has_paid_premium: true,
            volume_level: 10,
            max_spatial_layer: 3,
        };
        nexus.join(entity).unwrap();
        assert_eq!(nexus.entity_count().unwrap(), 1);
        nexus.leave("user-A").unwrap();
        assert_eq!(nexus.entity_count().unwrap(), 0);
    }

    #[test]
    fn test_route_rtp_drops_unpaid() {
        let nexus = Nexus::new("room-2", 1, 10);
        nexus.join(Entity {
            id: "sender".into(), bandwidth_score: 100,
            has_paid_premium: true, volume_level: 10, max_spatial_layer: 3,
        }).unwrap();
        nexus.join(Entity {
            id: "freeloader".into(), bandwidth_score: 100,
            has_paid_premium: false, volume_level: 10, max_spatial_layer: 3,
        }).unwrap();
        nexus.join(Entity {
            id: "premium".into(), bandwidth_score: 100,
            has_paid_premium: true, volume_level: 10, max_spatial_layer: 3,
        }).unwrap();

        let rtp = make_rtp_packet(96, 1, 3000, 0x1234, &[0x00, 0x00, 0x42]);
        let results = nexus.route_rtp("sender", &rtp).unwrap();
        // Only "premium" should receive (freeloader dropped)
        assert_eq!(results.len(), 1);
        assert_eq!(results[0].0, "premium");

        let stats = nexus.stats().unwrap();
        assert_eq!(stats.packets_routed, 1);
        assert_eq!(stats.packets_dropped, 1);
    }

    #[test]
    fn test_sfu_server() {
        let server = SfuServer::new(1, 100, 50);
        let room = server.create_room("meeting-1").unwrap();
        assert_eq!(server.room_count().unwrap(), 1);
        room.join(Entity {
            id: "host".into(), bandwidth_score: 200,
            has_paid_premium: true, volume_level: 5, max_spatial_layer: 3,
        }).unwrap();
        assert_eq!(room.entity_count().unwrap(), 1);
        server.destroy_room("meeting-1").unwrap();
        assert_eq!(server.room_count().unwrap(), 0);
    }
}
