//! SessionStream: uni-directional sink trait. Archive backends use
//! ArchiveBackend; live-write sinks like Langfuse use SessionStream.

use async_trait::async_trait;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use uuid::Uuid;

use super::bus_event::BusEvent;

#[async_trait]
pub trait SessionStream: Send + Sync {
    fn summary(&self) -> StreamSummary;
    fn scope(&self) -> StreamScope;
    async fn on_event(&self, event: &BusEvent) -> StreamOutcome;
    async fn shutdown(&self);
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StreamSummary {
    pub name:         String,
    pub kind:         StreamKind,
    pub target:       String,           // human-readable ("langfuse: https://…", "matrix: #room:server")
    pub active_since: DateTime<Utc>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum StreamKind {
    Matrix,
    Langfuse,
    Slack,
    Webhook,
    Custom,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "kind")]
pub enum StreamScope {
    Session     { scroll_id: Uuid },
    Connector   { connector_uid: Uuid },
    ArchiveWide { acknowledged: bool },
}

#[derive(Debug)]
pub enum StreamOutcome {
    Ok,
    Skipped,
    Failed(StreamError),
}

#[derive(Debug, Error)]
pub enum StreamError {
    #[error("transport: {0}")]       Transport(String),
    #[error("serialisation: {0}")]   Serialisation(String),
    #[error("rejected: {0}")]        Rejected(String),
    #[error("shutdown")]             Shutdown,
}
