//! Integration test: `JobQueueEscalation::with_audit` emits `OpsEvent`s for
//! `raise` and `resolve` state changes.

use klieo_bus_memory::MemoryBus;
use klieo_core::memory::{Episode, EpisodicMemory};
use klieo_core::test_utils::InMemoryEpisodic;
use klieo_core::RunId;
use klieo_ops::escalation::{
    Escalation, EscalationTicket, JobQueueEscalation, Resolution, ResolutionOutcome, Severity,
};
use klieo_ops::ops_event::OpsEvent;
use std::sync::Arc;

#[tokio::test]
async fn raise_and_resolve_emit_ops_events() {
    let episodic = Arc::new(InMemoryEpisodic::default());
    let run_id = RunId::new();
    let bus = MemoryBus::new();
    let esc = JobQueueEscalation::new(bus.jobs.clone())
        .with_audit(episodic.clone() as Arc<dyn EpisodicMemory>, run_id);

    let ticket = EscalationTicket::new(Severity::High, "test reason", None, None);
    let id = esc.raise(ticket).await.expect("raise");
    let resolution = Resolution::new(ResolutionOutcome::Approved, None, vec![], vec![]);
    esc.resolve(id, resolution).await.expect("resolve");

    let events = episodic.replay(run_id).await.expect("replay");
    let ops: Vec<OpsEvent> = events
        .into_iter()
        .filter_map(|e| match e {
            Episode::Ops(payload) => OpsEvent::from_episode_payload(&payload),
            _ => None,
        })
        .collect();

    assert!(
        ops.iter()
            .any(|e| matches!(e, OpsEvent::EscalationRaised { .. })),
        "expected EscalationRaised event"
    );
    assert!(
        ops.iter()
            .any(|e| matches!(e, OpsEvent::EscalationResolved { .. })),
        "expected EscalationResolved event"
    );
}
