//! Suite and dataset interoperability with the wider eval ecosystem (WOR-1431).
//!
//! Teams arrive with promptfoo configs, DeepEval datasets, and mcp-eval task
//! suites. This module bridges those into mcptest and back out again:
//!
//! - import (promptfoo, DeepEval, mcp-eval) reuses [`crate::benchmark_import`]
//!   to render a runnable mcptest agent suite, plus [`unsupported_warnings`] so
//!   a lossy conversion says what it dropped.
//! - export turns a mcptest suite into a neutral [`PortableDataset`] stamped
//!   with mcptest provenance.
//! - dataset builds a starter suite from a `tools/list` snapshot or a registry
//!   export, so an MCP-native surface becomes a runnable suite.
//!
//! Native mcptest YAML stays the canonical authoring surface; this is the
//! bridge for teams who already have suites elsewhere.

mod dataset;
mod export;
mod warnings;

pub use dataset::{from_registry, from_tools_list};
pub use export::{
    export_suite, PortableCase, PortableDataset, PortableExpect, INTEROP_SCHEMA_VERSION,
};
pub use warnings::unsupported_warnings;

#[cfg(test)]
mod tests {
    use super::*;
    use crate::benchmark_import::{import_tasks, BenchmarkKind};
    use serde_json::json;

    #[test]
    fn imports_a_deepeval_dataset_of_goldens() {
        let doc = json!({
            "goldens": [
                {"input": "What is 2+2?", "expected_output": "4"},
                {"input": "Capital of France?", "expected_output": "Paris"}
            ],
            "metrics": ["answer_relevancy"]
        });
        let (tasks, skipped) = import_tasks(&doc, BenchmarkKind::DeepEval);
        assert_eq!(tasks.len(), 2);
        assert!(skipped.is_empty());
        assert_eq!(tasks[0].prompt, "What is 2+2?");
        let warns = unsupported_warnings(&doc, BenchmarkKind::DeepEval);
        assert!(warns.iter().any(|w| w.contains("metrics")));
    }

    #[test]
    fn imports_an_mcp_eval_task_suite() {
        let doc = json!({
            "tasks": [
                {"name": "list files", "prompt": "List the files in /tmp", "expected_output": "ok"}
            ],
            "setup": {"command": "spin-up"}
        });
        let (tasks, _) = import_tasks(&doc, BenchmarkKind::McpEval);
        assert_eq!(tasks.len(), 1);
        assert_eq!(tasks[0].name, "list files");
        let warns = unsupported_warnings(&doc, BenchmarkKind::McpEval);
        assert!(warns.iter().any(|w| w.contains("setup")));
    }

    #[test]
    fn promptfoo_model_graded_assert_warns() {
        let doc = json!({
            "providers": ["openai:gpt-4"],
            "tests": [{"vars": {"prompt": "hi"}, "assert": [{"type": "llm-rubric", "value": "polite"}]}]
        });
        let warns = unsupported_warnings(&doc, BenchmarkKind::Promptfoo);
        assert!(warns.iter().any(|w| w.contains("providers")));
        assert!(warns
            .iter()
            .any(|w| w.contains("map to no mcptest matcher")));
    }

    #[test]
    fn builds_a_starter_dataset_from_a_tools_list_snapshot() {
        let snapshot = json!({
            "tools": [
                {"name": "get_weather", "description": "Look up the weather"},
                {"name": "send_email"}
            ]
        });
        let tasks = from_tools_list(&snapshot);
        assert_eq!(tasks.len(), 2);
        assert!(tasks[0].prompt.contains("get_weather"));
        assert!(tasks[0].prompt.contains("Look up the weather"));
    }

    #[test]
    fn builds_a_starter_dataset_from_a_registry_export() {
        let export = json!({"servers": [{"name": "acme-db", "description": "A database server"}]});
        let tasks = from_registry(&export);
        assert_eq!(tasks.len(), 1);
        assert!(tasks[0].prompt.contains("acme-db"));
    }

    #[test]
    fn exports_a_mcptest_suite_into_a_portable_dataset() {
        let suite_yaml = r#"
servers:
  weather:
    command: ["./weather"]
agents:
  - name: forecast
    model: claude-sonnet-4-5
    servers: [weather]
    prompt: What is the weather in Paris?
    expect:
      - target: final_response
        matcher:
          contains: Paris
"#;
        let suite: serde_yaml::Value = serde_yaml::from_str(suite_yaml).unwrap();
        let (dataset, skipped) = export_suite(&suite, "weather.yaml");
        assert!(skipped.is_empty());
        assert_eq!(dataset.generated_by, "mcptest");
        assert_eq!(dataset.cases.len(), 1);
        assert_eq!(dataset.cases[0].name, "forecast");
        let expect = dataset.cases[0].expect.as_ref().unwrap();
        assert_eq!(expect.kind, "contains");
        assert_eq!(expect.value, "Paris");
    }
}
