package com.yeejoin.amos.knowledgebase.face.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Sequence;
import com.yeejoin.amos.knowledgebase.face.model.KnowledgeMessageModel;
import com.yeejoin.amos.knowledgebase.face.orm.dao.MessageMapper;
import com.yeejoin.amos.knowledgebase.face.orm.entity.KnowledgeMessage;
import com.yeejoin.amos.knowledgebase.face.orm.entity.KnowledgeMessagePersonal;
import com.yeejoin.amos.knowledgebase.face.util.RemoteData;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.component.emq.EmqKeeper;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.exception.BaseException;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.exception.instance.DataNotFound;

import java.util.*;


/**
 * <p>
 * 标签库 服务类
 * </p>
 *
 * @author 子杨
 * @since 2020-08-05
 */
@Component
public class MessageService extends BaseService<KnowledgeMessageModel, KnowledgeMessage, MessageMapper> {

    /**
     * 消息类型-要点推送
     */
    public static final String MESSAGE_TYPE_PUSH = "ESSENTIAL_PUSH";
    /**
     * 消息类型-战例分享
     */
    public static final String MESSAGE_TYPE_SHARE = "DOC_SHARE";
    /**
     * 消息主题前缀
     */
    public static final String TOPIC_PREFIX = "knowledge_message_";

    public static final String SHARE_WAY_APP = "app";

    private final String userTypeUser = "user";
    private final String userTypeGroup = "group";

    @Autowired
    private MessagePersonalService messagePersonalService;
    @Autowired
    private EmqKeeper emqKeeper;
    @Autowired
    private Sequence sequence;


    /**
     * 根据用户查询消息列表
     */
    public List<Map> queryByOwner(String userId, String messageType) {
        try {
            List<Map> res = this.getBaseMapper().selectMessageListByOwner(userId, messageType);
            //翻译用户姓名
            Set<String> a = new HashSet<>();
            for (Map mesMap : res) {
                if (ValidationUtil.isEmpty(mesMap.get("sponsor"))) {
                    continue;
                }
                a.add(mesMap.get("sponsor").toString());
            }
            Map<String, String> userMap = RemoteData.getUserMap(a);
            for (Map mesMap : res) {
                if (ValidationUtil.isEmpty(mesMap.get("sponsor"))) {
                    continue;
                }
                mesMap.put("sponsorRealName", userMap.get(mesMap.get("sponsor").toString()));
            }
            return res;
        } catch (Exception e) {
            throw new DataNotFound("查询数据出错");
        }
    }

    /**
     * 根据消息id查询消息
     */
    public Map queryById(Long seq) {
        try {
            Map mesMap = this.getBaseMapper().selectMessageBySeq(seq);
            //翻译用户姓名
            mesMap.put("sponsorRealName", RemoteData.getUserRealNamById(mesMap.get("sponsor").toString()));
            return mesMap;
        } catch (Exception e) {
            throw new DataNotFound("查询数据出错");
        }
    }

    /**
     * 战例分享
     */
    @Transactional(rollbackFor = {BaseException.class, Exception.class})
    public boolean shareDoc(List<Map<String, Object>> users, List<Map<String, Object>> docs, String way) {
        if (ValidationUtil.equalsIgnoreCase(way, SHARE_WAY_APP)) {
            for (Map<String, Object> doc : docs) {
                //创建消息
                if (ValidationUtil.isEmpty(doc) || ValidationUtil.isEmpty(doc.get("sequenceNbr"))) {
                    throw new BadRequest("分享内容缺失");
                }
                String messageTitle = String.valueOf(doc.get("docTitle"));
                KnowledgeMessageModel message = createMessage(MESSAGE_TYPE_SHARE, Long.valueOf(doc.get("sequenceNbr").toString()), messageTitle, String.valueOf(doc.get("summary")));
                Set<String> userIdSet = new HashSet<>();
                userIdSet = parseUserMapToIdList(users, userIdSet);
                //创建个人消息
                createPersonalMessage(userIdSet, message.getSequenceNbr());
                //推送个人消息
                for (String userId : userIdSet) {
                    publishMessage(userId, message.getSequenceNbr());
                }
            }
        }
        return true;
    }

    /**
     * 要点推送
     */
    @Transactional(rollbackFor = {BaseException.class, Exception.class})
    public boolean pushEssential(List<Map<String, Object>> users, String messageTitle, String content, Long docSeq) {
        //创建消息
        KnowledgeMessageModel message = createMessage(MESSAGE_TYPE_PUSH, docSeq, messageTitle, content);
        Set<String> userIdSet = new HashSet<>();
        userIdSet = parseUserMapToIdList(users, userIdSet);
        //创建个人消息
        createPersonalMessage(userIdSet, message.getSequenceNbr());
        //推送个人消息
        for (String userId : userIdSet) {
            publishMessage(userId, message.getSequenceNbr());
        }
        return true;
    }

