package com.ruoyi.project.common.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.project.business.domain.TbAgent;
import com.ruoyi.project.business.domain.TqQuotation;
import com.ruoyi.project.business.enums.DelFlagEnum;
import com.ruoyi.project.business.enums.ReadStatusEnum;
import com.ruoyi.project.business.service.ITbAgentService;
import com.ruoyi.project.business.service.quotation.ITqQuotationService;
import com.ruoyi.project.common.ChatRoomActiveEnum;
import com.ruoyi.project.common.MessageChatTypeEnum;
import com.ruoyi.project.common.domain.MessageChat;
import com.ruoyi.project.common.domain.MessageChatContent;
import com.ruoyi.project.common.domain.MessageChatGroup;
import com.ruoyi.project.common.domain.MessageChatUser;
import com.ruoyi.project.common.domain.MessageContentUser;
import com.ruoyi.project.common.dto.MessageChatContentDto;
import com.ruoyi.project.common.dto.MessageChatDto;
import com.ruoyi.project.common.dto.MessageChatRes;
import com.ruoyi.project.common.dto.MessageContentUserDto;
import com.ruoyi.project.common.service.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

/**
 * @author jubs
 */
@Service
public class SseChatEmitterServiceImpl implements ISseChatEmitterService {

    private static final Logger log = LoggerFactory.getLogger(SseChatEmitterServiceImpl.class);

    @Value("${sse.timeOut}")
    public Long sseTimeOut;

    @Resource
    private IMessageChatService iMessageChatService;

    @Resource
    private IMessageChatContentService iMessageChatContentService;

    @Resource
    private IMessageChatUserService iMessageChatUserService;

    @Resource
    private IMessageChatGroupService iMessageChatGroupService;

    @Resource
    private IMessageContentUserService iMessageContentUserService;

    @Resource
    private ITqQuotationService tqQuotationService;
    @Resource
    private ISysUserService sysUserService;


    private static final Map<String, SseEmitter> sseChatCache = new ConcurrentHashMap<>();

