use super::common::{bucketwarden, operator_config};
use serde_json::Value;

#[test]
fn help_prints_operator_contract() {
    let output = bucketwarden().arg("--help").output().unwrap();

    assert!(output.status.success());
    let stdout = String::from_utf8(output.stdout).unwrap();
    assert!(stdout.contains("BucketWarden operator CLI"));
    assert!(stdout.contains("config validate --config <path>"));
    assert!(stdout.contains("health [--config <path>]"));
    assert!(stdout.contains("readiness [--config <path>]"));
    assert!(stdout.contains("diagnostics [--config <path>]"));
    assert!(stdout.contains("metrics [--config <path>]"));
    assert!(stdout.contains("audit export [--config <path>]"));
    assert!(stdout.contains("replication status [--config <path>]"));
    assert!(stdout.contains("policy explain --principal P --action A --resource R"));
    assert!(stdout.contains("policy simulate --principal P --action A --resource R [--dry-run]"));
    assert!(stdout.contains("auth report identity-providers"));
    assert!(stdout.contains("auth report credentials"));
    assert!(stdout.contains("auth report temporary-credentials"));
    assert!(stdout.contains("auth role assign --principal P --role ROLE --scope S"));
    assert!(stdout.contains("auth key rotate --principal P --old OLD --new NEW --secret SECRET"));
    assert!(stdout.contains("auth key revoke --principal P --key KEY"));
    assert!(stdout.contains("auth key report-leaked --principal P --key KEY"));
    assert!(stdout.contains("ui browser manifest|html|css|js"));
}

#[test]
fn short_help_prints_operator_contract() {
    let output = bucketwarden().arg("-h").output().unwrap();

    assert!(output.status.success());
    let stdout = String::from_utf8(output.stdout).unwrap();
    assert!(stdout.contains("BucketWarden operator CLI"));
    assert!(stdout.contains("bucketwarden s3 serve [--bind ADDR]"));
}

#[test]
fn browser_ui_commands_emit_manifest_and_static_assets() {
    let manifest = bucketwarden()
        .args(["ui", "browser", "manifest"])
        .output()
        .unwrap();
    assert!(manifest.status.success());
    let value: Value = serde_json::from_slice(&manifest.stdout).unwrap();
    assert_eq!(
        value["boundary_id"],
        "bnd:bucketwarden.browser-ui-full-product-scope"
    );
    assert_eq!(value["claim_tier"], "T3");
    assert!(value["features"]
        .as_array()
        .unwrap()
        .iter()
        .any(|feature| feature["feature_id"] == "feat:bucketwarden.ui.browser.login-page"));

    let html = bucketwarden()
        .args(["ui", "browser", "html"])
        .output()
        .unwrap();
    assert!(html.status.success());
    let html = String::from_utf8(html.stdout).unwrap();
    assert!(html.contains("BucketWarden Console"));
    assert!(html.contains("feat:bucketwarden.ui.browser.login-submit"));

    let css = bucketwarden()
        .args(["ui", "browser", "css"])
        .output()
        .unwrap();
    assert!(css.status.success());
    assert!(String::from_utf8(css.stdout)
        .unwrap()
        .contains("@media(max-width:760px)"));

    let js = bucketwarden()
        .args(["ui", "browser", "js"])
        .output()
        .unwrap();
    assert!(js.status.success());
    assert!(String::from_utf8(js.stdout)
        .unwrap()
        .contains("window.BucketWardenUI"));
}

#[test]
fn global_version_reports_cli_build_identity() {
    let output = bucketwarden().arg("--version").output().unwrap();

    assert!(output.status.success());
    let stdout = String::from_utf8(output.stdout).unwrap();
    assert!(stdout.contains("bucketwarden-cli"));
    assert!(stdout.contains(env!("CARGO_PKG_VERSION")));
}

#[test]
fn health_alias_outputs_json() {
    let output = bucketwarden().arg("--health").output().unwrap();

    assert!(output.status.success());
    let value: Value = serde_json::from_slice(&output.stdout).unwrap();
    assert_eq!(value["status"], "ok");
    assert_eq!(value["bucket_count"], 0);
}

#[test]
fn global_config_quiet_and_verbose_flags_affect_operator_dispatch() {
    let path = operator_config();

    let validate = bucketwarden()
        .args(["--config"])
        .arg(&path)
        .args(["config", "validate"])
        .output()
        .unwrap();
    assert!(validate.status.success());
    let value: Value = serde_json::from_slice(&validate.stdout).unwrap();
    assert_eq!(value["status"], "valid");
    assert_eq!(value["clock_epoch_seconds"], 42);

    let quiet = bucketwarden().arg("--quiet").output().unwrap();
    assert!(quiet.status.success());
    assert!(quiet.stdout.is_empty());

    let verbose = bucketwarden()
        .args(["--verbose", "diagnostics"])
        .output()
        .unwrap();
    let _ = std::fs::remove_file(&path);
    assert!(verbose.status.success());
    let value: Value = serde_json::from_slice(&verbose.stdout).unwrap();
    assert_eq!(value["cli"]["verbosity"], 1);
    assert_eq!(value["cli"]["build"]["package"], "bucketwarden-cli");
}

#[test]
fn config_validate_accepts_valid_operator_config() {
    let path = operator_config();

    let output = bucketwarden()
        .args(["config", "validate", "--config"])
        .arg(&path)
        .output()
        .unwrap();
    let _ = std::fs::remove_file(&path);

    assert!(output.status.success());
    let value: Value = serde_json::from_slice(&output.stdout).unwrap();
    assert_eq!(value["status"], "valid");
    assert_eq!(value["key_id"], "test-key");
    assert_eq!(value["key_material_bytes"], 6);
    assert_eq!(value["clock_epoch_seconds"], 42);
}

#[test]
fn runtime_probe_commands_accept_config_flag() {
    let path = operator_config();

    for command in ["health", "readiness", "diagnostics"] {
        let output = bucketwarden()
            .args([command, "--config"])
            .arg(&path)
            .output()
            .unwrap();
        assert!(output.status.success(), "{command} should accept --config");
        let value: Value = serde_json::from_slice(&output.stdout).unwrap();
        assert!(value["status"].is_string());
    }

    let metrics = bucketwarden()
        .args(["metrics", "--config"])
        .arg(&path)
        .output()
        .unwrap();
    assert!(metrics.status.success());
    assert!(String::from_utf8(metrics.stdout)
        .unwrap()
        .contains("bucketwarden_bucket_count"));

    let audit = bucketwarden()
        .args(["audit", "export", "--config"])
        .arg(&path)
        .output()
        .unwrap();
    assert!(audit.status.success());

    let replication = bucketwarden()
        .args(["replication", "status", "--config"])
        .arg(&path)
        .output()
        .unwrap();
    let _ = std::fs::remove_file(&path);
    assert!(replication.status.success());
    let value: Value = serde_json::from_slice(&replication.stdout).unwrap();
    assert_eq!(value["status"], "ok");
}
