//! Phase-3 config `vars`, end to end via `pic`: a group-owned var is
//! inherited by an app underneath it, and an app-owned var of the same key
//! overrides the inherited value (proximity wins, §3).
//!
//! Drives the real resolution path: a script does `vars::get("region")`
//! and returns it; we invoke it via `/api/v1/execute/{id}` and assert on
//! the body. First the group value flows down (inheritance), then an app
//! value shadows it (override).

use crate::common;
use crate::common::cleanup::{AppGuard, GroupGuard};

#[ignore = "needs DATABASE_URL pointing at a running Postgres"]
#[test]
fn group_var_is_inherited_then_app_value_overrides() {
    let Some(fx) = common::fixture_or_skip() else {
        return;
    };
    let env = common::admin_env(fx);
    let acme = common::unique_slug("v-acme");
    let app = common::unique_slug("v-app");

    // Group `acme`, then a `region` var on it (a JSON string "eu").
    let _g_acme = GroupGuard::new(&env.url, &env.token, &acme);
    common::pic_as(&env)
        .args(["groups", "create", &acme])
        .assert()
        .success();
    common::pic_as(&env)
        .args(["vars", "set", "region", "eu", "--group", &acme])
        .assert()
        .success();

    // App under acme with a script that reads + returns the resolved var.
    let _app = AppGuard::new(&env.url, &env.token, &app);
    common::pic_as(&env)
        .args(["apps", "create", &app, "--group", &acme])
        .assert()
        .success();
    let fixture = common::fixture_path("read-var.rhai");
    common::pic_as(&env)
        .args([
            "scripts",
            "deploy",
            fixture.to_str().unwrap(),
            "--app",
            &app,
        ])
        .assert()
        .success();

    // Resolve the deployed script's id.
    let ls = common::pic_as(&env)
        .args(["scripts", "ls", "--app", &app])
        .output()
        .expect("scripts ls");
    let id = common::parse_first_id(std::str::from_utf8(&ls.stdout).unwrap())
        .expect("scripts ls should produce one row");

    // Inherited: the app has no own `region`, so the group's "eu" resolves.
    assert_eq!(invoke_body(&env, &id), serde_json::json!("eu"), "inherited");

    // Proximity override: an app-owned `region` shadows the group value.
    common::pic_as(&env)
        .args(["vars", "set", "region", "us", "--app", &app])
        .assert()
        .success();
    assert_eq!(invoke_body(&env, &id), serde_json::json!("us"), "override");
}

/// Invoke a script via `pic scripts invoke <id>` (→ `/api/v1/execute/{id}`)
/// and parse its JSON body.
fn invoke_body(env: &common::TestEnv, id: &str) -> serde_json::Value {
    let out = common::pic_as(env)
        .args(["scripts", "invoke", id])
        .output()
        .expect("scripts invoke");
    assert!(
        out.status.success(),
        "invoke failed: {}",
        String::from_utf8_lossy(&out.stderr)
    );
    serde_json::from_slice(&out.stdout).expect("invoke body is JSON")
}
