//! `pic plan` journey: a freshly-pulled manifest must diff to all-no-op
//! (pull→plan is idempotent), and editing a script source must surface
//! as an update.

use tempfile::TempDir;

use crate::common;

#[ignore = "needs DATABASE_URL pointing at a running Postgres"]
#[test]
fn plan_roundtrips_then_detects_change() {
    let Some(fx) = common::fixture_or_skip() else {
        return;
    };
    let env = common::admin_env(fx);
    let (script_id, guard) = common::deploy_fixture(&env, "plan", "hello.rhai");
    let app = guard.slug().to_string();

    common::pic_as(&env)
        .args([
            "routes", "create", "--script", &script_id, "--path", "/p", "--method", "GET",
        ])
        .assert()
        .success();

    // Pull the live state, then plan it back — must be a clean no-op.
    let dir = TempDir::new().expect("tempdir");
    common::pic_as(&env)
        .args(["pull", &app, "--dir"])
        .arg(dir.path())
        .assert()
        .success();
    let manifest = dir.path().join("picloud.toml");

    let out = common::pic_as(&env)
        .args(["plan", "--file"])
        .arg(&manifest)
        .output()
        .expect("plan");
    assert!(
        out.status.success(),
        "plan failed: {}",
        String::from_utf8_lossy(&out.stderr)
    );
    let stdout = String::from_utf8(out.stdout).unwrap();
    let hello = stdout
        .lines()
        .find(|l| l.contains("hello"))
        .unwrap_or_else(|| panic!("no hello row in plan:\n{stdout}"));
    assert!(
        hello.contains("noop"),
        "expected hello no-op, got:\n{stdout}"
    );
    assert!(
        !stdout.contains("create") && !stdout.contains("delete"),
        "fresh pull should diff clean, got:\n{stdout}"
    );

    // Edit the script source on disk → plan must report an update.
    std::fs::write(
        dir.path().join("scripts/hello.rhai"),
        "let body = #{ ok: false }; body",
    )
    .expect("rewrite source");
    let out = common::pic_as(&env)
        .args(["plan", "--file"])
        .arg(&manifest)
        .output()
        .expect("plan after edit");
    let stdout = String::from_utf8(out.stdout).unwrap();
    let hello = stdout
        .lines()
        .find(|l| l.contains("hello"))
        .unwrap_or_else(|| panic!("no hello row in plan:\n{stdout}"));
    assert!(
        hello.contains("update"),
        "expected hello update after source edit, got:\n{stdout}"
    );

    drop(guard);
}
