//! Build script for coolprop-sys.
//!
//! Links the CoolProp C++ static library. Order of preference (prudent):
//! 1. Prebuilt static library under `vendor/coolprop/install_root/` (Windows MSVC).
//! 2. Compile from `vendor/coolprop` sources via CMake (slower; can fail on
//!    header generation / Python pickle issues on some corporate Windows images).
//! 3. System library fallback.

use std::env;
use std::path::{Path, PathBuf};

fn coolprop_vendor_root() -> Option<PathBuf> {
    let candidates = [
        PathBuf::from("../../vendor/coolprop"),
        PathBuf::from("../../../vendor/coolprop"),
        PathBuf::from("vendor/coolprop"),
    ];
    candidates.into_iter().find_map(|p| {
        p.canonicalize()
            .ok()
            .filter(|abs| abs.join("CMakeLists.txt").exists())
    })
}

/// Prefer a prebuilt CoolProp.lib so we do not re-run the fragile
/// `generate_headers` CMake custom step on every clean build.
fn find_prebuilt_static_lib(vendor: &Path) -> Option<PathBuf> {
    let root = vendor.join("install_root").join("static_library");
    if !root.is_dir() {
        return None;
    }
    // Walk shallow: Windows/64bit_MSVC_*/CoolProp.lib
    let mut matches = Vec::new();
    if let Ok(os_dirs) = std::fs::read_dir(&root) {
        for os_entry in os_dirs.flatten() {
            let os_path = os_entry.path();
            if !os_path.is_dir() {
                continue;
            }
            if let Ok(toolchain_dirs) = std::fs::read_dir(&os_path) {
                for tc in toolchain_dirs.flatten() {
                    let lib = tc.path().join("CoolProp.lib");
                    if lib.is_file() {
                        matches.push(lib);
                    }
                    // Also accept libCoolProp.a naming on non-MSVC trees
                    let lib_a = tc.path().join("libCoolProp.a");
                    if lib_a.is_file() {
                        matches.push(lib_a);
                    }
                }
            }
            // Direct CoolProp.lib under OS folder
            let direct = os_path.join("CoolProp.lib");
            if direct.is_file() {
                matches.push(direct);
            }
        }
    }
    // Prefer MSVC 64-bit paths when several exist
    matches.sort_by_key(|p| {
        let s = p.to_string_lossy().to_lowercase();
        let score = if s.contains("64bit") || s.contains("x64") {
            0
        } else {
            1
        };
        (score, s)
    });
    matches.into_iter().next()
}

fn link_system_libs(target_os: &str) {
    match target_os {
        "macos" => {
            println!("cargo:rustc-link-lib=dylib=c++");
        }
        "linux" | "freebsd" | "openbsd" | "netbsd" => {
            println!("cargo:rustc-link-lib=dylib=stdc++");
        }
        "windows" => {
            // MSVC links the C++ runtime automatically.
        }
        _ => {
            println!("cargo:rustc-link-lib=dylib=stdc++");
        }
    }
    if target_os != "windows" {
        println!("cargo:rustc-link-lib=dylib=m");
    }
}

fn main() {
    let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-env-changed=COOLPROP_PYTHON_EXECUTABLE");
    println!("cargo:rerun-if-env-changed=ENTROPYK_FORCE_COOLPROP_SOURCE_BUILD");

    let force_source = env::var("ENTROPYK_FORCE_COOLPROP_SOURCE_BUILD")
        .map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
        .unwrap_or(false);

    if let Some(vendor) = coolprop_vendor_root() {
        println!("cargo:rerun-if-changed={}", vendor.display());

        if !force_source {
            if let Some(prebuilt) = find_prebuilt_static_lib(&vendor) {
                let dir = prebuilt.parent().expect("CoolProp.lib has a parent dir");
                println!(
                    "cargo:warning=coolprop-sys: linking prebuilt static library at {}",
                    prebuilt.display()
                );
                println!("cargo:rustc-link-search=native={}", dir.display());
                println!("cargo:rustc-link-lib=static=CoolProp");
                link_system_libs(&target_os);
                if target_os == "macos" {
                    println!(
                        "cargo:rustc-link-arg=-Wl,-force_load,{}",
                        prebuilt.display()
                    );
                }
                return;
            }
        }

        // Source build via CMake (Release CRT matches Rust on Windows).
        let mut config = cmake::Config::new(&vendor);
        if let Ok(py) = env::var("COOLPROP_PYTHON_EXECUTABLE") {
            config.define("Python_EXECUTABLE", &py);
        }
        config
            .define("COOLPROP_SHARED_LIBRARY", "OFF")
            .define("COOLPROP_STATIC_LIBRARY", "ON")
            .define("COOLPROP_CATCH_TEST", "OFF")
            .define("COOLPROP_C_LIBRARY", "ON")
            .define("COOLPROP_MY_IFCO3_WRAPPER", "OFF")
            .profile("Release");
        let dst = config.build();

        println!("cargo:rustc-link-search=native={}/build", dst.display());
        println!(
            "cargo:rustc-link-search=native={}/build/Debug",
            dst.display()
        );
        println!(
            "cargo:rustc-link-search=native={}/build/Release",
            dst.display()
        );
        println!("cargo:rustc-link-search=native={}/lib", dst.display());
        println!("cargo:rustc-link-search=native={}/build", vendor.display());
        println!("cargo:rustc-link-lib=static=CoolProp");

        if target_os == "macos" {
            println!(
                "cargo:rustc-link-arg=-Wl,-force_load,{}/build/libCoolProp.a",
                dst.display()
            );
        }
    } else {
        println!(
            "cargo:warning=CoolProp source not found in vendor/. \
                   For full static build, run: \
                   git clone https://github.com/CoolProp/CoolProp.git vendor/coolprop"
        );
        if target_os == "windows" {
            println!("cargo:rustc-link-lib=CoolProp");
        } else {
            println!("cargo:rustc-link-lib=static=CoolProp");
        }
    }

    link_system_libs(&target_os);

    if target_os == "macos" {
        println!("cargo:rustc-link-arg=-Wl,-all_load");
    }
}
