//! Session persistence hooks.
//!
//! Provides a pluggable storage interface so callers can persist and restore
//! session snapshots across restarts (DB/Redis/etc.).

use std::collections::{HashMap, HashSet};

use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::protocol::capabilities::ClientCapabilities;
use crate::protocol::types::Implementation;

/// Serializable snapshot of a session's durable fields.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SessionSnapshot {
    /// Session ID
    pub id: String,
    /// Client information (set during initialize)
    pub client_info: Option<Implementation>,
    /// Client capabilities (set during initialize)
    pub capabilities: Option<ClientCapabilities>,
    /// Negotiated protocol version
    pub protocol_version: Option<String>,
    /// Per-session state values
    #[serde(default)]
    pub state: HashMap<String, Value>,
    /// Tools hidden from this session
    #[serde(default)]
    pub tool_hidden: HashSet<String>,
    /// Tool aliases (alias -> actual name)
    #[serde(default)]
    pub tool_aliases: HashMap<String, String>,
    /// Resources hidden from this session
    #[serde(default)]
    pub resource_hidden: HashSet<String>,
    /// Prompts hidden from this session
    #[serde(default)]
    pub prompt_hidden: HashSet<String>,
}

/// Session store interface for persistence across restarts.
///
/// Implementations should be fast and non-blocking where possible. If the
/// backend is async, consider enqueueing updates or using a background worker.
pub trait SessionStore: Send + Sync {
    /// Load a snapshot for a session ID, if present.
    fn load(&self, session_id: &str) -> Option<SessionSnapshot>;

    /// Persist a session snapshot.
    fn save(&self, snapshot: SessionSnapshot);

    /// Remove a persisted snapshot for a session ID.
    fn delete(&self, session_id: &str);

    /// List all persisted session IDs.
    fn list(&self) -> Vec<String> {
        Vec::new()
    }
}

/// No-op session store (default).
#[derive(Default)]
pub struct NullSessionStore;

impl SessionStore for NullSessionStore {
    fn load(&self, _session_id: &str) -> Option<SessionSnapshot> {
        None
    }

    fn save(&self, _snapshot: SessionSnapshot) {}

    fn delete(&self, _session_id: &str) {}

    fn list(&self) -> Vec<String> {
        Vec::new()
    }
}
