package cn.sikey.websocket.service;

import cn.sikey.websocket.config.CacheConnectionStateManager;
import cn.sikey.websocket.config.RabbitMQMessaging;
import cn.sikey.websocket.controller.app.message.vo.MessagingPublishReqVO;
import cn.sikey.websocket.controller.app.message.vo.MessagingPublishRespVO;
import cn.sikey.websocket.controller.app.message.vo.SaveMessageRecvReqVO;
import cn.sikey.websocket.enums.MessageStatus;
import cn.sikey.websocket.enums.MessageType;
import cn.sikey.websocket.message.Message;
import cn.sikey.websocket.message.MessageId;
import cn.sikey.websocket.message.MessageReceivedLog;
import cn.sikey.websocket.util.MessageConverterUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.util.List;
import java.util.Objects;

/**
 * @Author: nelson
 * @Date: 2025/5/29
 * @Description: 抽象服务
 */
@Slf4j
public class AbstractWebSocketService {

    @Resource
    private MessageIdIncrementingService<Long> messageIdIncrementingService;

    @Resource
    private MessageSendService messageSendService;

    @Resource
    private RabbitMQMessaging rabbitMQMessaging;

    @Resource
    private CacheConnectionStateManager cacheConnectionStateManager;

    @Resource
    private MessageRecvService messageRecvService;

    @Resource
    private ObjectMapper objectMapper;

    /**
     * 发布消息
     *
     * @param request 请求
     * @param <T>     消息内容类型
     * @return
     */
    public <T> MessagingPublishRespVO publish(MessagingPublishReqVO<T> request) {
        MessageType messageType = MessageType.valueOf(request.getMsgType());

        Message message = new Message().setId(new MessageId(messageIdIncrementingService.incr())).setType(messageType).setContent(request.getContent()).
                setSenderId("test").setSendTime(request.getSendTime());
        message.setReceiverId(List.of(request.getRecvId()));
        messageSendService.saveMessageSend(message);

        // 过滤用户自己
        message.setReceiverId(message.getReceiverId().stream().filter(r -> !r.equals("test")).toList());

        message.getReceiverId().forEach(receiverId -> {
            // 接收消息用户
            message.setReceiverId(List.of(receiverId));
            Object messagingObject = MessageConverterUtil.toMessaging(message);
            log.info("发消息给接收者: {}，消息内容：{}", receiverId, messagingObject);
            rabbitMQMessaging.publish(messagingObject);
        });

        return new MessagingPublishRespVO().setMsgId(message.getId().getId());
    }

    /**
     * 消费消息
     *
     * @param message 消息
     * @return
     */
    public void consumeMessage(Message message) {

        try {
            for (MessageReceivedLog messageReceivedLog : message.getReceivedLogs()) {
                String receiverId = messageReceivedLog.getReceiverId();

                // 加入数据库并且获取 ackId
                SaveMessageRecvReqVO saveMessageRecvReqVO = new SaveMessageRecvReqVO();
                saveMessageRecvReqVO.setMsgId(message.getId().getId());
                saveMessageRecvReqVO.setRecvId(receiverId);
                saveMessageRecvReqVO.setSenderId(message.getSenderId());
                saveMessageRecvReqVO.setMsgType(message.getType().getValue());
                saveMessageRecvReqVO.setContent(objectMapper.convertValue(message.getContent(), new TypeReference<>() {
                }));
                saveMessageRecvReqVO.setSendTime(message.getSendTime());
                saveMessageRecvReqVO.setMsgStatus(MessageStatus.DEFAULT.getValue());

                messageRecvService.saveMessageRecv(saveMessageRecvReqVO);
                messageReceivedLog.setAckId(saveMessageRecvReqVO.getId());

                if (cacheConnectionStateManager.isOnline(receiverId)) {

                    WebSocketSession session = cacheConnectionStateManager.getSession(receiverId);
                    if (Objects.nonNull(session)) {
                        session.sendMessage(
                                new TextMessage(objectMapper.writeValueAsString(MessageConverterUtil.toMessaging(message))));
                        messageRecvService.updateStatusById(MessageStatus.WAIT_ACK.getValue(), messageReceivedLog.getAckId());
                        continue;
                    }
                }

                // 消息存入离线队列
                messageRecvService.updateStatusById(MessageStatus.OFFLINE_QUEUE.getValue(), messageReceivedLog.getAckId());
            }

            log.info("消费消息完成");
        } catch (Exception e) {
        }
    }

}
