package com.example.system.chat.config;

import com.example.system.chat.mapper.MessageMapper;
import com.example.system.chat.mapper.SessionMassageMapper;
import com.example.system.chat.model.ConnectionMap;
import com.example.system.chat.model.WebSocketRequest;
import com.example.system.chat.model.WebSocketResp;
import com.example.system.model.UserTable;
import com.example.system.utils.JWTUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;
import java.util.List;

@Component
@Slf4j
public class WebSocketController extends TextWebSocketHandler {
    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private SessionMassageMapper sessionMassageMapper;
    @Resource
    private MessageMapper messageMapper;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("连接成功");
        Long userId = getUserIdBySession(session);
        ConnectionMap.onLine(Math.toIntExact(userId), session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        log.info("收到消息 message: {}", message);
        //获取用户发送的消息
        WebSocketRequest webSocketRequest = objectMapper.readValue(message.getPayload(), WebSocketRequest.class);
        if (!"message".equals(webSocketRequest.getType())) {
            return;
        }
        //获取发送者
        UserTable user = new UserTable();
        user.setUserId(getUserIdBySession(session));
        user.setUserName(getUserNameBySession(session));
        //构造一个转发的消息
        WebSocketResp resp = new WebSocketResp();
        resp.setType(webSocketRequest.getType());
        resp.setSessionId(webSocketRequest.getSessionId());
        resp.setUserId(Math.toIntExact(user.getUserId()));
        resp.setUserName(user.getUserName());
        resp.setContent(webSocketRequest.getContent());
        String ret = objectMapper.writeValueAsString(resp);
        //获取当前发送会话的所有好友id和name
        List<UserTable> list = sessionMassageMapper.getSessionBySessionId(webSocketRequest.getSessionId(), Math.toIntExact(user.getUserId()));
        list.add(user);
        //给所有人转发该条消息
        for (UserTable tmp : list) {
            WebSocketSession socketSession = ConnectionMap.getWSSessionById(Math.toIntExact(tmp.getUserId()));
            if (socketSession != null) {
                socketSession.sendMessage(new TextMessage(ret));
            }
        }
        //将该条消息存储在数据库中
        Integer a = messageMapper.sendMessage(Math.toIntExact(user.getUserId()), webSocketRequest.getSessionId(), webSocketRequest.getContent());
        if (a != 1) {
            throw new RuntimeException("消息存储异常");
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("连接异常 exception: {}", exception.toString());
        int userId = Math.toIntExact(getUserIdBySession(session));
        ConnectionMap.offLine(userId);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.info("连接关闭");
        int userId = Math.toIntExact(getUserIdBySession(session));
        ConnectionMap.offLine(userId);
    }

    public Long getUserIdBySession(WebSocketSession session) {
        session.getHandshakeHeaders();
        String userToken = (String) session.getAttributes().get("userToken");
        Claims claims = JWTUtil.checkToken(userToken);
        return (Long) claims.get("userId");
    }

    public String getUserNameBySession(WebSocketSession session) {
        HttpHeaders handshakeHeaders = session.getHandshakeHeaders();
        List<String> list = handshakeHeaders.get("sec-websocket-protocol");
        String userToken =list.get(0);
        Claims claims = JWTUtil.checkToken(userToken);
        return (String) claims.get("userName");
    }
}
