use std::fs;
use std::process::Command;

fn multi_rir_bundle_root() -> std::path::PathBuf {
    std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("../../rpki/target/live/20260316-112341-multi-final3")
}

fn helper_script() -> std::path::PathBuf {
    std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("scripts/payload_replay/multi_rir_case_info.py")
}

fn wrapper_script() -> std::path::PathBuf {
    std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("scripts/payload_replay/run_multi_rir_replay_case.sh")
}

#[test]
fn multi_rir_case_info_resolves_all_five_rirs_and_timings() {
    let bundle_root = multi_rir_bundle_root();
    if !bundle_root.is_dir() {
        eprintln!(
            "skipping multi-rir case info test; bundle root missing: {}",
            bundle_root.display()
        );
        return;
    }

    let expected = [
        ("afrinic", "afrinic", "afrinic.tal", "afrinic-ta.cer"),
        ("apnic", "apnic", "apnic-rfc7730-https.tal", "apnic-ta.cer"),
        ("arin", "arin", "arin.tal", "arin-ta.cer"),
        ("lacnic", "lacnic", "lacnic.tal", "lacnic-ta.cer"),
        ("ripe", "ripe", "ripe-ncc.tal", "ripe-ncc-ta.cer"),
    ];

    for (rir, trust_anchor, tal_suffix, ta_suffix) in expected {
        let out = Command::new("python3")
            .arg(helper_script())
            .args([
                "--bundle-root",
                bundle_root.to_string_lossy().as_ref(),
                "--rir",
                rir,
            ])
            .output()
            .expect("run helper script");

        assert!(
            out.status.success(),
            "helper failed for {rir}: status={}\nstdout={}\nstderr={}",
            out.status,
            String::from_utf8_lossy(&out.stdout),
            String::from_utf8_lossy(&out.stderr)
        );

        let json: serde_json::Value =
            serde_json::from_slice(&out.stdout).expect("parse helper json");
        assert_eq!(json["rir"].as_str(), Some(rir));
        assert_eq!(json["trust_anchor"].as_str(), Some(trust_anchor));
        assert!(
            json["base_archive"]
                .as_str()
                .unwrap_or("")
                .ends_with("base-payload-archive")
        );
        assert!(
            json["delta_archive"]
                .as_str()
                .unwrap_or("")
                .ends_with("payload-delta-archive")
        );
        assert!(
            json["base_locks"]
                .as_str()
                .unwrap_or("")
                .ends_with("base-locks.json")
        );
        assert!(
            json["delta_locks"]
                .as_str()
                .unwrap_or("")
                .ends_with("locks-delta.json")
        );
        assert!(
            json["tal_path"]
                .as_str()
                .unwrap_or("")
                .ends_with(tal_suffix)
        );
        assert!(json["ta_path"].as_str().unwrap_or("").ends_with(ta_suffix));
        assert!(
            json["validation_times"]["snapshot"]
                .as_str()
                .unwrap_or("")
                .contains("T")
        );
        assert!(
            json["validation_times"]["delta"]
                .as_str()
                .unwrap_or("")
                .contains("T")
        );
        assert!(
            json["routinator_timings"]["base_replay_seconds"]
                .as_f64()
                .unwrap_or(0.0)
                > 0.0
        );
        assert!(
            json["routinator_timings"]["delta_replay_seconds"]
                .as_f64()
                .unwrap_or(0.0)
                > 0.0
        );
    }
}

