package com.wecloud.im.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImInbox;
import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.mapper.ImInboxMapper;
import com.wecloud.im.param.ImMsgReadStatusUpdate;
import com.wecloud.im.param.ImMsgReceivedStatusUpdate;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationMembersService;
import com.wecloud.im.service.ImInboxService;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.ws.enums.MsgTypeEnum;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.sender.ChannelSender;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 消息收件箱表 服务实现类
 *
 * @author wei
 * @since 2021-05-06
 */
@Slf4j
@Service
public class ImInboxServiceImpl extends BaseServiceImpl<ImInboxMapper, ImInbox> implements ImInboxService {

    @Autowired
    private ImInboxMapper imInboxMapper;
    @Autowired
    private ImClientService imClientService;

    @Autowired
    private ImMessageService imMessageService;

    @Autowired
    private ImConversationMembersService imConversationMembersService;
    @Autowired
    private ChannelSender channelSender;

    @Autowired
    private ImApplicationService imApplicationService;


//    @Transactional(rollbackFor = Exception.class)
//    @Override
//    public boolean saveImInbox(ImInbox imInbox) throws Exception {
//        return super.save(imInbox);
//    }
//
//    @Transactional(rollbackFor = Exception.class)
//    @Override
//    public boolean updateImInbox(ImInbox imInbox) throws Exception {
//        return super.updateById(imInbox);
//    }
//
//    @Transactional(rollbackFor = Exception.class)
//    @Override
//    public boolean deleteImInbox(Long id) throws Exception {
//        return super.removeById(id);
//    }
//
//    @Override
//    public ImInboxQueryVo getImInboxById(Long id) throws Exception {
//        return imInboxMapper.getImInboxById(id);
//    }
//
//    @Override
//    public Paging<ImInboxQueryVo> getImInboxPageList(ImInboxPageParam imInboxPageParam) throws Exception {
//        Page<ImInboxQueryVo> page = new PageInfo<>(imInboxPageParam, OrderItem.desc(getLambdaColumn(ImInbox::getCreateTime)));
//        IPage<ImInboxQueryVo> iPage = imInboxMapper.getImInboxPageList(page, imInboxPageParam);
//        return new Paging<ImInboxQueryVo>(iPage);
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<Boolean> updateImMsgReceived(ImMsgReceivedStatusUpdate imMsgReceivedUpdate) {
        ImClient curentClient = imClientService.getCurentClient();

        // 修改已接收状态
        Long aLong = imInboxMapper.updateImMsgReceivedByIds(curentClient.getId(), imMsgReceivedUpdate.getMsgIds());

        //  根据appKey查询appid
        ImApplication application = imApplicationService.getCacheById(curentClient.getFkAppid());

        // 内容
        HashMap<String, String> contentMap = new HashMap<>();
        contentMap.put("receiverId", curentClient.getClientId());
        // 推送给接收方
        sendMsgStatus(curentClient, MsgTypeEnum.CLIENT_RECEIVED_MSG, contentMap, imMsgReceivedUpdate.getMsgIds());

        // 是否同时修改为已读状态
        if (imMsgReceivedUpdate.getReadStatus()) {

            ImMsgReadStatusUpdate imMsgReadStatusUpdate = new ImMsgReadStatusUpdate();
            imMsgReadStatusUpdate.setMsgIds(imMsgReceivedUpdate.getMsgIds());
            this.updateImMsgRead(imMsgReadStatusUpdate);

        }
        return ApiResult.ok();
    }

    /**
     * 统计未读消息数量
     *
     * @param clientId
     * @return
     */
    @Override
    public Integer countMyNotReadCount(Long clientId) {


        return imInboxMapper.countMyNotReadCount(clientId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<Boolean> updateImMsgRead(ImMsgReadStatusUpdate imMsgReadStatusUpdate) {
        ImClient curentClient = imClientService.getCurentClient();

        // 修改已读状态
        Long aLong = imInboxMapper.updateImMsgReadByIds(curentClient.getId(), imMsgReadStatusUpdate.getMsgIds());

        //  根据appKey查询appid
        ImApplication application = imApplicationService.getCacheById(curentClient.getFkAppid());

        // 内容
        HashMap<String, String> contentMap = new HashMap<>();
        contentMap.put("receiverId", curentClient.getClientId());
        sendMsgStatus(curentClient, MsgTypeEnum.CLIENT_READ_MSG, contentMap, imMsgReadStatusUpdate.getMsgIds());

        return ApiResult.ok();

    }

    /**
     * 下发状态类型消息
     *
     * @param curentClient        当前客户端
     * @param msgTypeEnum         消息类型枚举
     * @param contentMap          消息content内容
     * @param msgIds              消息id集合
     */
    private void sendMsgStatus(ImClient curentClient, MsgTypeEnum msgTypeEnum, HashMap<String, String> contentMap, List<Long> msgIds) {

        // 遍历消息id集合
        for (Long msgId : msgIds) {

            // 查询该消息
            ImMessage imMessageDb = imMessageService.getById(msgId);

            // 根据会话id查询该会话所有成员
            List<ImConversationMembers> membersList = imConversationMembersService.list(
                    new QueryWrapper<ImConversationMembers>().lambda()
                            .eq(ImConversationMembers::getFkConversationId, imMessageDb.getFkConversationId())
                            .notIn(ImConversationMembers::getFkClientId, curentClient.getId())
            );

            // 遍历发送给该会话的每个成员
            for (ImConversationMembers conversationMember : membersList) {

                //  消息实体
                ImMessage imMessage = new ImMessage();
                imMessage.setId(msgId);
                imMessage.setMsgType(msgTypeEnum.getUriCode());
                imMessage.setCreateTime(new Date());
                imMessage.setFkAppid(curentClient.getFkAppid());
                imMessage.setSender(curentClient.getId());
                imMessage.setWithdraw(false);
                imMessage.setEvent(true);
                imMessage.setSystemFlag(false);
                imMessage.setSendStatus(2);
                imMessage.setFkConversationId(conversationMember.getFkConversationId());

                // 封装响应的实体
                ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();
                BeanUtils.copyProperties(imMessage, imMessageOnlineSend);
                imMessageOnlineSend.setType(msgTypeEnum.getUriCode());
                imMessageOnlineSend.setMsgId(imMessage.getId());
                imMessageOnlineSend.setSender(curentClient.getClientId());
                imMessageOnlineSend.setContent(contentMap);
                imMessageOnlineSend.setConversationId(conversationMember.getFkConversationId());
                // 查询接收方
                ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                        .eq(ImClient::getFkAppid, curentClient.getFkAppid())
                        .eq(ImClient::getId, conversationMember.getFkClientId()));
                if (imClientReceiver == null) {
                    continue;
                }
                //  向接收方推送
                WsResponse<ImMessageOnlineSend> responseModel = new WsResponse<>();
                responseModel.setCmd(WsResponseCmdEnum.ONLINE_EVENT_MSG.getCmdCode());
                ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
                responseModel.setCode(result.getCode());
                responseModel.setMsg(result.getMessage());
                responseModel.setData(imMessageOnlineSend);
                responseModel.setReqId(null);
                channelSender.sendMsg(responseModel, imClientReceiver.getId());
            }
        }
    }

}
