//! 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, PartialEq, Eq, 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,
    /// True when the server marks the channel as password-protected.
    pub has_password: bool,
    /// Talk power threshold required to speak in this channel.
    /// `None` means no talk-power restriction.
    pub needed_talk_power: Option<i32>,
}

/// The target scope of a text message (mirrors TS3 `TextMessageTargetMode`).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum MessageTarget {
    /// Broadcast to entire server.
    Server,
    /// Broadcast to current channel.
    Channel,
    /// Private message to a specific client.
    Client(u64),
    /// Poke a specific client.
    Poke(u64),
}

/// An in-channel text message from a specific client.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ChatMessage {
    /// The client id of the sender.
    pub sender_id: ClientId,
    /// Nickname of the sender, preserved verbatim.
    pub sender_name: String,
    /// Message content, preserved verbatim.
    pub message: String,
    /// Target scope of this message.
    pub target: MessageTarget,
}

/// A server-activity notification derived from TeamSpeak bookkeeping events.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ServerActivity {
    /// Human-readable activity line.
    pub message: String,
}

/// One connected client on the server.
#[derive(Debug, Clone, PartialEq, Eq, 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,
    /// True when this client has muted microphone/input capture.
    pub input_muted: bool,
    /// True when this client has muted speaker/output audio.
    pub output_muted: bool,
    /// True when recent inbound voice activity was observed for this client.
    pub is_speaking: bool,
    /// True for TeamSpeak ServerQuery clients.
    pub is_server_query: bool,
    /// Current talk power value assigned by the server.
    pub talk_power: i32,
    /// True when the server has granted talk power regardless of numeric value.
    pub talk_power_granted: bool,
}

/// Best-effort profile and live connection details for one online
/// client, fetched through the normal TeamSpeak client protocol.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ClientProfile {
    /// Stable online client id.
    pub id: ClientId,
    /// Channel the client is currently in.
    pub channel: ChannelId,
    /// Nickname, preserved verbatim per ADR-008.
    pub name: String,
    /// TeamSpeak unique id encoded in the canonical base64 form.
    pub unique_id: String,
    /// Stable TeamSpeak database id, when visible.
    pub database_id: Option<u64>,
    /// ISO country code, when the server exposes one.
    pub country_code: String,
    /// User description, when visible.
    pub description: String,
    /// Client version string, populated by `clientgetvariables`.
    pub version: String,
    /// Client platform string, populated by `clientgetvariables`.
    pub platform: String,
    /// Account creation time as Unix seconds.
    pub created_unix_seconds: Option<i64>,
    /// Last connection time as Unix seconds.
    pub last_connected_unix_seconds: Option<i64>,
    /// Total historical connections, when visible.
    pub connections_total: Option<u64>,
    /// Current online duration in seconds, when visible.
    pub online_seconds: Option<i64>,
    /// Current idle time in milliseconds, when visible.
    pub idle_milliseconds: Option<i64>,
    /// Current ping in milliseconds, when visible.
    pub ping_milliseconds: Option<i64>,
    /// Client address. Empty when permission-gated.
    pub client_address: String,
    /// Resolved server group names for the online client.
    pub server_groups: Vec<String>,
    /// Resolved channel group name for the online client.
    pub channel_group: String,
    /// TeamSpeak avatar file path suffix, when an avatar hash is present.
    pub avatar_path: String,
    /// Downloaded bytes this month.
    pub bytes_downloaded_month: Option<u64>,
    /// Uploaded bytes this month.
    pub bytes_uploaded_month: Option<u64>,
    /// Downloaded bytes across all time.
    pub bytes_downloaded_total: Option<u64>,
    /// Uploaded bytes across all time.
    pub bytes_uploaded_total: Option<u64>,
    /// Client-to-server total packet loss ratio.
    pub packet_loss_client_to_server_total: Option<f32>,
    /// Server-to-client total packet loss ratio.
    pub packet_loss_server_to_client_total: Option<f32>,
}

/// Snapshot of the server's published state at a moment in time.
#[derive(Debug, Clone, PartialEq, Eq, 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>,
    /// Our own client id as the server published it. Used by the
    /// core session to confirm that a `move_to_channel` request
    /// actually applied (vs being silently rejected by the
    /// server's permission check).
    pub own_client_id: u64,
}

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