package com.sikey.wa04.api.websocket.client.handler;

import cn.hutool.json.JSONUtil;
import com.sikey.wa04.business.application.service.websocket.ConnectionHeartbeatService;
import com.sikey.wa04.business.application.service.websocket.ConnectionManagerService;
import com.sikey.wa04.common.constants.TraceConstant;
import io.netty.handler.codec.UnsupportedMessageTypeException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.PongMessage;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;

/**
 * WebSocket处理器
 *
 * @author luoyangwei
 */
@Component
@Slf4j
public class WebSocketHandler extends TextWebSocketHandler {

    @Resource
    private ConnectionHeartbeatService connectionHeartbeatService;

    @Resource
    private ConnectionManagerService connectionManagerService;

    private String getSecWebSocketKey(WebSocketSession session) {
        return session.getHandshakeHeaders().getFirst("Sec-WebSocket-Key");
    }

    /**
     * 处理消息
     *
     * @param webSocketSession 会话
     * @param textMessage      消息
     */
    @Override
    protected void handleTextMessage(WebSocketSession webSocketSession, TextMessage textMessage) throws Exception {
        log.info("[处理消息]消息内容：{}", JSONUtil.toJsonStr(textMessage.getPayload()));
        MDC.put(TraceConstant.REQUEST_ID, getSecWebSocketKey(webSocketSession));
        connectionHeartbeatService.handleCustomizedMessage(webSocketSession);
    }

    /**
     * 建立连接
     *
     * @param webSocketSession 会话
     * @throws Exception 异常
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        MDC.put(TraceConstant.REQUEST_ID, getSecWebSocketKey(webSocketSession));
        connectionManagerService.connectionEstablished(webSocketSession);
    }

    /**
     * 关闭连接
     *
     * @param webSocketSession 会话
     * @param closeStatus      状态
     * @throws Exception 异常
     */
    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        MDC.put(TraceConstant.REQUEST_ID, getSecWebSocketKey(webSocketSession));
        connectionManagerService.connectionClosed(webSocketSession, closeStatus);
        MDC.remove(TraceConstant.REQUEST_ID);
    }

    /**
     * 处理Pong
     *
     * @param webSocketSession 会话
     * @param pongMessage      消息
     * @throws Exception 异常
     */
    @Override
    protected void handlePongMessage(WebSocketSession webSocketSession, PongMessage pongMessage) throws Exception {
        connectionHeartbeatService.handlePongMessage(webSocketSession, pongMessage);
    }

    /**
     * 处理Ping
     *
     * @param session   会话
     * @param exception 异常
     * @return
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws IOException {
        if (exception instanceof UnsupportedMessageTypeException) {
            log.debug("Received Ping：{}", JSONUtil.toJsonPrettyStr(session));
            // 处理Ping消息
            session.sendMessage(new PongMessage());
        }
    }
}