    /**
     * 消息已读
     */
    @Transactional(rollbackFor = {BaseException.class, Exception.class})
    public List<KnowledgeMessagePersonal> readMessage(List<Long> ids) {
        QueryWrapper<KnowledgeMessagePersonal> queryWrapper = new QueryWrapper();
        queryWrapper.in("SEQUENCE_NBR", ids);
        List<KnowledgeMessagePersonal> messagePersonalModelList = messagePersonalService.list(queryWrapper);
        if (messagePersonalModelList.size() < 1) {
            throw new DataNotFound("找不到数据");
        }
        for (int i = 0; i < messagePersonalModelList.size(); i++) {
            messagePersonalModelList.get(i).setMessageStatus(MessagePersonalService.MESSAGE_STATUS_READ);
        }
        messagePersonalService.updateBatchById(messagePersonalModelList);
        return messagePersonalModelList;
    }

    /**
     * 消息全读
     */
    @Transactional(rollbackFor = {BaseException.class, Exception.class})
    public boolean readAllMessageByUserId(String userId) {
        KnowledgeMessagePersonal messagePersonal = new KnowledgeMessagePersonal();
        messagePersonal.setMessageStatus(MessagePersonalService.MESSAGE_STATUS_READ);
        UpdateWrapper<KnowledgeMessagePersonal> wrapper = new UpdateWrapper();
        wrapper.eq("MESSAGE_OWNER", userId);
        return messagePersonalService.update(messagePersonal, wrapper);
    }

    /**
     * 创建消息
     */
    private KnowledgeMessageModel createMessage(String messageType, Long targetSeq, String messageTitle, String messageContent) {
        KnowledgeMessageModel messageModel = new KnowledgeMessageModel();
        messageModel.setMessageType(messageType);
        messageModel.setTargetSeq(targetSeq);
        messageModel.setMessageTitle(messageTitle);
        messageModel.setMessageContent(messageContent);
        return this.createWithModel(messageModel);
    }

    /**
     * 创建个人消息
     */
    private boolean createPersonalMessage(Collection<String> ownerList, Long messageSeq) {
        if (!ValidationUtil.isEmpty(messageSeq)) {
            List<KnowledgeMessagePersonal> messageList = new ArrayList<>();
            Date now = new Date();
            String userId = RequestContext.getExeUserId();
            ownerList.forEach(owner -> {
                KnowledgeMessagePersonal message = new KnowledgeMessagePersonal();
                message.setSequenceNbr(sequence.nextId());
                message.setRecDate(now);
                message.setRecUserId(userId);
                message.setMessageOwner(owner);
                message.setMessageSeq(messageSeq);
                message.setMessageStatus(MessagePersonalService.MESSAGE_STATUS_UNREAD);
                messageList.add(message);
            });
            messagePersonalService.saveBatch(messageList);
        }
        return true;
    }

    /**
     * 用户/分组列表转为用户列表
     */
    private Set<String> parseUserMapToIdList(List<Map<String, Object>> users, Set<String> res) {
        if (!ValidationUtil.isEmpty(users)) {
            for (Map<String, Object> user : users) {
                String type = String.valueOf(user.get("type"));
                if (ValidationUtil.equalsIgnoreCase(userTypeUser, type)) {
                    String id = String.valueOf(user.get("id"));
                    res.add(id);
                } else if (ValidationUtil.equalsIgnoreCase(userTypeGroup, type)) {
                    if (user.containsKey("children")) {
                        Object childrenObj = user.get("children");
                        if (!ValidationUtil.isEmpty(childrenObj) && childrenObj instanceof List) {
                            List<Map<String, Object>> list = (List<Map<String, Object>>) childrenObj;
                            parseUserMapToIdList(list, res);
                        }
                    }
                }
            }
        }
        return res;
    }


    /**
     * 发布消息
     */
    private void publishMessage(String owner, Long messageSeq) {
        try {
            emqKeeper.getMqttClient().publish(getTopic(owner), messageSeq.toString().getBytes(), 2, false);
        } catch (MqttException e) {
            log.error("消息推送失败：接收人" + owner + "，消息id：" + messageSeq);
        }
    }

    /**
     * 获取用户的主题
     */
    private String getTopic(String userId) {
        return TOPIC_PREFIX + String.valueOf(userId);
    }

    /**
     * 分页查询消息
     */
    public List<Map> queryByPage(String userId, int current, int size, String messageType) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("owner", userId);
            param.put("current", (current - 1) * size);
            param.put("size", size);
            param.put("messageType", messageType);
            List<Map> res = this.getBaseMapper().selectMessageListByPage(param);
            //翻译用户姓名
            Set<String> a = new HashSet<>();
            for (Map mesMap : res) {
                if (ValidationUtil.isEmpty(mesMap.get("sponsor"))) {
                    continue;
                }
                a.add(mesMap.get("sponsor").toString());
            }
            Map<String, String> userMap = RemoteData.getUserMap(a);
            for (Map mesMap : res) {
                if (ValidationUtil.isEmpty(mesMap.get("sponsor"))) {
                    continue;
                }
                mesMap.put("sponsorRealName", userMap.get(mesMap.get("sponsor").toString()));
            }
            return res;
        } catch (Exception e) {
            throw new DataNotFound("查询数据出错");
        }
    }

    /**
     * 分页查询消息总数
     */
    public Integer queryByPageCount(String userId, String messageType) {
        try {
            Map<String, Object> param = new HashMap<>();
            param.put("owner", userId);
            param.put("messageType", messageType);
            return this.getBaseMapper().selectMessageListByCount(param);
        } catch (Exception e) {
            throw new DataNotFound("查询数据出错");
        }
    }
}
