pub mod article;
pub mod attachment;
pub mod ban;
pub mod category;
pub mod common;
pub mod conversation;
pub mod draft;
pub mod forward;
pub mod invite;
pub mod member;
pub mod message;
pub mod message_read;
pub mod notify;
pub mod pin;
pub mod presence;
pub mod reaction;
pub mod rooms;
pub mod search;
pub mod star;
pub mod thread;
pub mod voice;
pub mod workspace;

pub use common::{RoomInfo, UserInfo, WorkspaceInfo};

use model::channel::RoomMessageModel;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum ChannelEventType {
    MessageCreated,
    MessageUpdated,
    MessageDeleted,
    ReactionCreated,
    ReactionDeleted,
    MessageRead,
    ConversationUpdated,
    Custom(String),
}

impl ChannelEventType {
    pub fn as_str(&self) -> &str {
        match self {
            Self::MessageCreated => "message.created",
            Self::MessageUpdated => "message.updated",
            Self::MessageDeleted => "message.deleted",
            Self::ReactionCreated => "reaction.created",
            Self::ReactionDeleted => "reaction.deleted",
            Self::MessageRead => "message.read",
            Self::ConversationUpdated => "conversation.updated",
            Self::Custom(value) => value,
        }
    }
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ChannelEvent {
    pub room: Uuid,
    pub seq: Option<i64>,
    pub event_type: String,
    pub message: Option<RoomMessageModel>,
    pub payload: Option<Value>,
    #[serde(default)]
    pub sender_user: Option<UserInfo>,
}

impl ChannelEvent {
    pub fn message_created(message: RoomMessageModel) -> Self {
        Self {
            room: message.room,
            seq: Some(message.seq),
            event_type: ChannelEventType::MessageCreated.as_str().to_owned(),
            message: Some(message),
            payload: None,
            sender_user: None,
        }
    }

    pub fn message_created_with_sender(
        message: RoomMessageModel,
        sender: UserInfo,
    ) -> Self {
        Self {
            room: message.room,
            seq: Some(message.seq),
            event_type: ChannelEventType::MessageCreated.as_str().to_owned(),
            message: Some(message),
            payload: None,
            sender_user: Some(sender),
        }
    }

    pub fn custom(
        room: Uuid,
        event_type: impl Into<String>,
        payload: Value,
    ) -> Self {
        Self {
            room,
            seq: None,
            event_type: event_type.into(),
            message: None,
            payload: Some(payload),
            sender_user: None,
        }
    }
}
