use mimirs_agent::MimirAgent;
use mimirs_core::{AgentId, BlockId, MemoryAgent, MemoryBlock, MemoryInput};
use mimirs_ha::MemorySignal;
use mimirs_store::Urdarbrunnr;
use std::sync::Arc;
use tempfile::tempdir;
use tokio::time::{Duration, timeout};

#[tokio::test]
async fn test_signal_propagation() {
    let dir = tempdir().unwrap();
    let well = Arc::new(Urdarbrunnr::opna(dir.path(), 384).unwrap());
    let agent = MimirAgent::new(well, mimirs_agent::AgentConfig::default());

    // Subscribe to the event bus
    let mut rx = agent.bus().subscribe(AgentId::new());

    // Perform a store operation
    let input = MemoryInput {
        content: "Test signal propagation".to_string(),
        metadata: None,
        verifiability: None,
        scope: None,
        memory_class: None,
        source_session: None,
    };

    let _id = agent.store(input).await.unwrap();

    // Wait for the signal
    let signal = timeout(Duration::from_millis(100), rx.recv())
        .await
        .expect("Timeout waiting for signal")
        .expect("Receiver error");

    match signal {
        MemorySignal::MemoryStored { .. } => {
            // Success
        }
        _ => panic!("Expected MemoryStored signal, got {:?}", signal),
    }
}

#[tokio::test]
async fn test_block_attached_signal_and_wal() {
    let dir = tempdir().unwrap();
    let well = Arc::new(Urdarbrunnr::opna(dir.path(), 384).unwrap());
    let agent = MimirAgent::new(well, mimirs_agent::AgentConfig::default());

    // Subscribe to the event bus
    let mut rx = agent.bus().subscribe(AgentId::new());

    // Attach a block
    let block = MemoryBlock {
        id: BlockId::new(),
        label: "HA Test Block".to_string(),
        value: "Some state".to_string(),
        limit: 1000,
        pinned: false,
        shared_agents: vec![],
        read_only: false,
        memory_class: mimirs_core::MemoryClass::Episodic,
    };

    let block_id = agent.attach_block(block).await.unwrap();

    // Verify signal
    let signal = timeout(Duration::from_millis(100), rx.recv())
        .await
        .expect("Timeout waiting for signal")
        .expect("Receiver error");

    match signal {
        MemorySignal::BlockAttached { block_id: sid, .. } => {
            assert_eq!(sid, block_id);
        }
        _ => panic!("Expected BlockAttached signal, got {:?}", signal),
    }
}

#[tokio::test]
async fn test_consolidation_signal() {
    let dir = tempdir().unwrap();
    let well = Arc::new(Urdarbrunnr::opna(dir.path(), 384).unwrap());
    let agent = MimirAgent::new(well, mimirs_agent::AgentConfig::default());

    // Subscribe
    let mut rx = agent.bus().subscribe(AgentId::new());

    // Run consolidation
    agent.consolidate().await.unwrap();

    // Verify signal
    let signal = timeout(Duration::from_millis(100), rx.recv())
        .await
        .expect("Timeout waiting for signal")
        .expect("Receiver error");

    match signal {
        MemorySignal::ConsolidationCompleted { .. } => {
            // Success
        }
        _ => panic!("Expected ConsolidationCompleted signal, got {:?}", signal),
    }
}
