use uuid::Uuid;

use crate::event::{member, message, notify, reaction};
use crate::event::{RoomInfo, UserInfo};

use super::out_event::WsOutEvent;

pub struct EventDispatcher;

impl EventDispatcher {
    pub fn dispatch_message(
        room_id: Uuid,
        room_name: &str,
        msg: &model::channel::RoomMessageModel,
    ) -> WsOutEvent {
        let room = RoomInfo {
            id: room_id,
            name: room_name.to_string(),
        };
        WsOutEvent::MessageNew {
            room: room.clone(),
            data: message::MessageNewService {
                id: msg.id,
                seq: msg.seq,
                room,
                sender_type: "user".to_string(),
                sender: UserInfo::unknown(msg.author),
                thread: msg.thread,
                in_reply_to: msg.parent,
                content: msg.content.clone(),
                content_type: msg.content_type.clone(),
                pinned: msg.pinned,
                system_type: msg.system_type.clone(),
                metadata: msg.metadata.clone(),
                thinking_content: None,
                thinking_is_chunked: None,
                send_at: msg.created_at,
                reactions: vec![],
            },
        }
    }

    pub fn dispatch_typing_start(
        room_id: Uuid,
        _room_name: &str,
        user_id: Uuid,
        display_name: Option<String>,
    ) -> WsOutEvent {
        let user = UserInfo {
            id: user_id,
            username: display_name.clone().unwrap_or_default(),
            display_name: display_name.unwrap_or_default(),
            avatar_url: String::new(),
        };
        let room = RoomInfo::unknown(room_id);
        WsOutEvent::TypingStart {
            room: room.clone(),
            data: member::TypingStartService {
                room,
                user,
                sender_type: "user".to_string(),
            },
        }
    }

    pub fn dispatch_typing_stop(
        room_id: Uuid,
        _room_name: &str,
        user_id: Uuid,
        display_name: Option<String>,
    ) -> WsOutEvent {
        let user = UserInfo {
            id: user_id,
            username: display_name.clone().unwrap_or_default(),
            display_name: display_name.unwrap_or_default(),
            avatar_url: String::new(),
        };
        let room = RoomInfo::unknown(room_id);
        WsOutEvent::TypingStop {
            room: room.clone(),
            data: member::TypingStopService {
                room,
                user,
                sender_type: "user".to_string(),
            },
        }
    }

    pub fn dispatch_reactions(
        room_id: Uuid,
        room_name: &str,
        message_id: Uuid,
        groups: Vec<reaction::ReactionGroup>,
    ) -> WsOutEvent {
        let room = RoomInfo {
            id: room_id,
            name: room_name.to_string(),
        };
        WsOutEvent::ReactionBatchUpdated {
            room: room.clone(),
            data: reaction::ReactionBatchUpdatedService {
                room,
                message: message_id,
                reactions: groups,
            },
        }
    }

    pub fn dispatch_notification(
        data: notify::NotifyCreatedService,
    ) -> WsOutEvent {
        WsOutEvent::NotifyCreated { data }
    }
}