#[test]
fn multi_rir_case_info_prefers_lock_validation_time_over_replay_started_at() {
    let td = tempfile::tempdir().expect("tempdir");
    let bundle_root = td.path();
    let rir_root = bundle_root.join("apnic");
    fs::create_dir_all(rir_root.join("base-payload-archive")).expect("base archive dir");
    fs::create_dir_all(rir_root.join("payload-delta-archive")).expect("delta archive dir");
    fs::create_dir_all(rir_root.join("timings")).expect("timings dir");

    fs::write(
        bundle_root.join("timing-summary.json"),
        r#"{"apnic":{"durations":{"base-replay":1.5,"delta-replay":2.5}}}"#,
    )
    .expect("write timing summary");
    fs::write(
        rir_root.join("base-locks.json"),
        r#"{"version":1,"capture":"base-cap","validationTime":"2026-03-16T11:49:15+08:00","rrdp":{},"rsync":{}}"#,
    )
    .expect("write base locks");
    fs::write(
        rir_root.join("locks-delta.json"),
        r#"{"version":1,"capture":"delta-cap","baseCapture":"base-cap","baseLocksSha256":"deadbeef","validationTime":"2026-03-16T12:14:10+08:00","rrdp":{},"rsync":{}}"#,
    )
    .expect("write delta locks");
    fs::write(
        rir_root.join("timings/base-replay.json"),
        r#"{"startedAt":"2099-01-01T00:00:00Z","durationSeconds":1.5}"#,
    )
    .expect("write base timing");
    fs::write(
        rir_root.join("timings/delta-replay.json"),
        r#"{"startedAt":"2099-01-02T00:00:00Z","durationSeconds":2.5}"#,
    )
    .expect("write delta timing");
    for rel in [
        "base-vrps.csv",
        "record-delta.csv",
        "replay-delta.csv",
        "verification.json",
        "README.md",
    ] {
        fs::write(
            rir_root.join(rel),
            "placeholder
",
        )
        .expect("write required file");
    }

    let repo_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let out = Command::new("python3")
        .arg(helper_script())
        .args([
            "--bundle-root",
            bundle_root.to_string_lossy().as_ref(),
            "--repo-root",
            repo_root.to_string_lossy().as_ref(),
            "--rir",
            "apnic",
        ])
        .output()
        .expect("run helper script");

    assert!(
        out.status.success(),
        "helper failed: status={}
stdout={}
stderr={}",
        out.status,
        String::from_utf8_lossy(&out.stdout),
        String::from_utf8_lossy(&out.stderr)
    );

    let json: serde_json::Value = serde_json::from_slice(&out.stdout).expect("parse helper json");
    assert_eq!(
        json["validation_times"]["snapshot"].as_str(),
        Some("2026-03-16T11:49:15+08:00")
    );
    assert_eq!(
        json["validation_times"]["delta"].as_str(),
        Some("2026-03-16T12:14:10+08:00")
    );
    assert_eq!(
        json["timing_started_at"]["snapshot_replay"].as_str(),
        Some("2099-01-01T00:00:00Z")
    );
    assert_eq!(
        json["timing_started_at"]["delta_replay"].as_str(),
        Some("2099-01-02T00:00:00Z")
    );
}

#[test]
fn multi_rir_wrapper_describe_mode_works_for_ripe() {
    let bundle_root = multi_rir_bundle_root();
    if !bundle_root.is_dir() {
        eprintln!(
            "skipping multi-rir wrapper describe test; bundle root missing: {}",
            bundle_root.display()
        );
        return;
    }

    let out = Command::new(wrapper_script())
        .env("BUNDLE_ROOT", &bundle_root)
        .args(["ripe", "describe"])
        .output()
        .expect("run wrapper script");

    assert!(
        out.status.success(),
        "wrapper failed: status={}\nstdout={}\nstderr={}",
        out.status,
        String::from_utf8_lossy(&out.stdout),
        String::from_utf8_lossy(&out.stderr)
    );

    let json: serde_json::Value =
        serde_json::from_slice(&out.stdout).expect("parse wrapper describe json");
    assert_eq!(json["rir"].as_str(), Some("ripe"));
    assert_eq!(json["trust_anchor"].as_str(), Some("ripe"));
    assert!(
        json["verification_json"]
            .as_str()
            .unwrap_or("")
            .ends_with("verification.json")
    );
}
