//! Integration tests for `mcptest tool-bench run`.
//!
//! Drives the binary over the shipped benchmark example (deterministic, no
//! model) and over a synthetic spec, asserting the human summary, the JSON
//! report shape, and the `--min-drop` gate's exit code.

use assert_cmd::Command;
use predicates::prelude::*;

fn mcptest() -> Command {
    Command::cargo_bin("mcptest").expect("binary builds")
}

/// Workspace root, so the example path resolves regardless of the test CWD.
fn workspace_root() -> std::path::PathBuf {
    std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
        .ancestors()
        .nth(2)
        .expect("crates/mcptest is two levels below the workspace root")
        .to_path_buf()
}

#[test]
fn the_shipped_example_runs_offline_and_shows_drops() {
    mcptest()
        .current_dir(workspace_root())
        .args([
            "tool-bench",
            "run",
            "examples/tool-description-bench/spec.yml",
        ])
        .assert()
        .success()
        .stdout(predicate::str::contains("selection accuracy: 100%"))
        .stdout(predicate::str::contains("largest selection drop: 33%"));
}

#[test]
fn min_drop_gate_passes_when_descriptions_matter() {
    mcptest()
        .current_dir(workspace_root())
        .args([
            "tool-bench",
            "run",
            "examples/tool-description-bench/spec.yml",
            "--min-drop",
            "0.3",
        ])
        .assert()
        .success();
}

#[test]
fn min_drop_gate_fails_when_a_mutation_does_not_move_selection() {
    let dir = tempfile::tempdir().unwrap();
    let spec = dir.path().join("spec.yml");
    // The dropped keyword is redundant (the description still matches via
    // "forecast"), so selection does not move and the strict gate fails.
    std::fs::write(
        &spec,
        r#"
catalog:
  tools:
    - name: alpha
      description: Return the weather forecast and temperature for a city.
intents:
  - query: what is the weather forecast
    gold: [alpha]
mutations:
  - tool: alpha
    kind: drop_keyword
    word: weather
"#,
    )
    .unwrap();

    mcptest()
        .args([
            "tool-bench",
            "run",
            spec.to_str().unwrap(),
            "--min-drop",
            "0.5",
        ])
        .assert()
        .failure()
        .stderr(predicate::str::contains("below --min-drop"));
}

#[test]
fn json_output_carries_the_report_shape() {
    mcptest()
        .current_dir(workspace_root())
        .args([
            "tool-bench",
            "run",
            "examples/tool-description-bench/spec.yml",
            "--json",
        ])
        .assert()
        .success()
        .stdout(predicate::str::contains("\"baseline\""))
        .stdout(predicate::str::contains("\"selection\""))
        .stdout(predicate::str::contains("\"mutations\""));
}
