use super::handlers::*;
use super::{DefaultHandlers, EventParseFunc};
use crate::models::gateway::*;
use std::sync::{LazyLock, RwLock};

static EVENT_PARSE_FUNC_MAP: LazyLock<RwLock<Vec<(OpCode, EventType, EventParseFunc)>>> =
    LazyLock::new(|| RwLock::new(default_event_handlers()));

fn default_event_handlers() -> Vec<(OpCode, EventType, EventParseFunc)> {
    [
        (EventGuildCreate, guild_handler as EventParseFunc),
        (EventGuildUpdate, guild_handler),
        (EventGuildDelete, guild_handler),
        (EventChannelCreate, channel_handler),
        (EventChannelUpdate, channel_handler),
        (EventChannelDelete, channel_handler),
        (EventGuildMemberAdd, guild_member_handler),
        (EventGuildMemberUpdate, guild_member_handler),
        (EventGuildMemberRemove, guild_member_handler),
        (EventMessageCreate, message_handler),
        (EventMessageDelete, message_delete_handler),
        (EventMessageReactionAdd, message_reaction_handler),
        (EventMessageReactionRemove, message_reaction_handler),
        (EventAtMessageCreate, at_message_handler),
        (EventPublicMessageDelete, public_message_delete_handler),
        (EventDirectMessageCreate, direct_message_handler),
        (EventDirectMessageDelete, direct_message_delete_handler),
        (EventAudioStart, audio_handler),
        (EventAudioFinish, audio_handler),
        (EventAudioOnMic, audio_handler),
        (EventAudioOffMic, audio_handler),
        (EventMessageAuditPass, message_audit_handler),
        (EventMessageAuditReject, message_audit_handler),
        (EventForumThreadCreate, thread_handler),
        (EventForumThreadUpdate, thread_handler),
        (EventForumThreadDelete, thread_handler),
        (EventForumPostCreate, post_handler),
        (EventForumPostDelete, post_handler),
        (EventForumReplyCreate, reply_handler),
        (EventForumReplyDelete, reply_handler),
        (EventForumAuditResult, forum_audit_handler),
        (EventInteractionCreate, interaction_handler),
        (EventGroupAtMessageCreate, group_at_message_handler),
        (EventC2CMessageCreate, c2c_message_handler),
        (EventSubscribeMsgStatus, subscribe_msg_status_handler),
        (EventC2CFriendAdd, c2c_friend_handler),
        (EventC2CFriendDel, c2c_friend_handler),
        (EventEnterAIO, enter_aio_handler),
    ]
    .into_iter()
    .map(|(event, handler)| (WSDispatchEvent, event.to_string(), handler))
    .collect()
}

pub fn RegisterHandler(op_code: OpCode, event_type: impl Into<EventType>, handler: EventParseFunc) {
    let event_type = event_type.into();
    let mut handlers = EVENT_PARSE_FUNC_MAP
        .write()
        .expect("event handler map lock poisoned");
    if let Some((_, _, existing)) = handlers
        .iter_mut()
        .find(|(op, event, _)| *op == op_code && *event == event_type)
    {
        *existing = handler;
    } else {
        handlers.push((op_code, event_type, handler));
    }
}

pub fn ParseAndHandle(payload: &mut WSPayload) -> crate::Result<()> {
    let raw = payload
        .raw_message
        .clone()
        .unwrap_or_else(|| serde_json::to_vec(payload).unwrap_or_default());
    let handler = {
        let handlers = EVENT_PARSE_FUNC_MAP
            .read()
            .expect("event handler map lock poisoned");
        payload.base.event_type.as_ref().and_then(|event_type| {
            handlers
                .iter()
                .find(|(op, event, _)| *op == payload.base.op_code && event.as_str() == event_type)
                .map(|(_, _, handler)| *handler)
        })
    };

    if let Some(handler) = handler {
        handler(payload, &raw)
    } else if let Some(plain) = DefaultHandlers
        .read()
        .expect("default handlers lock poisoned")
        .plain
    {
        plain(payload, &raw)
    } else {
        Ok(())
    }
}
