use std::env;
use vergen_gitcl::{Emitter, GitclBuilder};

fn main() {
    let pkg_version = env::var("CARGO_PKG_VERSION").expect("CARGO_PKG_VERSION not set");
    if let Err(err) = emit_git_instructions() {
        println!("cargo:warning=Failed to emit git metadata via vergen: {err}");
        println!("cargo:rustc-env=GPU_TRACE_PERF_VERSION={pkg_version}");
        return;
    }

    let computed_version = compute_version(&pkg_version);
    println!("cargo:rustc-env=GPU_TRACE_PERF_VERSION={computed_version}");
}

fn emit_git_instructions() -> Result<(), Box<dyn std::error::Error>> {
    let gitcl = GitclBuilder::default()
        .describe(true, false, None)
        .sha(true)
        .dirty(true)
        .build()?;

    Emitter::default()
        .add_instructions(&gitcl)?
        .emit_and_set()?;
    Ok(())
}

fn compute_version(package_version: &str) -> String {
    let describe = read_vergen_var("VERGEN_GIT_DESCRIBE");
    let short_rev = match read_vergen_var("VERGEN_GIT_SHA") {
        Some(value) => value,
        None => return package_version.to_string(),
    };
    let dirty = read_vergen_var("VERGEN_GIT_DIRTY");

    let version_string = if matches_release_tag(&describe, package_version) {
        package_version.to_string()
    } else {
        format!("{package_version} (git {short_rev})")
    };

    if dirty.as_deref() == Some("true") {
        format!("{version_string}-dirty")
    } else {
        version_string
    }
}

fn matches_release_tag(describe: &Option<String>, package_version: &str) -> bool {
    describe
        .as_deref()
        .map(|tag| tag == package_version || tag.trim_start_matches('v') == package_version)
        .unwrap_or(false)
}

fn read_vergen_var(name: &str) -> Option<String> {
    const IDEMPOTENT: &str = "VERGEN_IDEMPOTENT_OUTPUT";
    match env::var(name) {
        Ok(value) if !value.is_empty() && value != IDEMPOTENT => Some(value),
        _ => None,
    }
}
