use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use uuid::Uuid;

/// Channel type discriminator.
/// Text chat channels keep the historical "room" naming for familiarity.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ChannelType {
    /// Text-based chat room
    Room,
    /// Voice channel
    Voice,
    /// Waterfall / masonry article post channel
    Article,
}

impl Default for ChannelType {
    fn default() -> Self {
        Self::Room
    }
}

impl std::fmt::Display for ChannelType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::Room => write!(f, "room"),
            Self::Voice => write!(f, "voice"),
            Self::Article => write!(f, "article"),
        }
    }
}

impl From<&str> for ChannelType {
    fn from(s: &str) -> Self {
        match s {
            "voice" => Self::Voice,
            "article" => Self::Article,
            _ => Self::Room,
        }
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, FromRow)]
pub struct ChannelModel {
    pub id: Uuid,
    pub wk: Uuid,
    pub parent: Option<Uuid>,
    pub name: String,
    pub topic: Option<String>,
    /// Legacy DB column; mapped to `channel_type` in app logic.
    #[sqlx(rename = "room_type")]
    pub channel_type: String,
    pub position: i32,
    pub is_private: bool,
    pub is_archived: bool,
    pub ai_enabled: bool,
    pub created_by: Uuid,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub deleted_at: Option<DateTime<Utc>>,
}

impl ChannelModel {
    /// Return the parsed channel type enum.
    pub fn channel_kind(&self) -> ChannelType {
        ChannelType::from(self.channel_type.as_str())
    }

    /// Convenience: true when this is a text-chat room.
    pub fn is_room(&self) -> bool {
        self.channel_kind() == ChannelType::Room
    }

    /// Convenience: true when this is a voice channel.
    pub fn is_voice(&self) -> bool {
        self.channel_kind() == ChannelType::Voice
    }

    /// Convenience: true when this is an article post channel.
    pub fn is_article(&self) -> bool {
        self.channel_kind() == ChannelType::Article
    }
}
