use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelCapabilities {
    pub supports_function_calling: bool,
    pub supports_parallel_function_calling: bool,
    pub supports_tool_choice: bool,
    pub supports_response_schema: bool,
    pub supports_system_messages: bool,
    pub supports_web_search: bool,
    pub supports_url_context: bool,
    pub supports_vision: bool,
    pub supports_streaming: bool,
    pub max_tokens: Option<usize>,
    pub context_window: Option<usize>,
}

impl Default for ModelCapabilities {
    fn default() -> Self {
        Self {
            supports_function_calling: false,
            supports_parallel_function_calling: false,
            supports_tool_choice: false,
            supports_response_schema: false,
            supports_system_messages: true,
            supports_web_search: false,
            supports_url_context: false,
            supports_vision: false,
            supports_streaming: true,
            max_tokens: None,
            context_window: None,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_model_capabilities_default() {
        let caps = ModelCapabilities::default();
        assert!(!caps.supports_function_calling);
        assert!(!caps.supports_parallel_function_calling);
        assert!(!caps.supports_tool_choice);
        assert!(!caps.supports_response_schema);
        assert!(caps.supports_system_messages);
        assert!(!caps.supports_web_search);
        assert!(!caps.supports_url_context);
        assert!(!caps.supports_vision);
        assert!(caps.supports_streaming);
        assert!(caps.max_tokens.is_none());
        assert!(caps.context_window.is_none());
    }

    #[test]
    fn test_model_capabilities_custom() {
        let caps = ModelCapabilities {
            supports_function_calling: true,
            supports_parallel_function_calling: true,
            supports_tool_choice: true,
            supports_response_schema: true,
            supports_system_messages: true,
            supports_web_search: true,
            supports_url_context: true,
            supports_vision: true,
            supports_streaming: true,
            max_tokens: Some(4096),
            context_window: Some(128000),
        };
        assert!(caps.supports_function_calling);
        assert!(caps.supports_vision);
        assert_eq!(caps.max_tokens, Some(4096));
        assert_eq!(caps.context_window, Some(128000));
    }

    #[test]
    fn test_model_capabilities_clone() {
        let caps = ModelCapabilities {
            supports_function_calling: true,
            supports_vision: true,
            max_tokens: Some(8192),
            ..ModelCapabilities::default()
        };
        let cloned = caps.clone();
        assert_eq!(
            caps.supports_function_calling,
            cloned.supports_function_calling
        );
        assert_eq!(caps.max_tokens, cloned.max_tokens);
    }

    #[test]
    fn test_model_capabilities_serialization() {
        let caps = ModelCapabilities {
            supports_function_calling: true,
            max_tokens: Some(4096),
            ..ModelCapabilities::default()
        };
        let json = serde_json::to_value(&caps).unwrap();
        assert_eq!(json["supports_function_calling"], true);
        assert_eq!(json["max_tokens"], 4096);
        assert_eq!(json["supports_streaming"], true);
    }

    #[test]
    fn test_model_capabilities_deserialization() {
        let json = r#"{
            "supports_function_calling": true,
            "supports_parallel_function_calling": true,
            "supports_tool_choice": true,
            "supports_response_schema": false,
            "supports_system_messages": true,
            "supports_web_search": false,
            "supports_url_context": false,
            "supports_vision": true,
            "supports_streaming": true,
            "max_tokens": 8192,
            "context_window": 200000
        }"#;
        let caps: ModelCapabilities = serde_json::from_str(json).unwrap();
        assert!(caps.supports_function_calling);
        assert!(caps.supports_vision);
        assert_eq!(caps.max_tokens, Some(8192));
        assert_eq!(caps.context_window, Some(200000));
    }

    #[test]
    fn test_model_capabilities_partial_deserialization() {
        let json = r#"{
            "supports_function_calling": true,
            "supports_parallel_function_calling": false,
            "supports_tool_choice": false,
            "supports_response_schema": false,
            "supports_system_messages": true,
            "supports_web_search": false,
            "supports_url_context": false,
            "supports_vision": false,
            "supports_streaming": true
        }"#;
        let caps: ModelCapabilities = serde_json::from_str(json).unwrap();
        assert!(caps.max_tokens.is_none());
        assert!(caps.context_window.is_none());
    }
}
