//! Tauri event relay.
//!
//! The stable serialisable event DTOs live in `backend::events`. This module
//! owns only the Tauri-specific relay: subscribing to the domain event bus and
//! emitting named Tauri events.

pub use backend::events::{
    AgentLaunchFailedDto, DomainEventDto, ModelServerStatusChangedDto, OrchestrationSourceDto,
    AGENT_LAUNCH_FAILED, DOMAIN_EVENT, MODEL_SERVER_STATUS_CHANGED,
};
use domain::events::DomainEvent;
use infrastructure::TokioBroadcastEventBus;
use tauri::{AppHandle, Emitter};

/// Subscribes the relay to the bus and spawns a background task that forwards
/// every non-PTY [`DomainEvent`] to the frontend as Tauri events.
///
/// High-frequency `PtyOutput` is intentionally not relayed through this global
/// event; it goes through per-session PTY channels instead.
pub fn spawn_relay(app: AppHandle, bus: &TokioBroadcastEventBus) {
    use tokio::sync::broadcast::error::RecvError;

    let mut rx = bus.raw_receiver();
    tauri::async_runtime::spawn(async move {
        loop {
            match rx.recv().await {
                Ok(event) => {
                    if matches!(event, DomainEvent::PtyOutput { .. }) {
                        continue;
                    }

                    let dto = DomainEventDto::from(&event);
                    let _ = app.emit(DOMAIN_EVENT, dto);

                    match &event {
                        DomainEvent::ModelServerStatusChanged { server_id, status } => {
                            let _ = app.emit(
                                MODEL_SERVER_STATUS_CHANGED,
                                ModelServerStatusChangedDto {
                                    server_id: server_id.to_string(),
                                    status: status.into(),
                                },
                            );
                        }
                        DomainEvent::AgentLaunchFailed {
                            agent_id,
                            cause,
                            code,
                            message,
                        } => {
                            let _ = app.emit(
                                AGENT_LAUNCH_FAILED,
                                AgentLaunchFailedDto {
                                    agent_id: agent_id.to_string(),
                                    cause: cause.clone(),
                                    code: code.clone(),
                                    message: message.clone(),
                                },
                            );
                        }
                        _ => {}
                    }
                }
                Err(RecvError::Lagged(_)) => continue,
                Err(RecvError::Closed) => break,
            }
        }
    });
}
