//! Integration tests for `#[derive(KlieoResponse)]`.

use klieo_core::{parse_structured, KlieoResponse};
use klieo_macros::KlieoResponse;
use schemars::JsonSchema;
use serde::Deserialize;

#[derive(Debug, PartialEq, Deserialize, JsonSchema, KlieoResponse)]
struct ParsedReply {
    name: String,
    age: u32,
    tags: Vec<String>,
}

#[test]
fn derive_emits_json_schema_with_field_types() {
    // `JsonSchema` and `KlieoResponse` both define `json_schema`;
    // disambiguate explicitly so the test asserts the trait we care
    // about.
    let schema = <ParsedReply as KlieoResponse>::json_schema();
    // schemars 0.8 produces a top-level $schema + properties under
    // `properties` for object types. Walk the structure to assert the
    // declared field types surface correctly.
    let props = &schema["properties"];
    assert_eq!(props["name"]["type"], "string");
    // u32 is rendered as "integer" with format "uint32".
    assert_eq!(props["age"]["type"], "integer");
    assert_eq!(props["tags"]["type"], "array");
    assert_eq!(props["tags"]["items"]["type"], "string");
}

#[test]
fn derive_round_trips_via_parse_structured() {
    let raw = r#"{"name":"alice","age":30,"tags":["a","b"]}"#;
    let parsed: ParsedReply = parse_structured(raw).unwrap();
    assert_eq!(
        parsed,
        ParsedReply {
            name: "alice".into(),
            age: 30,
            tags: vec!["a".into(), "b".into()],
        }
    );
}

#[test]
fn derive_round_trips_with_code_fences() {
    let raw = "```json\n{\"name\":\"bob\",\"age\":7,\"tags\":[]}\n```";
    let parsed: ParsedReply = parse_structured(raw).unwrap();
    assert_eq!(
        parsed,
        ParsedReply {
            name: "bob".into(),
            age: 7,
            tags: vec![],
        }
    );
}
