// Tests for mecha10_behavior_runtime::registry

use async_trait::async_trait;
use mecha10_behavior_runtime::prelude::*;
use serde_json::json;

#[derive(Debug)]
struct TestBehavior {
    _value: f64,
}

#[async_trait]
impl BehaviorNode for TestBehavior {
    async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
        Ok(NodeStatus::Success)
    }

    fn name(&self) -> &str {
        "test_behavior"
    }
}

#[test]
fn test_register_and_create() {
    let mut registry = NodeRegistry::new();

    registry.register("test", |config| {
        let _value = config.get("value").and_then(|v| v.as_f64()).unwrap_or(0.0);
        Ok(Box::new(TestBehavior { _value }))
    });

    let node = registry.create("test", json!({"value": 42.0})).unwrap();
    assert_eq!(node.name(), "test_behavior");
}

#[test]
fn test_create_missing_type() {
    let registry = NodeRegistry::new();
    let result = registry.create("missing", json!({}));
    assert!(result.is_err());
    assert!(result.unwrap_err().to_string().contains("not registered"));
}

#[test]
fn test_contains() {
    let mut registry = NodeRegistry::new();
    registry.register("test", |_| Ok(Box::new(TestBehavior { _value: 0.0 })));

    assert!(registry.contains("test"));
    assert!(!registry.contains("missing"));
}

#[test]
fn test_registered_types() {
    let mut registry = NodeRegistry::new();
    registry.register("test1", |_| Ok(Box::new(TestBehavior { _value: 0.0 })));
    registry.register("test2", |_| Ok(Box::new(TestBehavior { _value: 0.0 })));

    let types = registry.registered_types();
    assert_eq!(types.len(), 2);
    assert!(types.contains(&"test1".to_string()));
    assert!(types.contains(&"test2".to_string()));
}

#[test]
fn test_len_and_is_empty() {
    let mut registry = NodeRegistry::new();
    assert!(registry.is_empty());
    assert_eq!(registry.len(), 0);

    registry.register("test", |_| Ok(Box::new(TestBehavior { _value: 0.0 })));
    assert!(!registry.is_empty());
    assert_eq!(registry.len(), 1);
}

#[test]
fn test_clone() {
    let mut registry = NodeRegistry::new();
    registry.register("test", |_| Ok(Box::new(TestBehavior { _value: 0.0 })));

    let cloned = registry.clone();
    assert!(cloned.contains("test"));
    assert_eq!(cloned.len(), 1);
}
