// Tests for mecha10_behavior_runtime::composition

use async_trait::async_trait;
use mecha10_behavior_runtime::prelude::*;

#[derive(Debug)]
struct MockBehavior {
    status: NodeStatus,
    tick_count: usize,
}

impl MockBehavior {
    fn new(status: NodeStatus) -> Self {
        Self { status, tick_count: 0 }
    }
}

#[async_trait]
impl BehaviorNode for MockBehavior {
    async fn tick(&mut self, _ctx: &Context) -> anyhow::Result<NodeStatus> {
        self.tick_count += 1;
        Ok(self.status)
    }
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_sequence_all_succeed() {
    let ctx = Context::new("test").await.unwrap();
    let mut sequence = SequenceNode::new(vec![
        Box::new(MockBehavior::new(NodeStatus::Success)),
        Box::new(MockBehavior::new(NodeStatus::Success)),
    ]);

    let status = sequence.run_until_complete(&ctx).await.unwrap();
    assert_eq!(status, NodeStatus::Success);
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_sequence_one_fails() {
    let ctx = Context::new("test").await.unwrap();
    let mut sequence = SequenceNode::new(vec![
        Box::new(MockBehavior::new(NodeStatus::Success)),
        Box::new(MockBehavior::new(NodeStatus::Failure)),
    ]);

    let status = sequence.run_until_complete(&ctx).await.unwrap();
    assert_eq!(status, NodeStatus::Failure);
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_selector_first_succeeds() {
    let ctx = Context::new("test").await.unwrap();
    let mut selector = SelectOrNode::new(vec![
        Box::new(MockBehavior::new(NodeStatus::Success)),
        Box::new(MockBehavior::new(NodeStatus::Failure)),
    ]);

    let status = selector.run_until_complete(&ctx).await.unwrap();
    assert_eq!(status, NodeStatus::Success);
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_selector_all_fail() {
    let ctx = Context::new("test").await.unwrap();
    let mut selector = SelectOrNode::new(vec![
        Box::new(MockBehavior::new(NodeStatus::Failure)),
        Box::new(MockBehavior::new(NodeStatus::Failure)),
    ]);

    let status = selector.run_until_complete(&ctx).await.unwrap();
    assert_eq!(status, NodeStatus::Failure);
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_parallel_require_all() {
    let ctx = Context::new("test").await.unwrap();
    let mut parallel = ParallelNode::new(
        vec![
            Box::new(MockBehavior::new(NodeStatus::Success)),
            Box::new(MockBehavior::new(NodeStatus::Success)),
        ],
        ParallelPolicy::RequireAll,
    );

    let status = parallel.run_until_complete(&ctx).await.unwrap();
    assert_eq!(status, NodeStatus::Success);
}

#[tokio::test]
#[ignore = "Requires Redis infrastructure"]
async fn test_parallel_require_one() {
    let ctx = Context::new("test").await.unwrap();
    let mut parallel = ParallelNode::new(
        vec![
            Box::new(MockBehavior::new(NodeStatus::Success)),
            Box::new(MockBehavior::new(NodeStatus::Failure)),
        ],
        ParallelPolicy::RequireOne,
    );

    let status = parallel.run_until_complete(&ctx).await.unwrap();
    assert_eq!(status, NodeStatus::Success);
}