    @Override
    public SseEmitter createChatRoomConnect(String clientId) {
        // 设置超时时间，0表示不过期。默认30秒，超过时间未完成会抛出异常：AsyncRequestTimeoutException
        SseEmitter sseEmitter = new SseEmitter(sseTimeOut);
        // 注册回调
        // 长链接完成后回调接口(即关闭连接时调用)
        sseEmitter.onCompletion(completionCallBack(clientId));
        // 连接超时回调
        sseEmitter.onTimeout(timeoutCallBack(clientId));
        // 将连接保存在容器中,后续发送消息从容器中获取连接发送
        sseChatCache.put(clientId, sseEmitter);
        sendChatMessageToClientId(SecurityUtils.getUserId());
        return sseEmitter;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createChatRoom(MessageChatDto dto) {
        List<Long> userIdList = getQuoteOrderUserIds(dto.getChatName());
        Long currentUserId = SecurityUtils.getUserId();
        Date date = DateUtils.getNowDate();
        userIdList = userIdList.stream().distinct().collect(Collectors.toList());

        //查找报价单下 相关所有人的 聊天室信息
        // @Date 2024/7/4 11:21 @Author jubs 😀 @description:业务变更，多个版本的报价 共用一个聊天室
        List<MessageChatDto> chatRooms = iMessageChatService.getChatRoomByUserIds(userIdList, null,
                dto.getChatName());

        //  判断 是否已经创建过
        Long chatRoomId = null;
        //确保所有参与者 都在该聊天室中,取出 userIdList 与 chatRooms 的差集
        List<Long> notInChatRooms;

        List<Long> notVisibleChatUserId = new ArrayList<>();

        if (chatRooms.isEmpty()) {
            //需要创建聊天室
            MessageChat messageChat = new MessageChat();
            messageChat.setChatType(MessageChatTypeEnum.QUOTE.getCode());
            messageChat.setChatName(dto.getChatName());
            messageChat.setCreateBy(String.valueOf(currentUserId));
            messageChat.setCreateTime(date);
            messageChat.setQuotationNo(dto.getChatName());
            iMessageChatService.getBaseMapper().insert(messageChat);
            chatRoomId = messageChat.getId();
            notInChatRooms = userIdList;
        } else {
            //说明 该 报价单  已经创建过聊天室
            chatRoomId = chatRooms.stream().filter(chatRoom -> chatRoom.getChatName().equals(dto.getChatName()))
                    .findFirst().get().getId();
            List<MessageChatDto> finalChatRooms = chatRooms;
            notInChatRooms = userIdList.stream().filter(
                    userId -> !finalChatRooms.stream().map(MessageChatDto::getChatUserId).collect(Collectors.toList())
                            .contains(userId)).collect(Collectors.toList());

            List<MessageChatDto> hideChatRooms = chatRooms.stream()
                    .filter(chatRoom -> chatRoom.getVisible().equals(ChatRoomVisibleEnum.HIDE.getCode()))
                    .collect(Collectors.toList());
            notVisibleChatUserId = userIdList.stream().filter(
                    userId -> hideChatRooms.stream().map(MessageChatDto::getChatUserId).collect(Collectors.toList()).contains(userId)
            ).collect(Collectors.toList());
        }
        //step 2: 新增 参与者
        if (!notInChatRooms.isEmpty()) {
            List<MessageChatUser> messageChatUsers = new ArrayList<>();
            for (Long userId : notInChatRooms) {
                MessageChatUser messageChatUser = new MessageChatUser();
                messageChatUser.setMessageChatId(chatRoomId);
                messageChatUser.setUserId(userId);
                //如果是自己点击了聊天室，激活当前聊天室
                messageChatUser.setActive(currentUserId.equals(userId) ? ChatRoomActiveEnum.TOP.getCode() : ChatRoomActiveEnum.NOT_TOP.getCode());
                messageChatUser.setSort(0L);
                messageChatUser.setVisible(ChatRoomVisibleEnum.SHOW.getCode());
                messageChatUsers.add(messageChatUser);
            }
            iMessageChatUserService.saveBatch(messageChatUsers);
        }
        //step 3: 展示 隐藏的聊天室
        if (!notVisibleChatUserId.isEmpty()) {
            iMessageChatUserService.update(
                    Wrappers.<MessageChatUser>lambdaUpdate()
                            .in(MessageChatUser::getUserId, notVisibleChatUserId)
                            .eq(MessageChatUser::getMessageChatId, chatRoomId)
                            .set(MessageChatUser::getVisible, ChatRoomVisibleEnum.SHOW.getCode())
                            .set(MessageChatUser::getUpdateBy, currentUserId.toString())
                            .set(MessageChatUser::getUpdateTime, DateUtils.getNowDate())
            );
        }

        // @Date 2024/7/3 17:24 @Author jubs 😀 @description:当前聊天室激活，其余聊天室取消
        iMessageChatUserService.update(
                Wrappers.<MessageChatUser>lambdaUpdate()
                        .eq(MessageChatUser::getUserId, currentUserId)
                        .eq(MessageChatUser::getMessageChatId, chatRoomId)
                        .set(MessageChatUser::getVisible, ChatRoomVisibleEnum.SHOW.getCode())
                        .set(MessageChatUser::getActive, ChatRoomActiveEnum.TOP.getCode())
                        .set(MessageChatUser::getUpdateBy, currentUserId.toString())
                        .set(MessageChatUser::getUpdateTime, DateUtils.getNowDate())
        );


        iMessageChatUserService.update(
                Wrappers.<MessageChatUser>lambdaUpdate()
                        .eq(MessageChatUser::getUserId, currentUserId)
                        .ne(MessageChatUser::getMessageChatId, chatRoomId)
                        .set(MessageChatUser::getActive, ChatRoomActiveEnum.NOT_TOP.getCode())
                        .set(MessageChatUser::getUpdateBy, currentUserId.toString())
                        .set(MessageChatUser::getUpdateTime, DateUtils.getNowDate())
        );


        //拉取今天以前的 10条聊天记录
        //step 1: 查询 从当前时间向前的10条聊天记录
        List<MessageChatContentDto> messageChatContents = iMessageChatContentService.getMessageChatContentList(
                chatRoomId);
        for (MessageChatDto messageChat : chatRooms) {
            if (messageChat.getId().equals(chatRoomId)) {
                messageChat.setChatContentList(messageChatContents);
            }
        }

        chatRooms = iMessageChatService.getChatRoomByUserIds(Collections.singletonList(currentUserId), null, null);
        //过滤其中隐藏的聊天室
        chatRooms = chatRooms.stream().filter(
                item -> ChatRoomVisibleEnum.SHOW.getCode().equals(item.getVisible())
        ).collect(Collectors.toList());
        Map<String, Object> chatRoomUnRead = markUnreadMessage(
                chatRooms.stream().map(MessageChatDto::getId).collect(Collectors.toList()),
                Collections.singletonList(currentUserId));
        for (MessageChatDto chatRoom : chatRooms) {
            if (chatRoomUnRead.containsKey(chatRoom.getId() + "__" + currentUserId)) {
                chatRoom.setHasUnReadMessage((Boolean) chatRoomUnRead.get(chatRoom.getId() + "__" + currentUserId));
                if (chatRoom.isHasUnReadMessage()) {
                    chatRoom.setUnReadMessageCount(
                            (Integer) chatRoomUnRead.get(chatRoom.getId() + "__" + currentUserId + "unReadNum"));
                }
            }
        }

        // @Date 2024/6/28 13:28 @Author jubs 😀 @description: 聊天室的角标 应当是未读讯息的总数，非聊天室的总数
        MessageChatRes messageChatRes = new MessageChatRes();
        Integer unReadMessageCount = 0;
        for (MessageChatDto chatRoom : chatRooms) {
            if (chatRoom.isHasUnReadMessage()) {
                unReadMessageCount += chatRoom.getUnReadMessageCount();
            }
        }
        messageChatRes.setChatRoomsTotal(Long.valueOf(unReadMessageCount));
        chatRooms.sort(Comparator.comparing(MessageChatDto::getActive));
        messageChatRes.setChatRooms(chatRooms);
        messageChatRes.setClientId(dto.getCurrentActiveConnectId());
        messageChatRes.setPopUpFlag(true);
        List<String> clientIdList = new ArrayList<>(
                sseChatCache.entrySet().stream().filter(entry -> entry.getKey().contains(currentUserId + "_chat_"))
                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)).keySet());
        clientIdList.sort(Collections.reverseOrder());
        for (String toClientId : clientIdList) {
            messageChatRes.setClientId(toClientId);
            sendChatRoomToClientByClientId(toClientId, messageChatRes, sseChatCache.get(toClientId));
        }
    }

    @Override
    public void sendChatMessageToClientId(Long clientId) {
        try {
            MessageChatRes messageChatRes = new MessageChatRes();
            Long currentUserId = SecurityUtils.getUserId();
            List<MessageChatDto> chatRooms = iMessageChatService.getChatRoomByUserIds(
                    Collections.singletonList(currentUserId), null, null);
            if (chatRooms != null && !chatRooms.isEmpty()) {
                // 按照active排序 0 优先在前
                //过滤掉其中隐藏的聊天
                chatRooms = chatRooms.stream()
                        .filter(chatRoom -> !ChatRoomVisibleEnum.HIDE.getCode().equals(chatRoom.getVisible()))
                        .sorted(Comparator.comparing(MessageChatDto::getActive))
                        .collect(Collectors.toList());
                List<MessageChatDto> activeChatRooms = chatRooms.stream()
                        .filter(chatRoom -> ChatRoomActiveEnum.TOP.getCode().equals(chatRoom.getActive()))
                        .collect(Collectors.toList());

                if (!activeChatRooms.isEmpty()) {
                    //查询被激活的聊天室 或者置顶的聊天室  聊天记录
                    //step 1: 查询 从当前时间向前的10条聊天记录
                    List<MessageChatContentDto> messageChatContents = iMessageChatContentService.getMessageChatContentList(
                            activeChatRooms.get(0).getId());
                    chatRooms.get(0).setChatContentList(messageChatContents);
                } else {
                    List<MessageChatContentDto> messageChatContents = iMessageChatContentService.getMessageChatContentList(
                            chatRooms.get(0).getId());
                    chatRooms.get(0).setChatContentList(messageChatContents);
                }
                Map<String, Object> chatRoomUnRead = markUnreadMessage(
                        chatRooms.stream().map(MessageChatDto::getId).collect(Collectors.toList()),
                        Collections.singletonList(currentUserId));
                for (MessageChatDto chatRoom : chatRooms) {
                    if (chatRoomUnRead.containsKey(chatRoom.getId() + "__" + currentUserId)) {
                        chatRoom.setHasUnReadMessage(
                                (Boolean) chatRoomUnRead.get(chatRoom.getId() + "__" + currentUserId));
                        if (chatRoom.isHasUnReadMessage()) {
                            chatRoom.setMaxUnReadMessageTime((Date) chatRoomUnRead.get(chatRoom.getId() + "__" + currentUserId + "lastUnReadTime"));

                            chatRoom.setUnReadMessageCount(
                                    (Integer) chatRoomUnRead.get(chatRoom.getId() + "__" + currentUserId + "unReadNum"));
                        }
                    }
                }

                messageChatRes.setChatRooms(chatRooms);
                messageChatRes.setPopUpFlag(true);

                Integer unReadMessageCount = 0;
                for (MessageChatDto chatRoom : chatRooms) {
                    if (chatRoom.isHasUnReadMessage()) {
                        unReadMessageCount += chatRoom.getUnReadMessageCount();
                    }
                }
                messageChatRes.setChatRoomsTotal(Long.valueOf(unReadMessageCount));

                // 获取连接中所有user为当前id的连接
                // 前端再创建连接的时候所用的id是由  UserId+_chat_+时间戳 的格式创建的,这里会根据userid获取所有的连接对所有的连接进行发送消息的操作
                // 可以根据实际情况进行修改,只要clientId和创建连接的时候保持一致即可发送消息
                List<String> clientIdList = new ArrayList<>(
                        sseChatCache.entrySet().stream().filter(entry -> entry.getKey().contains(clientId + "_chat_"))
                                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)).keySet());
                clientIdList.sort(Collections.reverseOrder());
                for (String toClientId : clientIdList) {
                    messageChatRes.setClientId(toClientId);
                    sendChatRoomToClientByClientId(toClientId, messageChatRes, sseChatCache.get(toClientId));
                }
            } else {
                //这个人先前没有聊天室，则创建空信息体的连接
                List<String> clientIdList = new ArrayList<>(
                        sseChatCache.entrySet().stream().filter(entry -> entry.getKey().contains(clientId + "_chat_"))
                                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)).keySet());
                clientIdList.sort(Collections.reverseOrder());
                messageChatRes.setChatRoomsTotal(0L);
                messageChatRes.setPopUpFlag(false);
                for (String toClientId : clientIdList) {
                    messageChatRes.setClientId(toClientId);
                    sendChatRoomToClientByClientId(toClientId, messageChatRes, sseChatCache.get(toClientId));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public void sentChatMessageToClientIdList(List<Long> userOnlineId, boolean popUpFlag, MessageChatDto dto) {
        try {
            Map<String, MessageChatRes> messageChatResMap = new HashMap<>();
            List<MessageChatDto> chatRooms = iMessageChatService.getChatRoomByUserIds(userOnlineId, null, null);
            if (chatRooms != null && !chatRooms.isEmpty()) {
                //聊天室按照每个人+聊天室 进行分组
                //                Map<String, List<MessageChatDto>> chatRoomsMap = chatRooms.stream().collect(Collectors.groupingBy(it -> it.getMessageChatUserId() + "@@@" + it.getId()));
               /* //查询 每个人的讯息
                List<MessageChatContentDto> contentDtos = iMessageChatContentService.getContentByUserIds(userOnlineId);
                //聊天记录 按照聊天室 进行分组
                Map<Long, List<MessageChatContentDto>> contentDtosMap = contentDtos.stream().collect(Collectors.groupingBy(MessageChatContentDto::getMessageChatId));
                //匹配所有用户 设置 所有聊天室的 讯息
                for (String chatRoom : chatRoomsMap.keySet()) {
                    Long chatRoomId = Long.parseLong(chatRoom.split("@@@")[1]);
                    MessageChatDto personalChatRoom = chatRoomsMap.get(chatRoom).get(0);
                    //聊天记录分组中有该聊天室
                    if (contentDtosMap.containsKey(chatRoomId)) {
                        List<MessageChatContentDto> contentDtosList = contentDtosMap.get(chatRoomId);
                        personalChatRoom.setChatContentList(contentDtosList);
                    }
                }*/
                //过滤隐藏的聊天室
                chatRooms = chatRooms.stream().filter(item ->
                        ChatRoomVisibleEnum.SHOW.getCode().equals(item.getVisible())).collect(Collectors.toList());

                Map<String, Object> chatRoomUnRead = markUnreadMessage(
                        chatRooms.stream().map(MessageChatDto::getId).collect(Collectors.toList()), userOnlineId);
                for (Long userId : userOnlineId) {
                    List<MessageChatDto> personalChatRooms = chatRooms.stream()
                            .filter(it -> it.getChatUserId().equals(userId))
                            .sorted(Comparator.comparing(MessageChatDto::getActive))
                            .collect(Collectors.toList());
                    for (MessageChatDto chatRoom : personalChatRooms) {
                        if (chatRoomUnRead.containsKey(chatRoom.getId() + "__" + userId)) {
                            MessageChatRes messageChatRes = new MessageChatRes();
                            chatRoom.setHasUnReadMessage((Boolean) chatRoomUnRead.get(chatRoom.getId() + "__" + userId));
                            if (chatRoom.isHasUnReadMessage()) {
                                chatRoom.setMaxUnReadMessageTime(((Date) chatRoomUnRead.get(chatRoom.getId() + "__" + userId + "lastUnReadTime")));
                                chatRoom.setUnReadMessageCount(
                                        (Integer) chatRoomUnRead.get(chatRoom.getId() + "__" + userId + "unReadNum"));
                            }
                            messageChatRes.setChatRooms(personalChatRooms);
                            Integer unReadMessageCount = 0;
                            for (MessageChatDto personalChatRoom : personalChatRooms) {
                                if (personalChatRoom.isHasUnReadMessage()) {
                                    unReadMessageCount += personalChatRoom.getUnReadMessageCount();
                                }
                            }
                            messageChatRes.setChatRoomsTotal(Long.valueOf(unReadMessageCount));
                            messageChatRes.setPopUpFlag(popUpFlag);
                            messageChatResMap.put(String.valueOf(userId), messageChatRes);

                        }
                    }
                }
                for (Long userId : userOnlineId) {
                    List<String> clientIdList = new ArrayList<>(
                            sseChatCache.entrySet().stream().filter(entry -> entry.getKey().contains(userId + "_chat_"))
                                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)).keySet());
                    clientIdList.sort(Collections.reverseOrder());
                    for (String toClientId : clientIdList) {
                        if (messageChatResMap.containsKey(toClientId.split("_chat_")[0])) {
                            MessageChatRes messageChatRes = messageChatResMap.get(toClientId.split("_chat_")[0]);
                            messageChatRes.setClientId(toClientId);
                            sendChatRoomToClientByClientId(toClientId, messageChatRes, sseChatCache.get(toClientId));
                        }
                    }
                }


            }
        } catch (Exception e) {
            log.error("用户id:{} 发送聊天室失败", userOnlineId, e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void toSendInputMessage(MessageChatDto dto) {
        //获取当前用户id
        Long currentUserId = SecurityUtils.getUserId();
        //聊天室 id
        Long chatRoomId = dto.getId();

        //todo: 查询 该报价单 的 创建人、上级销售经理、上级代理商经理
        List<Long> userIdList = getQuoteOrderUserIds(dto.getQuotationNo());
        userIdList = userIdList.stream().distinct().collect(Collectors.toList());
        //查询 该报价单的所有在线 连接用户
        List<Long> userIdListOnline = new ArrayList<>(userIdList);
        //将所有人 对于该聊天是来说 都要展示
        iMessageChatUserService.update(Wrappers.<MessageChatUser>lambdaUpdate()
                .eq(MessageChatUser::getMessageChatId, chatRoomId)
                .set(MessageChatUser::getVisible, ChatRoomVisibleEnum.SHOW.getCode())
                .set(MessageChatUser::getUpdateBy, SecurityUtils.getUserId().toString())
                .set(MessageChatUser::getUpdateTime, new Date()));


        // 将当前 聊天记录 按天存入表中

        //按照当天 查询 是否已经有聊天记录组
        List<MessageChatGroup> messageChatGroups = iMessageChatGroupService.list(
                Wrappers.<MessageChatGroup>lambdaQuery().eq(MessageChatGroup::getMessageChatId, chatRoomId)
                        .eq(MessageChatGroup::getChateDate, DateUtils.getDate()));

        List<MessageChatContent> currentActiveContent = dto.getCurrentActiveContentList();
        List<Long> unReadMessageContentId = new ArrayList<>();
        Long messageGroupId = null;
        //激活当前聊天室
        iMessageChatUserService.update(
                Wrappers.<MessageChatUser>lambdaUpdate()
                        .eq(MessageChatUser::getUserId, currentUserId)
                        .eq(MessageChatUser::getMessageChatId, chatRoomId)
                        .set(MessageChatUser::getActive, 0)
                        .set(MessageChatUser::getVisible, ChatRoomVisibleEnum.SHOW.getCode())
                        .set(MessageChatUser::getUpdateBy, currentUserId.toString())
                        .set(MessageChatUser::getUpdateTime, DateUtils.getNowDate())
        );
        //取消激活其余聊天室
        iMessageChatUserService.update(
                Wrappers.<MessageChatUser>lambdaUpdate()
                        .eq(MessageChatUser::getUserId, SecurityUtils.getUserId())
                        .ne(MessageChatUser::getMessageChatId, chatRoomId)
                        .set(MessageChatUser::getActive, 1)
                        .set(MessageChatUser::getUpdateBy, SecurityUtils.getUserId().toString())
                        .set(MessageChatUser::getUpdateTime, DateUtils.getNowDate())
        );

        // 如果没有 则创建新的聊天记录组
        if (messageChatGroups.isEmpty()) {
            MessageChatGroup messageChatGroup = new MessageChatGroup();
            messageChatGroup.setMessageChatId(chatRoomId);
            messageChatGroup.setChateDate(DateUtils.getNowDate());
            messageChatGroup.setCreateBy(currentUserId.toString());
            messageChatGroup.setCreateTime(DateUtils.getNowDate());
            iMessageChatGroupService.save(messageChatGroup);
            messageGroupId = messageChatGroup.getId();
        } else {
            messageGroupId = messageChatGroups.get(0).getId();
        }
        //插入聊天记录
        List<MessageChatContent> content = new ArrayList<>();
        for (MessageChatContent currentActiveContentItem : currentActiveContent) {
            MessageChatContent contentItem = new MessageChatContent();
            contentItem.setMessageContent(currentActiveContentItem.getMessageContent());
            contentItem.setMessageType(currentActiveContentItem.getMessageType());
            contentItem.setMessageChatGroupId(messageGroupId);
            contentItem.setCreateBy(currentUserId.toString());
            contentItem.setCreateTime(DateUtils.getNowDate());
            contentItem.setSendUserId(currentUserId);
            content.add(contentItem);
        }

        iMessageChatContentService.saveBatch(content);
        unReadMessageContentId = content.stream().map(MessageChatContent::getId).collect(Collectors.toList());
        //对于所有人来说 除了自己都是未读讯息
        List<MessageContentUser> messageContentUsers = new ArrayList<>();
        Date date = DateUtils.getNowDate();
        for (Long userId : userIdList) {
            if (!userId.equals(currentUserId)) {
                for (Long unReadMessageContentIdItem : unReadMessageContentId) {
                    MessageContentUser messageContentUser = new MessageContentUser();
                    messageContentUser.setMessageChatContentId(unReadMessageContentIdItem);
                    messageContentUser.setReceiveUserId(userId);
                    messageContentUser.setReadStatus(ReadStatusEnum.UN_READ.getValue());
                    messageContentUser.setCreateBy(currentUserId.toString());
                    messageContentUser.setCreateTime(date);
                    messageContentUsers.add(messageContentUser);
                }

            }
        }
        iMessageContentUserService.saveBatch(messageContentUsers);
        //对于自己来说，已读该聊天室的所有信息
        //step1:查询这个聊天室 非自己发送的信息
        List<MessageChatContent> chatContents = iMessageChatContentService.list(
                Wrappers.<MessageChatContent>lambdaQuery()
                        .eq(MessageChatContent::getMessageChatGroupId, messageGroupId)
                        .ne(MessageChatContent::getSendUserId, currentUserId.toString())
                        .eq(MessageChatContent::getDelFlag, DelFlagEnum.NORMAL.getValue())
        );
        if(chatContents!=null&& !chatContents.isEmpty()){
            //STEP2:查询这些信息是否已经存在未读信息表中
            List<MessageContentUser> messageContentUserList = iMessageContentUserService.list(
                    Wrappers.<MessageContentUser>lambdaQuery()
                            .in(MessageContentUser::getMessageChatContentId, chatContents.stream().map(MessageChatContent::getId).collect(Collectors.toList()))
                            .eq(MessageContentUser::getReceiveUserId, currentUserId.toString())
                            .eq(MessageContentUser::getReadStatus, ReadStatusEnum.UN_READ.getValue())
                            .eq(MessageContentUser::getDelFlag, DelFlagEnum.NORMAL.getValue()));
            if(messageContentUserList!=null && !messageContentUserList.isEmpty()){
                messageContentUserList.forEach(item-> {
                    item.setReadStatus(ReadStatusEnum.READ.getValue());
                    item.setUpdateBy(currentUserId.toString());
                    item.setUpdateTime(date);
                });
                iMessageContentUserService.updateBatchById(messageContentUserList);
            }
        }



                //批量发送 讯息
                sentChatMessageToClientIdList(userIdListOnline, true, dto);
    }

    List<Long> getQuoteOrderUserIds(String quotationNo) {
        // 聊天室创建时,
        //（1）当前点击人
        //（2）报价单的创建人
        //（3）当前点击人的 区域链路上的 所有销售经理
        List<Long> userIdList = new ArrayList<>();
        userIdList.add(SecurityUtils.getUserId());
        List<TqQuotation> quotation = tqQuotationService.list(
                Wrappers.<TqQuotation>lambdaQuery()
                        .eq(TqQuotation::getQuotationNo, quotationNo)
                        .eq(TqQuotation::getDelFlag, DelFlagEnum.NORMAL.getValue())
        );
        if (quotation != null && !quotation.isEmpty()) {
            userIdList.addAll(quotation.stream().map((item) -> Long.valueOf(item.getCreateBy())).collect(Collectors.toList()));
        }
        List<SysUser> sysUsers = sysUserService.selectSaleByCurAgent();
        if (sysUsers != null && !sysUsers.isEmpty()) {
            List<Long> userIds = sysUsers.stream().map(SysUser::getUserId).collect(Collectors.toList());
            if (!userIds.isEmpty()) {
                userIdList.addAll(userIds);
            }
        }
        // @Date 2024/6/21 13:10 @Author jubs 😀 @description:因为聊天室 对所有群体开放，所以要查询该聊天室的所有用户
        List<MessageChat> chatRooms = iMessageChatService.list(
                Wrappers.<MessageChat>lambdaQuery()
                        .eq(MessageChat::getQuotationNo, quotationNo)
                        .eq(MessageChat::getDelFlag, DelFlagEnum.NORMAL.getValue()));
        if (chatRooms != null && !chatRooms.isEmpty()) {
            List<Long> chatRoomsId = chatRooms.stream().map(MessageChat::getId).collect(Collectors.toList());
            List<MessageChatUser> chatRoomsUser = iMessageChatUserService.list(
                    Wrappers.<MessageChatUser>lambdaQuery()
                            .in(MessageChatUser::getMessageChatId, chatRoomsId)
                            .eq(MessageChatUser::getDelFlag, DelFlagEnum.NORMAL.getValue())
            );
            if (chatRoomsUser != null && !chatRoomsUser.isEmpty()) {
                List<Long> chatRoomsUserId = chatRoomsUser.stream().map(MessageChatUser::getUserId)
                        .collect(Collectors.toList());
                if (!chatRoomsUserId.isEmpty()) {
                    userIdList.addAll(chatRoomsUserId);
                }
            }
        }
        //去重
        userIdList = userIdList.stream().distinct().collect(Collectors.toList());
        return userIdList;
    }


    public void sendChatRoomToClientByClientId(String clientId, MessageChatRes messageChatRes, SseEmitter sseEmitter) {
        if (sseEmitter == null) {
            log.error("推送消息失败：客户端{}未创建长链接,失败消息:{}", clientId, messageChatRes.toString());
            // 如果长连接不存在,由于SSE是由客户端向服务端发起请求创建链接的,所以,服务端并不知道链接是否存在,
            // 这里是如果链接不存在的话,在容器中将当前链接删除
            removeChatUser(clientId);
            return;
        }
        // 整合要发送消息内容数据,放到链接内
        SseEmitter.SseEventBuilder sendData = SseEmitter.event().id(clientId)
                .data(messageChatRes, MediaType.APPLICATION_JSON);
        try {
            // 最终发送消息的方法
            sseEmitter.send(sendData);
        } catch (Exception e) {
            /**
             * 这里通过捕捉发送消息一场的凡是判断是否发送成功,
             * 如果由异常产生,则视为发送失败,可做重试操作,或者其他发送失败的异常处理逻辑
             */
            // 推送消息失败，记录错误日志，进行重推
            log.error("推送消息失败：{},尝试进行重推", messageChatRes);
            boolean isSuccess = true;
            // 推送消息失败后，每隔10s推送一次，推送5次
            for (int i = 0; i < 1; i++) {
                try {
                    sseEmitter = sseChatCache.get(clientId);
                    if (sseEmitter == null) {
                        log.error("{}的第{}次消息重推失败，未创建长链接", clientId, i + 1);
                        removeChatUser(clientId);
                        return;
                    }
                    sseEmitter.send(sendData);
                } catch (Exception ex) {
                    log.error("{}的第{}次消息重推失败", clientId, i + 1, ex);
                    isSuccess = false;
                    continue;
                }
                log.info("{}的第{}次消息重推成功,{}", clientId, i + 1, messageChatRes);
                isSuccess = true;
            }
            if (!isSuccess) {
                removeChatUser(clientId);
            }
        }
    }


    /**
     * 长链接完成后回调接口(即关闭连接时调用)
     *
     * @param clientId 客户端ID
     **/
    private Runnable completionCallBack(String clientId) {
        return () -> {
            log.info("结束连接：{}", clientId);
            // 由于SSE长连接只能由客户端发起连接 服务端不能主动与客户端建立连接所以在服务端内如果关闭连接做删除连接操作
            removeChatUser(clientId);
        };
    }

    /**
     * 连接超时时调用
     *
     * @param clientId 客户端ID
     **/
    private Runnable timeoutCallBack(String clientId) {
        return () -> {
            log.info("连接超时：{}", clientId);
            // 由于SSE长连接只能由客户端发起连接 服务端不能主动与客户端建立连接所以在服务端内如果连接超时仅做删除连接操作
            removeChatUser(clientId);
        };
    }

    private void removeChatUser(String clientId) {
        sseChatCache.remove(clientId);
        log.info("SseEmitterServiceImpl[removeChatUser]:移除用户：{}", clientId);
    }


    /**
     * description: markUnreadMessage  标价每个人下的 聊天室是否有未读
     *
     * @param chatRoomsId: 聊天室id
     * @param userIds:     接收者id
     * @return java.util.Map<java.lang.String, java.lang.Boolean> 以 聊天室__接收人 作为key,是否有未读为value
     * @author jubs 😀
     * @date 2024/5/17 9:29
     */
    Map<String, Object> markUnreadMessage(List<Long> chatRoomsId, List<Long> userIds) {
        Map<String, Object> result = new HashMap<>();
        List<MessageContentUserDto> contentUserDtos = iMessageContentUserService.markUnReadMessage(chatRoomsId,
                userIds);
        // 以 聊天室+接收人分组
        Map<String, List<MessageContentUserDto>> groupByChatRoomIdAndUserId = contentUserDtos.stream()
                .collect(Collectors.groupingBy(it -> it.getMessageChatId() + "__" + it.getReceiveUserId()));


        if (!groupByChatRoomIdAndUserId.isEmpty()) {
            //循环此分组
            for (String key : groupByChatRoomIdAndUserId.keySet()) {
                List<MessageContentUserDto> messageContentUserDtos = groupByChatRoomIdAndUserId.get(key);

                for (MessageContentUserDto messageContentUserDto : messageContentUserDtos) {
                    //有未读讯息
                    if (key.contains(
                            messageContentUserDto.getMessageChatId() + "__" + messageContentUserDto.getReceiveUserId())
                            && messageContentUserDto.getUnReadMessage() > 0) {
                        //设置最新的一条未读信息的产生的事件
                        result.put(key + "lastUnReadTime", messageContentUserDto.getMaxUnReadMessageTime());
                        result.put(key, true);
                    } else {
                        result.put(key, false);
                    }
                }
                boolean flag = !messageContentUserDtos.isEmpty();
                if (flag) {
                    //计算总数
                    Integer unReadNum = 0;
                    for (MessageContentUserDto messageContentUserDto : messageContentUserDtos) {
                        unReadNum += messageContentUserDto.getUnReadMessage();
                    }
                    result.put(key + "unReadNum", unReadNum);
                }
            }
        }
        return result;

    }

}
