use chrono::Local;
use clap::Parser;
use rand::Rng;
use std::thread;
use std::time::{Duration, Instant};
use sysinfo::System;

#[derive(Parser, Debug, Clone)]
#[command(version, about, long_about = None)]
struct Args {
    #[arg(long, help = "使用的线程数", default_value_t = 2)]
    thread_count: u32,

    #[arg(long, default_value_t = 50, help = "每个线程执行计算的时间比例",
        value_parser = clap::value_parser!(u32).range(1..100)
    )]
    thread_percent: u32,

    #[arg(long, default_value_t = 30, help = "CPU总的最大的一分钟负载, 达到后, 程序睡眠. 此值为 (htop_load_average_1分钟 / CPU核数 * 100)",
        value_parser = clap::value_parser!(u32).range(1..100)
    )]
    max_load_average_percent: u32,

    #[arg(long, action=clap::ArgAction::SetTrue)]
    verbose: bool,
}

fn run_task(tid: u32, args: Args) {
    let sys = System::new_all();
    let cpu_nb = sys.cpus().len();

    let max_load_avg = args.max_load_average_percent as f64 / 100f64 * cpu_nb as f64;

    println!(
        "[{:?}]启动线程: {tid}, CPU: {cpu_nb}, 最大负载: {max_load_avg:.2}(={}%x{})",
        Local::now(),
        args.max_load_average_percent,
        cpu_nb,
    );

    let mut rng = rand::rng();

    loop {
        // 秒
        let run_interval = rng.random_range(5..10) as f64;
        let run_sec = run_interval * args.thread_percent as f64 / 100f64;
        let sleep_sec = run_interval - run_sec;

        let run_du = Duration::from_secs_f64(run_sec);
        let sleep_du = Duration::from_secs_f64(sleep_sec);

        if args.verbose {
            println!(
                "[{:?}]线程{tid} 执行计算: {run_du:?}, 睡{sleep_du:?}",
                Local::now()
            );
        }

        let now = Instant::now();
        let mut sum: i64 = 0;
        loop {
            if now.elapsed() > run_du {
                break;
            }

            sum = sum.wrapping_add(1);
        }

        if args.verbose {
            println!(
                "[{:?}]线程{tid} 执行睡眠: {run_du:?}, 睡{sleep_du:?}",
                Local::now()
            );
        }
        thread::sleep(sleep_du);

        loop {
            let load_avg = System::load_average();
            if load_avg.one < max_load_avg {
                break;
            }
            let sleep_du = Duration::from_secs(rng.random_range(5..10));

            if args.verbose {
                println!(
                    "[{:?}]线程{tid} 检测到超过最大负载 {} > {}, 睡眠 {:?}",
                    Local::now(),
                    load_avg.one,
                    max_load_avg,
                    sleep_du
                );
            }

            thread::sleep(sleep_du);
        }
    }
}

fn main() {
    let args = Args::parse();

    println!(
        "启动线程 {}, 每线程计算时间占比: {}%, 最高负载: {}%, 打印日志: {}",
        args.thread_count, args.thread_percent, args.max_load_average_percent, args.verbose
    );

    for tid in 0..args.thread_count {
        let args = args.clone();
        thread::spawn(move || {
            run_task(tid, args);
        });
    }

    let sys = System::new_all();
    let cpu_nb = sys.cpus().len();


    let sleep_du = Duration::from_millis(5000);
    loop {
        thread::sleep(sleep_du);

        let avg = System::load_average();

        println!(
            "[{:?}]当前负载: {:.2}%, {:?}",
            Local::now(),
            avg.one / cpu_nb as f64 * 100f64,
            avg,
        );
    }
}