use std::path::Path;

use anyhow::{Context, Result};
use tempfile::TempDir;
use tracing::info;

use crate::codegen::{generate_cargo_toml, generate_main_rs};
use crate::config::BuildConfig;

pub fn build(cfg: &BuildConfig, output_dir: &str) -> Result<()> {
    let tmp = TempDir::new().context("create temp dir")?;
    let tmp_path = tmp.path();

    // Write generated files
    std::fs::create_dir_all(tmp_path.join("src"))?;
    std::fs::write(tmp_path.join("Cargo.toml"), generate_cargo_toml(cfg))?;
    std::fs::write(tmp_path.join("src/main.rs"), generate_main_rs(cfg))?;

    info!(dir = %tmp_path.display(), "compiling custom binary");

    // Run cargo build --release
    let status = std::process::Command::new("cargo")
        .args(["build", "--release"])
        .current_dir(tmp_path)
        .status()
        .context("run cargo")?;

    if !status.success() {
        anyhow::bail!("cargo build failed with status {status}");
    }

    // Copy output binary
    let binary_name = &cfg.build.output;
    let src = tmp_path.join("target/release").join(binary_name);
    let dst = Path::new(output_dir).join(binary_name);
    std::fs::copy(&src, &dst)
        .with_context(|| format!("copy {} → {}", src.display(), dst.display()))?;

    info!(output = %dst.display(), "binary ready");
    Ok(())
}
