package cn.reghao.tnb.message.app.ws.chat;

import cn.reghao.jutil.jdk.serializer.JdkSerializer;
import cn.reghao.jutil.jdk.serializer.JsonConverter;
import cn.reghao.tnb.auth.api.constant.TokenType;
import cn.reghao.tnb.auth.api.dto.AuthedAccount;
import cn.reghao.tnb.auth.api.iface.AccountQuery;
import cn.reghao.tnb.message.api.dto.PushMsg;
import cn.reghao.tnb.message.api.dto.event.EventMsg;
import cn.reghao.tnb.message.api.model.EventType;
import cn.reghao.tnb.message.api.model.resp.EventMessageResp;
import cn.reghao.tnb.message.app.rabbit.RabbitProducer;
import cn.reghao.tnb.message.app.ws.chat.msg.ChatPayload;
import cn.reghao.tnb.message.app.ws.chat.msg.EventResp;
import cn.reghao.tnb.message.app.ws.config.PingPayload;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;

/**
 * @author reghao
 * @date 2025-10-11 20:45:24
 */
@Slf4j
@Component
public class ChatConnection {
    @DubboReference(check = false, retries = 0, timeout = 60_000)
    private AccountQuery accountQuery;

    private final RabbitProducer rabbitProducer;
    // userId -> session
    private final Map<Long, WebSocketSession> userSessions = new HashMap<>();
    // sessionId -> userId
    private final Map<String, Long> sessionUsers = new HashMap<>();

    public ChatConnection(RabbitProducer rabbitProducer) {
        this.rabbitProducer = rabbitProducer;
    }

    public boolean addSession(WebSocketSession webSocketSession) {
        String userToken = (String) webSocketSession.getAttributes().get("userToken");
        //String videoId = (String) webSocketSession.getAttributes().get("videoId");
        AuthedAccount authedAccount = accountQuery.getAuthedAccount(TokenType.token.getValue(), userToken);
        if (authedAccount != null) {
            long userId = authedAccount.getUserId();
            addUserSession(userId, webSocketSession);
            return true;
        }
        return false;
    }

    public void addUserSession(long userId, WebSocketSession webSocketSession) {
        String sessionId = webSocketSession.getId();
        userSessions.put(userId, webSocketSession);
        sessionUsers.put(sessionId, userId);
    }

    public void removeUserSession(WebSocketSession webSocketSession) {
        String sessionId = webSocketSession.getId();
        Long userId = sessionUsers.get(sessionId);
        userSessions.remove(userId);
        sessionUsers.remove(userId);
    }

    public Long getUserId(String sessionId) {
        return sessionUsers.get(sessionId);
    }

    public WebSocketSession getUserSession(long userId) {
        return userSessions.get(userId+"");
    }

    public void sendPingPayload(WebSocketSession session) throws IOException {
        PingPayload pingPayload = new PingPayload(60, 120);
        EventResp eventResp = new EventResp();
        eventResp.setEvent("connect");
        eventResp.setPayload(pingPayload);

        TextMessage textMessage = new TextMessage(JsonConverter.objectToJson(eventResp));
        session.sendMessage(textMessage);
    }

    public void sendHeartbeatPong(WebSocketSession session) throws IOException {
        EventMessageResp<String> resp = new EventMessageResp<>(EventType.heartbeat, "pong");
        TextMessage textMessage = new TextMessage(JsonConverter.objectToJson(resp));
        session.sendMessage(textMessage);
    }

    public void sendTextMsg(PushMsg pushMsg) throws IOException {
        String userId = pushMsg.getReceiverId();
        EventMsg eventMsg = pushMsg.getEventMsg();

        WebSocketSession webSocketSession = userSessions.get(userId);
        if (webSocketSession == null) {
            log.error("{} 不在线", userId);
            return;
        }

        TextMessage textMessage = new TextMessage(JsonConverter.objectToJson(eventMsg));
        webSocketSession.sendMessage(textMessage);
    }

    public void send(String receiverId, String content) throws IOException {
        WebSocketSession webSocketSession = userSessions.get(receiverId);
        if (webSocketSession == null) {
            log.error("{} 不在线", receiverId);
            return;
        }

        EventMessageResp<String> resp = new EventMessageResp<>(EventType.event_content, content);
        TextMessage textMessage = new TextMessage(JsonConverter.objectToJson(resp));
        webSocketSession.sendMessage(textMessage);
    }

    public void send1(String receiverId, Object object) throws IOException {
        WebSocketSession webSocketSession = userSessions.get(receiverId);
        if (webSocketSession == null) {
            log.error("{} 不在线", receiverId);
            return;
        }

        TextMessage textMessage = new TextMessage(JsonConverter.objectToJson(object));
        webSocketSession.sendMessage(textMessage);
    }

    public void send(String receiverId, Object message) throws IOException {
        WebSocketSession session = userSessions.get(receiverId);
        if (session != null) {
            byte[] bytes = JdkSerializer.serialize(message);
            BinaryMessage binaryMessage = new BinaryMessage(bytes);
            session.sendMessage(binaryMessage);
        }
    }

    public void sendChatMessage(String receiverId, ChatPayload chatPayload) throws IOException {
        WebSocketSession session = userSessions.get(receiverId);
        if (session == null) {
            return;
        }

        EventResp eventResp = new EventResp();
        eventResp.setEvent("event_talk");
        eventResp.setPayload(chatPayload);

        TextMessage textMessage = new TextMessage(JsonConverter.objectToJson(eventResp));
        session.sendMessage(textMessage);
    }

    public void unicast() {
    }

    public void multicast() {

    }

    public void broadcast(String sender, String text) throws IOException {
        for (WebSocketSession webSocketSession : userSessions.values()) {
            InetSocketAddress socketAddress = webSocketSession.getRemoteAddress();
            int port = socketAddress.getPort();
            if (webSocketSession.isOpen()) {
                Map<String, String> map = new HashMap<>();
                map.put("senderId", sender);
                map.put("receiverId", ""+port);
                map.put("payload", text);

                String json = JsonConverter.objectToJson(map);
                TextMessage textMessage = new TextMessage(json);
                webSocketSession.sendMessage(textMessage);
            }
        }
    }
}
