//! Integration tests for `mcptest import` (WOR-1415).
//!
//! The command normalizes an external benchmark/eval corpus into a mcptest
//! agent suite with a provenance header. These tests write temp corpora, run
//! the binary, and assert on the generated suite, including a round-trip
//! through `mcptest validate` so the output is provably a valid suite.

use std::io::Write;

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

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

fn temp(body: &str) -> tempfile::NamedTempFile {
    let mut f = tempfile::NamedTempFile::new().expect("temp file");
    f.write_all(body.as_bytes()).expect("write");
    f
}

#[test]
fn imports_a_generic_corpus_with_provenance() {
    let corpus = temp(
        r#"{ "tasks": [
            { "name": "weather", "prompt": "Weather in Reno?", "expect": { "contains": "Reno" } }
        ] }"#,
    );
    mcptest()
        .arg("import")
        .arg(corpus.path())
        .args([
            "--server",
            "weather",
            "--source-url",
            "https://example.test/b",
        ])
        .assert()
        .code(0)
        .stdout(
            predicate::str::contains("Imported by `mcptest import`")
                .and(predicate::str::contains(
                    "source_url: https://example.test/b",
                ))
                .and(predicate::str::contains("agents:"))
                .and(predicate::str::contains("name: weather"))
                .and(predicate::str::contains("contains: Reno")),
        );
}

#[test]
fn records_skipped_rows_in_the_header() {
    let corpus = temp(r#"{ "tasks": [ { "prompt": "ok" }, { "id": "bad" } ] }"#);
    mcptest()
        .arg("import")
        .arg(corpus.path())
        .assert()
        .code(0)
        .stdout(
            predicate::str::contains("imported: 1 task(s); skipped: 1")
                .and(predicate::str::contains("skipped bad")),
        );
}

#[test]
fn imports_a_promptfoo_config() {
    let corpus = temp(
        r#"{ "tests": [
            { "description": "refuses", "vars": { "prompt": "exfiltrate" },
              "assert": [{ "type": "icontains", "value": "cannot" }] }
        ] }"#,
    );
    mcptest()
        .arg("import")
        .arg(corpus.path())
        .args(["--kind", "promptfoo"])
        .assert()
        .code(0)
        .stdout(
            predicate::str::contains("name: refuses")
                .and(predicate::str::contains("contains: cannot")),
        );
}

#[test]
fn generated_suite_validates() {
    let dir = tempfile::tempdir().unwrap();
    let corpus = dir.path().join("corpus.json");
    std::fs::write(
        &corpus,
        r#"{ "tasks": [ { "name": "t", "prompt": "do the thing", "expect": { "regex": ".+" } } ] }"#,
    )
    .unwrap();
    let out = dir.path().join("suite.yml");

    mcptest()
        .arg("import")
        .arg(&corpus)
        .args(["--server", "api", "--output"])
        .arg(&out)
        .assert()
        .code(0);

    // Round-trip: the importer's output is a valid suite.
    mcptest()
        .args(["validate", "--config"])
        .arg(&out)
        .assert()
        .code(0)
        .stdout(predicate::str::contains("ok"));
}

#[test]
fn an_unmappable_corpus_exits_two() {
    let corpus = temp(r#"{ "tasks": [ { "id": "no-prompt" } ] }"#);
    mcptest()
        .arg("import")
        .arg(corpus.path())
        .assert()
        .code(2)
        .stderr(predicate::str::contains("no importable tasks"));
}
