use super::common::bucketwarden;
use serde_json::Value;

#[test]
fn policy_tooling_commands_emit_explanations_simulations_and_findings() {
    let explain = bucketwarden()
        .args([
            "policy",
            "explain",
            "--principal",
            "alice",
            "--action",
            "s3:GetObject",
            "--resource",
            "archive/public/a.txt",
        ])
        .output()
        .unwrap();
    assert!(explain.status.success());
    let value: Value = serde_json::from_slice(&explain.stdout).unwrap();
    assert_eq!(value["reason"], "allowed");

    let simulate = bucketwarden()
        .args([
            "policy",
            "simulate",
            "--principal",
            "alice",
            "--action",
            "s3:GetObject",
            "--resource",
            "archive/private/a.txt",
            "--dry-run",
        ])
        .output()
        .unwrap();
    assert!(simulate.status.success());
    let value: Value = serde_json::from_slice(&simulate.stdout).unwrap();
    assert_eq!(value["dry_run"], true);
    assert_eq!(value["explanation"]["reason"], "explicit deny");

    let analyze = bucketwarden().args(["policy", "analyze"]).output().unwrap();
    assert!(analyze.status.success());
    let value: Value = serde_json::from_slice(&analyze.stdout).unwrap();
    assert!(value
        .as_array()
        .unwrap()
        .iter()
        .any(|finding| finding["code"] == "allow-wildcard-principal"));
}

#[test]
fn auth_admin_tooling_commands_emit_role_and_key_lifecycle_results() {
    let providers = bucketwarden()
        .args(["auth", "report", "identity-providers"])
        .output()
        .unwrap();
    assert!(providers.status.success());
    let value: Value = serde_json::from_slice(&providers.stdout).unwrap();
    assert!(value["native_support_state"]
        .as_array()
        .unwrap()
        .iter()
        .any(|provider| provider == "oidc"));
    assert!(value["configuration_admin_surface"]
        .as_array()
        .unwrap()
        .iter()
        .any(|method| method == "AuthStore::assume_role_with_web_identity"));

    let credentials = bucketwarden()
        .args(["auth", "report", "credentials"])
        .output()
        .unwrap();
    assert!(credentials.status.success());
    let value: Value = serde_json::from_slice(&credentials.stdout).unwrap();
    assert!(value["configuration_admin_surface"]
        .as_array()
        .unwrap()
        .iter()
        .any(|operation| operation == "AuthStore::rotate_access_key"));

    let temporary = bucketwarden()
        .args(["auth", "report", "temporary-credentials"])
        .output()
        .unwrap();
    assert!(temporary.status.success());
    let value: Value = serde_json::from_slice(&temporary.stdout).unwrap();
    assert!(value["security_governance_impact"]
        .as_array()
        .unwrap()
        .iter()
        .any(|control| control == "session scope is explicit and non-expanding"));

    let role = bucketwarden()
        .args([
            "auth",
            "role",
            "assign",
            "--principal",
            "alice",
            "--role",
            "security-officer",
            "--scope",
            "*",
        ])
        .output()
        .unwrap();
    assert!(role.status.success());
    let value: Value = serde_json::from_slice(&role.stdout).unwrap();
    assert_eq!(value["principal_id"], "alice");
    assert_eq!(value["role"], "SecurityOfficer");

    let roles = bucketwarden()
        .args(["auth", "role", "list", "--principal", "alice"])
        .output()
        .unwrap();
    assert!(roles.status.success());
    let value: Value = serde_json::from_slice(&roles.stdout).unwrap();
    assert!(value
        .as_array()
        .unwrap()
        .iter()
        .any(|role| role["role"] == "ReadOnlyOperator"));

    let rotate = bucketwarden()
        .args([
            "auth",
            "key",
            "rotate",
            "--principal",
            "alice",
            "--old",
            "AKIAOLD",
            "--new",
            "AKIANEW",
            "--secret",
            "new-secret",
        ])
        .output()
        .unwrap();
    assert!(rotate.status.success());
    let value: Value = serde_json::from_slice(&rotate.stdout).unwrap();
    assert_eq!(value["old_access_key_id"], "AKIAOLD");
    assert_eq!(value["new_access_key_id"], "AKIANEW");

    let revoke = bucketwarden()
        .args([
            "auth",
            "key",
            "revoke",
            "--principal",
            "alice",
            "--key",
            "AKIAREVOKE",
        ])
        .output()
        .unwrap();
    assert!(revoke.status.success());
    let value: Value = serde_json::from_slice(&revoke.stdout).unwrap();
    assert_eq!(value["access_key_id"], "AKIAREVOKE");
    assert_eq!(value["revoked"], true);

    let leaked = bucketwarden()
        .args([
            "auth",
            "key",
            "report-leaked",
            "--principal",
            "alice",
            "--key",
            "AKIALEAKED",
        ])
        .output()
        .unwrap();
    assert!(leaked.status.success());
    let value: Value = serde_json::from_slice(&leaked.stdout).unwrap();
    assert_eq!(value["access_key_id"], "AKIALEAKED");
    assert_eq!(value["revoked"], true);
}

#[test]
fn conformance_and_demo_commands_emit_non_certifying_operator_outputs() {
    let conformance = bucketwarden().arg("conformance").output().unwrap();
    assert!(conformance.status.success());
    let value: Value = serde_json::from_slice(&conformance.stdout).unwrap();
    assert!(value["sources"].as_u64().unwrap() > 0);
    assert!(value["promotion_gates"].as_u64().unwrap() > 0);

    let runtime = bucketwarden()
        .args(["conformance", "runtime"])
        .output()
        .unwrap();
    assert!(runtime.status.success());
    let value: Value = serde_json::from_slice(&runtime.stdout).unwrap();
    assert_eq!(value["passed"], true);
    assert!(value["sigv4_vectors"]
        .as_array()
        .unwrap()
        .iter()
        .all(|vector| vector["executed"] == true && vector["rejected_negative_case"] == true));

    let demo = bucketwarden().arg("demo").output().unwrap();
    assert!(demo.status.success());
    let value: Value = serde_json::from_slice(&demo.stdout).unwrap();
    assert_eq!(value["health"]["status"], "ok");
    assert!(value.get("audit_summary").is_some());
}
