Documentation
use sysinfo::{CpuExt, NetworkExt, NetworksExt, ProcessExt, System, SystemExt};

use serde::Serialize;

#[derive(Debug, Serialize, Default, Clone)]
pub struct SysInfo {
    pub server: Server,
    pub cpu: Cpu,
    pub cpu_load: CpuLoad,
    pub memory: Memory,
    pub process: Process,
    pub network: Vec<Network>,
}

#[derive(Debug, Serialize, Default, Clone)]
pub struct Cpu {
    pub name: String,
    pub arch: String,
    pub processors: usize,
    pub frequency: u64,
    pub cores: String,
    pub total_use: f32,
}
#[derive(Debug, Serialize, Default, Clone)]
pub struct CpuLoad {
    pub one: f64,
    pub five: f64,
    pub fifteen: f64,
}

#[derive(Debug, Serialize, Default, Clone)]
pub struct Memory {
    pub total_memory: u64,
    pub used_memory: u64,
    pub total_swap: u64,
    pub used_swap: u64,
}

#[derive(Debug, Serialize, Default, Clone)]
pub struct Server {
    pub oper_sys_name: String,
    pub host_name: String,
    pub system_version: String,
    pub system_kerne: String,
}
#[derive(Debug, Serialize, Default, Clone)]
pub struct Process {
    pub name: String,
    pub used_memory: u64,
    pub used_virtual_memory: u64,
    pub cup_usage: f32,
    pub start_time: u64,
    pub run_time: u64,
    pub disk_usage: DiskUsage,
}
#[derive(Debug, Serialize, Default, Clone)]
pub struct DiskUsage {
    pub read_bytes: u64,
    pub total_read_bytes: u64,
    pub written_bytes: u64,
    pub total_written_bytes: u64,
}

#[derive(Debug, Serialize, Default, Clone)]
pub struct Network {
    pub name: String,
    pub received: u64,
    pub total_received: u64,
    pub transmitted: u64,
    pub total_transmitted: u64,
}




pub fn get_oper_sys_info() -> SysInfo {
    let mut sys = System::new_all();
    sys.refresh_all();
    let pid = sysinfo::get_current_pid().expect("failed to get PID");
    let server = Server {
        oper_sys_name: sys.name().unwrap_or_else(|| "unknown".to_owned()),
        host_name: sys.host_name().unwrap_or_else(|| "unknown".to_owned()),
        system_version: sys.long_os_version().unwrap_or_else(|| "unknown".to_owned()),
        system_kerne: sys.kernel_version().unwrap_or_else(|| "unknown".to_owned()),
    };
    let process = match sys.process(pid) {
        Some(p) => Process {
            name: p.name().to_string(),
            used_memory: p.memory(),
            used_virtual_memory: p.virtual_memory(),
            cup_usage: p.cpu_usage(),
            start_time: p.start_time(),
            run_time: p.run_time(),
            disk_usage: DiskUsage {
                read_bytes: p.disk_usage().read_bytes,
                total_read_bytes: p.disk_usage().total_read_bytes,
                written_bytes: p.disk_usage().written_bytes,
                total_written_bytes: p.disk_usage().total_written_bytes,
            },
        },
        None => Process { ..Default::default() },
    };

    let mut network: Vec<Network> = Vec::new();

    for (interface_name, data) in sys.networks().iter() {
        network.push(Network {
            name: interface_name.to_string(),
            received: data.received(),
            total_received: data.total_received(),
            transmitted: data.transmitted(),
            total_transmitted: data.total_transmitted(),
        });
    }
    let cpu = Cpu {
        name: sys.global_cpu_info().brand().to_string(),
        arch: std::env::consts::ARCH.to_string(),
        cores: sys.physical_core_count().map(|c| c.to_string()).unwrap_or_else(|| "Unknown".to_owned()),
        total_use: sys.global_cpu_info().cpu_usage(),
        frequency: sys.global_cpu_info().frequency(),
        processors: sys.cpus().len(),
    };
    let cpu_load = CpuLoad {
        one: sys.load_average().one,
        five: sys.load_average().five,
        fifteen: sys.load_average().fifteen,
    };
    let memory = Memory {
        total_memory: sys.total_memory(),
        used_memory: sys.used_memory(),
        total_swap: sys.total_swap(),
        used_swap: sys.used_swap(),
    };

    SysInfo {
        server,
        cpu,
        memory,
        process,
        network,
        cpu_load,
    }
}


#[test]
fn test(){
    let sys_info = get_oper_sys_info();
    println!("{sys_info:#?}")
}