// Tests for mecha10_behavior_runtime::execution

use async_trait::async_trait;
use mecha10_behavior_runtime::prelude::*;
use std::time::Duration;

#[derive(Debug)]
struct CounterBehavior {
    max_count: usize,
    count: usize,
}

impl CounterBehavior {
    fn new(max_count: usize) -> Self {
        Self { max_count, count: 0 }
    }
}

#[async_trait]
impl BehaviorNode for CounterBehavior {
    async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
        self.count += 1;
        if self.count >= self.max_count {
            Ok(NodeStatus::Success)
        } else {
            Ok(NodeStatus::Running)
        }
    }

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

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_executor_runs_until_complete() {
    let ctx = Context::new("test").await.unwrap();
    let behavior = Box::new(CounterBehavior::new(5));
    let mut executor = BehaviorExecutor::new(behavior, 100.0);

    let (status, stats) = executor.run_until_complete(&ctx).await.unwrap();
    assert_eq!(status, NodeStatus::Success);
    assert_eq!(stats.tick_count, 5);
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_executor_with_max_ticks() {
    let ctx = Context::new("test").await.unwrap();
    let behavior = Box::new(CounterBehavior::new(100)); // Won't complete in time
    let mut executor = BehaviorExecutor::new(behavior, 100.0).with_max_ticks(10);

    let result = executor.run_until_complete(&ctx).await;
    assert!(result.is_err());
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_executor_for_duration() {
    let ctx = Context::new("test").await.unwrap();
    let behavior = Box::new(CounterBehavior::new(1000)); // Won't complete in time
    let mut executor = BehaviorExecutor::new(behavior, 100.0);

    let (status, stats) = executor
        .run_for_duration(&ctx, Duration::from_millis(50))
        .await
        .unwrap();

    // Should have run for about 50ms at 100 Hz = ~5 ticks
    assert!(stats.tick_count >= 3);
    assert!(stats.tick_count <= 7);
    assert_eq!(status, NodeStatus::Running); // Not complete
}
