use std::{path::Path, process::Command};

use crate::common::{TRACE_FILE, VardalithResult, file_utils::find_file_by_extension};

pub fn execute_patch(workdir: &str) -> VardalithResult<()> {
    let trace_file = Path::new(workdir).join(TRACE_FILE);
    if !trace_file.exists() {
        return Err(format!(
            "Trace file does not exist in working directory: {}",
            trace_file.display()
        ));
    }
    let vanilla =
        find_file_by_extension(workdir, "vanilla")?.ok_or("Cannot find original binary")?;
    let mumak_root =
        std::env::var("MUMAK_ROOT").map_err(|_| "MUMAK_ROOT environment variable is not set.")?;

    // Static analysis
    let sa_result = Command::new(format!("{}/src/bin/palantir", mumak_root))
        .current_dir(&workdir)
        .arg("-p")
        .arg("-i")
        .arg("1")
        .arg("-t")
        .arg(trace_file)
        .arg("-a")
        .arg(format!("{}/src/analysis/acquire_calls.txt", mumak_root))
        .arg("-r")
        .arg(format!("{}/src/analysis/release_calls.txt", mumak_root))
        .arg(&vanilla)
        .output()
        .map_err(|e| format!("Failed to execute static analysis: {}", e))?;

    if !sa_result.status.success() {
        let stderr = String::from_utf8_lossy(&sa_result.stderr);
        println!("Static analysis failed: {}", stderr);
    }

    // Patching
    // The patch wrapper script is very sketchy, eventually should just reimplement in this ecosystem
    let pw_result = Command::new(format!("{}/src/patching/patch_wrapper.py", mumak_root))
        .current_dir(&workdir)
        .arg(&vanilla)
        .arg("to_patch.csv") // generated by palantir
        .output()
        .map_err(|e| format!("Failed to execute patch_wrapper: {}", e))?;

    if !pw_result.status.success() {
        let stderr = String::from_utf8_lossy(&pw_result.stderr);
        println!("Patching failed: {}", stderr);
    }

    Ok(())
}
