//! Tests for LlmSchema derive macro
//!
//! These tests verify that the macro can generate valid JSON schemas
//! suitable for LLM function calling

use schemabound_schema::LlmSchema;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, JsonSchema, LlmSchema, Debug)]
struct MockOrganization {
    id: String,
    name: String,
    slug: String,
    owner_id: String,
}

#[derive(Serialize, Deserialize, JsonSchema, LlmSchema, Debug)]
struct MockUser {
    id: String,
    email: String,
    name: String,
}

#[test]
fn llm_schema_derives_json_schema() {
    let schema = MockOrganization::llm_schema();

    assert!(
        schema.schema.object.is_some(),
        "Schema should have object validation"
    );
    let obj = schema.schema.object.unwrap();

    // Verify all properties are present
    assert!(obj.properties.contains_key("id"), "Should have id property");
    assert!(
        obj.properties.contains_key("name"),
        "Should have name property"
    );
    assert!(
        obj.properties.contains_key("slug"),
        "Should have slug property"
    );
    assert!(
        obj.properties.contains_key("owner_id"),
        "Should have owner_id property"
    );
}

#[test]
fn llm_schema_has_required_fields() {
    let schema = MockOrganization::llm_schema();
    let obj = schema.schema.object.unwrap();

    // All fields should be required
    assert!(!obj.required.is_empty(), "Should have required fields");
}

#[test]
fn llm_schema_works_with_multiple_types() {
    let org_schema = MockOrganization::llm_schema();
    let user_schema = MockUser::llm_schema();

    // Both should produce valid schemas
    assert!(org_schema.schema.object.is_some());
    assert!(user_schema.schema.object.is_some());

    // They should be different
    let org_props = org_schema.schema.object.unwrap().properties;
    let user_props = user_schema.schema.object.unwrap().properties;

    assert_ne!(
        org_props.len(),
        user_props.len(),
        "Different types should have different property counts"
    );
}

#[test]
fn llm_schema_is_serializable() {
    let schema = MockOrganization::llm_schema();

    // Should be able to serialize to JSON
    let json = serde_json::to_string(&schema).expect("Should serialize to JSON");
    assert!(!json.is_empty(), "Serialized schema should not be empty");

    // Should be valid JSON that can be deserialized
    let _: serde_json::Value = serde_json::from_str(&json).expect("Should be valid JSON");
}
