//! Public DTOs returned across the protocol boundary. All fields are
//! owned primitives or `String`s; no `tsclientlib` types leak.

use serde::{Deserialize, Serialize};

/// Opaque server-side channel identifier. Internal representation is
/// the upstream u64 but callers must treat it as opaque.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ChannelId(pub u64);

/// Opaque server-side client identifier.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ClientId(pub u64);

/// One channel in the server's tree.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChannelInfo {
    /// Stable channel id.
    pub id: ChannelId,
    /// Parent channel id; `ChannelId(0)` indicates a top-level channel.
    pub parent: ChannelId,
    /// Display name, preserved verbatim per ADR-008.
    pub name: String,
    /// Server-side ordering hint.
    pub order: i64,
}

/// One connected client on the server.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClientInfo {
    /// Stable client id.
    pub id: ClientId,
    /// Channel the client is currently in.
    pub channel: ChannelId,
    /// Nickname, preserved verbatim per ADR-008.
    pub name: String,
}

/// Snapshot of the server's published state at a moment in time.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerSnapshot {
    /// Server name.
    pub server_name: String,
    /// Server welcome banner. Contains markup from the upstream
    /// server (BBCode-like); not parsed here.
    pub welcome_message: String,
    /// Server platform string.
    pub platform: String,
    /// Server version string.
    pub version: String,
    /// All channels currently known.
    pub channels: Vec<ChannelInfo>,
    /// All clients currently known.
    pub clients: Vec<ClientInfo>,
}

impl ChannelId {
    /// The conventional root sentinel used by TeamSpeak-compatible
    /// servers for the top of the channel tree.
    pub const ROOT: ChannelId = ChannelId(0);
}
