fn main() {
    // INTERIM: both llama-cpp-sys-2 and whisper-rs-sys statically link
    // their own copy of ggml, so GNU ld / lld see duplicate symbols when
    // linking the lumotia binary and its lib-tests. --allow-multiple-definition
    // makes the linker pick the first definition; safe while both crates
    // pin compatible ggml revisions. Replace with a system-ggml shared-lib
    // setup as a follow-up.
    if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("linux") {
        println!("cargo:rustc-link-arg=-Wl,--allow-multiple-definition");
    }

    assert_loopback_llm_csp();

    tauri_build::build()
}

/// Regression guard for brief item #2 (pre-emptive loopback LLM scope).
///
/// Lumotia's bundled llama.cpp server and any BYO Ollama install speak HTTP
/// on `127.0.0.1:*`. If the `connect-src` CSP ever drops those entries,
/// `fetch()` from the webview to the local LLM silently 404s with an
/// opaque scope error (Vibe #438 / #487). We keep the current permit
/// pinned at build time so a stray edit can't regress it unnoticed.
///
/// Parses `tauri.conf.json` properly and inspects the `connect-src`
/// directive of the CSP, rather than substring-searching the whole
/// file — the latter would both false-pass on unrelated values
/// containing a loopback URL and false-fail on JSON-escaped forward
/// slashes.
fn assert_loopback_llm_csp() {
    let conf_path = std::path::Path::new("tauri.conf.json");
    println!("cargo:rerun-if-changed=tauri.conf.json");

    let raw = std::fs::read_to_string(conf_path)
        .expect("build.rs: failed to read tauri.conf.json for CSP regression guard");
    let conf: serde_json::Value =
        serde_json::from_str(&raw).expect("build.rs: tauri.conf.json is not valid JSON");

    let csp = conf
        .pointer("/app/security/csp")
        .and_then(|v| v.as_str())
        .expect("build.rs: tauri.conf.json missing app.security.csp string");

    // Split the CSP into directives (`default-src 'self'; script-src ...`)
    // and find the one whose directive NAME is exactly "connect-src".
    // A prefix match would also accept hypothetical future directives
    // like "connect-src-elem" (2026-04-22 review MINOR).
    let connect_src = csp
        .split(';')
        .map(str::trim)
        .find_map(|directive| {
            let (name, rest) = directive.split_once(char::is_whitespace)?;
            if name == "connect-src" {
                Some(rest.trim())
            } else {
                None
            }
        })
        .expect(
            "build.rs: tauri.conf.json CSP missing connect-src directive — \
             local LLM fetches will be blocked (brief item #2)",
        );

    let tokens: Vec<&str> = connect_src.split_whitespace().collect();
    for required in ["http://127.0.0.1:*", "ws://127.0.0.1:*"] {
        assert!(
            tokens.contains(&required),
            "build.rs: tauri.conf.json CSP connect-src must permit {required} \
             for local LLM connectivity (brief item #2). Current connect-src: \
             {connect_src:?}"
        );
    }
    for forbidden in ["http://localhost:*", "ws://localhost:*"] {
        assert!(
            !tokens.contains(&forbidden),
            "build.rs: tauri.conf.json CSP connect-src must not permit {forbidden}; \
             normalize local LLM endpoints to 127.0.0.1 instead. Current connect-src: \
             {connect_src:?}"
        );
    }
}
