//! Integration tests for `mcptest ablation` (with/without-tools uplift).
//!
//! These prove the plumbing offline: the command loads a suite, connects the
//! agent's server, runs both arms (tools attached and withheld), scores each,
//! and emits the report. The model is forced onto the canned stub (an unknown
//! model family plus `--allow-stub-provider`), so both arms get the same
//! response and the uplift is zero regardless of any key in the environment.
//! The uplift math itself is covered by the `mcptest_core::ablation` unit tests
//! and the `agent_ablation` end-to-end test.

use std::io::Write;

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

/// The mcptest binary, used both as the command under test and as the stdio
/// MCP server the agent connects to.
const BIN: &str = env!("CARGO_BIN_EXE_mcptest");

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

/// Write a suite whose single-prompt agent targets `mcptest mcp-server` and is
/// scored by a deterministic expectation the stub response satisfies.
fn write_suite(dir: &tempfile::TempDir, body: &str) -> std::path::PathBuf {
    let path = dir.path().join("ablation.yml");
    let mut f = std::fs::File::create(&path).unwrap();
    f.write_all(body.as_bytes()).unwrap();
    path
}

fn smoke_suite() -> String {
    // Single-quote the binary path: on Windows CARGO_BIN_EXE is a backslash
    // path, and a backslash in a double-quoted YAML scalar is an invalid escape.
    format!(
        r#"servers:
  s:
    command: ['{BIN}', 'mcp-server']
agents:
  - name: smoke
    models: [stub-model]
    servers: [s]
    prompt: say something
    max_turns: 2
    max_tokens: 64
    expect:
      - target: final_response
        matcher:
          icontains: stub
"#
    )
}

#[test]
fn ablation_runs_both_arms_and_reports_uplift() {
    let dir = tempfile::tempdir().unwrap();
    let suite = write_suite(&dir, &smoke_suite());
    mcptest()
        .arg("ablation")
        .arg(&suite)
        .arg("--allow-stub-provider")
        .assert()
        .success()
        .stdout(predicate::str::contains("uplift"));
}

#[test]
fn ablation_json_emits_the_report_shape() {
    let dir = tempfile::tempdir().unwrap();
    let suite = write_suite(&dir, &smoke_suite());
    mcptest()
        .arg("ablation")
        .arg(&suite)
        .arg("--allow-stub-provider")
        .arg("--json")
        .assert()
        .success()
        .stdout(predicate::str::contains("\"success_uplift\""));
}

#[test]
fn ablation_with_no_agents_exits_two() {
    let dir = tempfile::tempdir().unwrap();
    let suite = write_suite(
        &dir,
        &format!(
            r#"servers:
  s:
    command: ['{BIN}', 'mcp-server']
tools:
  - name: a tool exists
    server: s
    tool: echo
    expect:
      - target: result
        matcher:
          is-json: true
"#
        ),
    );
    mcptest()
        .arg("ablation")
        .arg(&suite)
        .arg("--allow-stub-provider")
        .assert()
        .code(2);
}
