use serde::Serialize;
use uuid::Uuid;

use crate::event::{
    RoomInfo, WorkspaceInfo, article, attachment, ban, category, conversation, draft,
    forward, invite, member, message, message_read, notify, pin, presence,
    reaction, rooms, search, star, thread, voice, workspace,
};

#[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum WsOutEvent {
    Pong {
        protocol_version: u32,
    },
    Error(WsError),
    CsrfToken {
        token: String,
    },
    RoomCreated {
        room: RoomInfo,
        data: rooms::RoomCreatedService,
    },
    RoomDeleted {
        room: RoomInfo,
        data: rooms::RoomDeletedService,
    },
    RoomRenamed {
        room: RoomInfo,
        data: rooms::RoomRenamedService,
    },
    RoomTopicUpdated {
        room: RoomInfo,
        data: rooms::RoomTopicUpdatedService,
    },
    RoomSettingsUpdated {
        room: RoomInfo,
        data: rooms::RoomSettingsUpdatedService,
    },
    RoomMoved {
        room: RoomInfo,
        data: rooms::RoomMovedService,
    },
    MessageNew {
        room: RoomInfo,
        data: message::MessageNewService,
    },
    MessageEdited {
        room: RoomInfo,
        data: message::MessageEditedService,
    },
    MessageRevoked {
        room: RoomInfo,
        data: message::MessageRevokedService,
    },
    MessageStreamStart {
        room: RoomInfo,
        data: message::MessageStreamStartService,
    },
    MessageStreamChunk {
        room: RoomInfo,
        data: message::MessageStreamChunkService,
    },
    MessageStreamDone {
        room: RoomInfo,
        data: message::MessageStreamDoneService,
    },
    MessageList {
        room: RoomInfo,
        data: message::MessageListService,
    },
    MemberJoined {
        room: RoomInfo,
        data: member::MemberJoinedService,
    },
    MemberRemoved {
        room: RoomInfo,
        data: member::MemberRemovedService,
    },
    ReadReceipt {
        room: RoomInfo,
        data: member::ReadReceiptService,
    },
    TypingStart {
        room: RoomInfo,
        data: member::TypingStartService,
    },
    TypingStop {
        room: RoomInfo,
        data: member::TypingStopService,
    },
    ReactionAdded {
        room: RoomInfo,
        data: reaction::ReactionAddedService,
    },
    ReactionRemoved {
        room: RoomInfo,
        data: reaction::ReactionRemovedService,
    },
    ReactionBatchUpdated {
        room: RoomInfo,
        data: reaction::ReactionBatchUpdatedService,
    },
    ThreadCreated {
        room: RoomInfo,
        data: thread::ThreadCreatedService,
    },
    ThreadUpdated {
        room: RoomInfo,
        data: thread::ThreadUpdatedService,
    },
    ThreadResolved {
        room: RoomInfo,
        data: thread::ThreadResolvedService,
    },
    ThreadArchived {
        room: RoomInfo,
        data: thread::ThreadArchivedService,
    },
    ThreadList {
        data: thread::ThreadListService,
    },
    CategoryCreated {
        workspace: WorkspaceInfo,
        data: category::CategoryCreatedService,
    },
    CategoryUpdated {
        workspace: WorkspaceInfo,
        data: category::CategoryUpdatedService,
    },
    CategoryDeleted {
        workspace: WorkspaceInfo,
        data: category::CategoryDeletedService,
    },
    PinAdded {
        room: RoomInfo,
        data: pin::PinAddedService,
    },
    PinRemoved {
        room: RoomInfo,
        data: pin::PinRemovedService,
    },
    WorkspaceRoomCreated {
        workspace: WorkspaceInfo,
        data: workspace::WorkspaceRoomCreatedService,
    },
    WorkspaceRoomDeleted {
        workspace: WorkspaceInfo,
        data: workspace::WorkspaceRoomDeletedService,
    },
    DraftSaved {
        room: RoomInfo,
        data: draft::DraftSavedService,
    },
    DraftCleared {
        room: RoomInfo,
        data: draft::DraftClearedService,
    },
    SearchResult {
        data: search::SearchResultService,
    },
    NotifyCreated {
        data: notify::NotifyCreatedService,
    },
    NotifyRead {
        data: notify::NotifyReadService,
    },
    PresenceChanged {
        data: presence::PresenceChangedService,
    },
    CustomStatusUpdated {
        data: presence::CustomStatusUpdatedService,
    },
    InviteCreated {
        data: invite::InviteCreatedService,
    },
    InviteAccepted {
        data: invite::InviteAcceptedService,
    },
    AttachmentUploaded {
        room: RoomInfo,
        data: attachment::AttachmentUploadedService,
    },
    UserBanned {
        data: ban::BannedService,
    },
    UserUnbanned {
        data: ban::UnbannedService,
    },
    VoiceChannelJoined {
        room: RoomInfo,
        data: voice::VoiceChannelJoinedService,
    },
    VoiceChannelLeft {
        room: RoomInfo,
        data: voice::VoiceChannelLeftService,
    },
    ConversationPinned {
        room: RoomInfo,
        data: conversation::ConversationPinnedService,
    },
    ConversationUnpinned {
        room: RoomInfo,
        data: conversation::ConversationUnpinnedService,
    },
    ConversationMuted {
        room: RoomInfo,
        data: conversation::ConversationMutedService,
    },
    ConversationUnmuted {
        room: RoomInfo,
        data: conversation::ConversationUnmutedService,
    },
    ConversationUnreadUpdated {
        room: RoomInfo,
        data: conversation::ConversationUnreadUpdatedService,
    },
    ConversationList {
        data: Vec<conversation::ConversationSummary>,
    },
    MessageRead {
        room: RoomInfo,
        data: message_read::MessageReadService,
    },
    MessageReadBatch {
        room: RoomInfo,
        data: message_read::MessageReadBatchService,
    },
    MessageReaders {
        data: message_read::MessageReadersService,
    },
    MessageStarred {
        room: RoomInfo,
        data: star::MessageStarredService,
    },
    MessageUnstarred {
        room: RoomInfo,
        data: star::MessageUnstarredService,
    },
    StarredList {
        data: Vec<star::StarredMessageEntry>,
    },
    MessageForwarded {
        room: RoomInfo,
        data: forward::MessageForwardedService,
    },
    ArticleCreated {
        room: RoomInfo,
        data: article::ArticleCreatedService,
    },
    ArticleUpdated {
        room: RoomInfo,
        data: article::ArticleUpdatedService,
    },
    ArticleDeleted {
        room: RoomInfo,
        data: article::ArticleDeletedService,
    },
    ArticleList {
        data: article::ArticleListService,
    },
    ArticleDetail {
        data: article::ArticleDetail,
    },
    ArticleLiked {
        room: RoomInfo,
        data: article::ArticleLikedService,
    },
    ArticleUnliked {
        room: RoomInfo,
        data: article::ArticleUnlikedService,
    },
    ArticleCommentCreated {
        room: RoomInfo,
        data: article::ArticleCommentCreatedService,
    },
    ArticleCommentDeleted {
        room: RoomInfo,
        data: article::ArticleCommentDeletedService,
    },
    ArticleCommentList {
        data: article::ArticleCommentListService,
    },
    ArticleLikedUsers {
        data: article::ArticleLikedUsersService,
    },
    Response {
        request_id: Uuid,
        data: serde_json::Value,
    },
}

#[derive(Debug, Clone, Serialize)]
pub struct WsError {
    pub code: i32,
    pub error: String,
    pub message: String,
}
