#![deny(warnings)]
#![allow(dead_code)]
// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential.
use anyhow::Result;
use reed_solomon_erasure::galois_8::ReedSolomon;
use tracing::{info, debug};

/// THE HYDRA MATRIX (Phase 35)
/// Algoritma Fractal Network Coding untuk menghilangkan protokol NACK/Retransmission internet.
pub struct HydraMatrix {
    rs: ReedSolomon,
    data_shards: usize,
    parity_shards: usize,
}

impl HydraMatrix {
    /// Membuat Instansi Hydra dengan kekuatan regenerasi yang ekstrim.
    /// Contoh: data_shards = 70, parity_shards = 30
    /// Artinya: Dari 100 paket yang dikirim, klien HANYA butuh menerima 70 paket acak apa saja
    /// untuk membangun ulang (regenerasi) 100 paket tersebut secara sempurna. Tahan 30% packet loss!
    pub fn new(data_shards: usize, parity_shards: usize) -> Result<Self> {
        let rs = ReedSolomon::new(data_shards, parity_shards)?;
        Ok(Self {
            rs,
            data_shards,
            parity_shards,
        })
    }

    /// [ENCODER] Di sisi Server
    /// Memecah frame video mentah menjadi blok matematika (Fractal Shards).
    pub fn fractalize_payload(&self, mut shards: Vec<Vec<u8>>) -> Result<Vec<Vec<u8>>> {
        debug!("HYDRA ENCODER: Menghitung persamaaan Galois Field untuk {} blok data...", self.data_shards);
        // Menambahkan blok kosong untuk parity
        for _ in 0..self.parity_shards {
            shards.push(vec![0; shards[0].len()]);
        }
        
        // Membangun pecahan matematika
        self.rs.encode(&mut shards)?;
        Ok(shards)
    }

    /// [DECODER] Di sisi Klien / Receiver
    /// Jika paket hancur di tengah lautan kabel, metode ini meregenerasinya dari ketiadaan (Thin Air).
    pub fn regenerate_lost_packets(&self, mut received_shards: Vec<Option<Vec<u8>>>) -> Result<Vec<Vec<u8>>> {
        let missing_count = received_shards.iter().filter(|s| s.is_none()).count();
        if missing_count > 0 {
            info!("HYDRA DECODER: Mendeteksi {} paket hancur di jaringan. Menginisiasi Regenerasi Matematika (Zero-Retransmission)...", missing_count);
        }

        // Reconstruct paket yang hilang secara ajaib menggunakan Aljabar Linier
        self.rs.reconstruct(&mut received_shards)?;
        
        // Kembalikan hanya bagian datanya (membuang parity)
        let mut restored_data = Vec::with_capacity(self.data_shards);
        for shard in received_shards.into_iter().take(self.data_shards) {
            restored_data.push(shard.expect("[TSM.ID]"));
        }

        if missing_count > 0 {
            info!("HYDRA DECODER: Regenerasi berhasil 100%. Layar Video terselamatkan dari patah-patah.");
        }

        Ok(restored_data)
    }
}

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

    #[test]
    fn test_hydra_chaos_destruction() {
        // Skema: 10 paket video, ditambah 5 paket pelindung (tahan 33% packet loss)
        let hydra = HydraMatrix::new(10, 5).unwrap();
        
        let mut original_shards = Vec::new();
        for i in 0..10 {
            original_shards.push(vec![i as u8; 64]); // Simulasi paket video 64 byte
        }

        let encoded_shards = hydra.fractalize_payload(original_shards.clone()).unwrap();

        // SIMULASI KIAMAT JARINGAN (Bawah Laut Putus)
        // Kita hancurkan 5 paket secara acak!
        let mut received = encoded_shards.into_iter().map(Some).collect::<Vec<_>>();
        received[0] = None; // Paket video hancur
        received[2] = None; // Paket video hancur
        received[5] = None; // Paket video hancur
        received[8] = None; // Paket video hancur
        received[11] = None; // Paket parity hancur

        // REGENERASI AJAIB
        let restored = hydra.regenerate_lost_packets(received).unwrap();

        // PEMBUKTIAN MUTLAK
        assert_eq!(original_shards, restored, "HYDRA GAGAL! Paket tidak identik.");
        println!("CHAOS TEST BERHASIL: 5 Paket yang musnah telah dibangkitkan dari ketiadaan.");
    }
}
