package com.testor.module.messageNotice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.testor.biz.sys.user.model.domain.SysUser;
import com.testor.biz.sys.user.service.SysUserService;
import com.testor.common.constant.StatusEnum;
import com.testor.module.messageNotice.dao.TMsgNoticeDao;
import com.testor.module.messageNotice.model.domain.TMsgNotice;
import com.testor.module.messageNotice.model.vo.FlowableModelInfo;
import com.testor.module.messageNotice.model.vo.ModelObjVO;
import com.testor.module.messageNotice.model.vo.MsgTemplateVO;
import com.testor.module.messageNotice.service.TMsgNoticeService;
import com.tongtech.tfw.backend.common.context.ContextUtils;
import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 消息通知Service业务层处理
 *
 * @author testor-framework
 * @date 2022-05-18 19:38:47
 */
@Slf4j
@Service
public class TMsgNoticeServiceImpl extends SuperServiceImpl<TMsgNoticeDao, TMsgNotice> implements TMsgNoticeService {
    @Autowired
    private TMsgNoticeDao tMsgNoticeDao;
    @Resource
    private FlowableModelInfo flowableModelInfo;

    @Autowired
    private SysUserService userService;

    /**
     * 通过流程示例id，处理消息
     * @param processInstanceId
     */
    public void processPassMsgHandleByProDefInsId(String processInstanceId){
        if(StrUtil.isBlank(processInstanceId)) {
            return;
        }
        // todo 根据 processInstanceId 获取相关信息 处理逻辑
        String startUserId = null;
        String businessKey = null;
        Map variablesMap = null;

        processPassMsgHandle(startUserId, businessKey, variablesMap);
    }

    /**
     * 审批流程通过后的消息通知处理
     */
    @Transactional
    public void processPassMsgHandle(String startUserId, String businessKey, Map variablesMap) {
        if (StrUtil.isBlank(businessKey) || variablesMap == null || variablesMap.size() == 0) {
            return;
        }

        List<ModelObjVO> modelList = flowableModelInfo.getModelArr();
        if (modelList == null || modelList.size() == 0) {
            return;
        }

        String bizKeyId = variablesMap.get("bizKeyId").toString();
        ModelObjVO modelObj = null;
        for (ModelObjVO item : modelList) {
            if (!businessKey.equals(item.getKey())) {
                continue;
            }
            modelObj = item;
            break;
        }

        if (modelObj == null || modelObj.getMsgTemplateArr() == null || modelObj.getMsgTemplateArr().size() == 0) { // 不存在消息模板
            return;
        }
        List<MsgTemplateVO> msgTemplateList = modelObj.getMsgTemplateArr();
        Map<String, MsgTemplateVO> msgTemplateMap = new HashMap<>();
        // 保存 除 approved 、 notice 两种基本消息模板 外的模板
        Map<String, MsgTemplateVO> msgOtherTemplateMap = new HashMap<>();
        for(MsgTemplateVO item : msgTemplateList) {
            msgTemplateMap.put(item.getTemplateType(), item);
            if(!"approved".equals(item.getTemplateType()) && !"notice".equals(item.getTemplateType())) {
                msgOtherTemplateMap.put(item.getTemplateType(), item);
            }
        }

        // 审核通过向 申请人 发送消息
        MsgTemplateVO approvedTemplateObj = msgTemplateMap.get("approved");
      ///  MsgTemplateVO finalMsgTemplateVO = BeanHelper.beanToBean(approvedTemplateObj, MsgTemplateVO.class);;
        MsgTemplateVO finalMsgTemplateVO = new MsgTemplateVO();
        BeanUtil.copyProperties(approvedTemplateObj, finalMsgTemplateVO);
        // 处理解析 消息模型 逻辑
        String msgContent = analysisMsgTemplate(finalMsgTemplateVO.getTemplateContent(), variablesMap);
        finalMsgTemplateVO.setTemplateContent(msgContent);
        List<String> list = new ArrayList<>();
        list.add(startUserId);
        List<TMsgNotice> tMsgNoticeList = generateMsgNotice(businessKey, bizKeyId, list, finalMsgTemplateVO);

        // todo 处理 除两种基本消息外的消息 逻辑
        List<TMsgNotice> tMsgNoticeOtherList = handleOtherMsgTemplate(businessKey, bizKeyId, msgOtherTemplateMap, variablesMap);
        if(tMsgNoticeOtherList != null && tMsgNoticeOtherList.size() > 0) {
            tMsgNoticeList.addAll(tMsgNoticeOtherList);
        }

        if (msgTemplateMap.get("notice") == null // 通知消息模板为配置，则不进行发送
                || StrUtil.isBlank(msgTemplateMap.get("notice").getTemplateType())) {
            saveBatch(tMsgNoticeList);
            return;
        }

        String tableName = modelObj.getTable();
        List<String> userIdList = obtainMsgUsers(tableName, bizKeyId);
        if(userIdList == null || userIdList.size() == 0) {
            saveBatch(tMsgNoticeList);
            return ;
        }
        userIdList.remove(startUserId);
        if(userIdList == null || userIdList.size() == 0) {
            saveBatch(tMsgNoticeList);
            return ;
        }
        // 审核通过向 指定用户 发送消息
        MsgTemplateVO noticeTemplateObj = msgTemplateMap.get("notice");
        MsgTemplateVO finalNoticeTemplateVO = new MsgTemplateVO();
        BeanUtil.copyProperties(noticeTemplateObj, finalNoticeTemplateVO);
        String noticeMsgContent = analysisMsgTemplate(finalNoticeTemplateVO.getTemplateContent(), variablesMap);
        finalNoticeTemplateVO.setTemplateContent(noticeMsgContent);
        List<TMsgNotice> tMsgNoticeListTwo = generateMsgNotice(businessKey, bizKeyId, userIdList, finalNoticeTemplateVO);

        tMsgNoticeList.addAll(tMsgNoticeListTwo);
        boolean saveResult = saveBatch(tMsgNoticeList);
    }

    /**
     * 获取 需要发送消息的 用户
     *
     * @param tableName 业务表
     * @param bizKeyId  业务id
     * @return
     */
    public List<String> obtainMsgUsers(String tableName, String bizKeyId) {
        try{
            Map receiverObjMap = tMsgNoticeDao.selectReceiverObjById(tableName, bizKeyId);
            if (receiverObjMap == null || receiverObjMap.size() == 0) {  // 不存在接收对象，不进行处理
                return null;
            }

            if (receiverObjMap.get("receiver_type") == null) {
                return null;
            }
            // receiver_type(比如：-1、不存在接收对象，0：所有人，1-代表接收人、2代表组织结构)
            String receiverType = receiverObjMap.get("receiver_type").toString();
            // 接收对象：可为人，组织机构，根据receiver_type确定)、
           // String receiverObj = receiverObjMap.get("receiver_obj").toString();

            if ("-1".equals(receiverType)) { // 不存在，不进行处理
                return null;
            }

            List<String> userIdList;
            if ("0".equals(receiverType)) { // 所有人通知
                QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
                queryWrapper.select("user_id").eq("status", "0");
                List<SysUser> userList = userService.list(queryWrapper);
                if (userList == null || userList.size() == 0) {
                    return null;
                }
                userIdList = userList.parallelStream().map(SysUser::getUserId).collect(Collectors.toList());

            } else if ("1".equals(receiverType)) { // 向指定人发送消息
                // 接收对象：可为人，组织机构，根据receiver_type确定)、
                String receiverObj = receiverObjMap.get("receiver_obj").toString();
                String[] strs = receiverObj.split(",");
                userIdList = Arrays.asList(strs);

            } else if ("2".equals(receiverType)) {  // 向指定组织下的人员发送消息
                // 接收对象：可为人，组织机构，根据receiver_type确定)、
                String receiverObj = receiverObjMap.get("receiver_obj").toString();
                List orgIdList = Arrays.asList(receiverObj.split(","));
                LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.select(SysUser::getUserId)
                        .in(SysUser::getOrgId, orgIdList)
                        .eq(SysUser::getStatus, "0");
                List<SysUser> userList = userService.list(queryWrapper);
                if (userList == null || userList.size() == 0) {
                    return null;
                }
                userIdList = userList.parallelStream().map(SysUser::getUserId).collect(Collectors.toList());

            } else {
                userIdList = null;
            }

            return userIdList;

        }catch(Exception e) {
            log.info(e.toString());
            return null;
        }
    }


    /**
     * 组装消息通知
     *
     * @param bizKey
     * @param bizKeyId
     * @param userIdList
     * @param msgTemplate
     * @return
     */
    public List<TMsgNotice> generateMsgNotice(String bizKey, String bizKeyId, List<String> userIdList, MsgTemplateVO msgTemplate) {
        if (userIdList == null || userIdList.size() == 0) {
            return null;
        }

        List<TMsgNotice> tMsgNoticeList = new ArrayList<>();
        TMsgNotice msgNotice;
        for (String userId : userIdList) {
            msgNotice = new TMsgNotice();
            msgNotice.setBusinessId(bizKeyId);
            msgNotice.setBusinessKey(bizKey);
            msgNotice.setMsgType(msgTemplate.getTemplateType());
            msgNotice.setMsgTypeName(msgTemplate.getTemplateTypeName());
            msgNotice.setContent(msgTemplate.getTemplateContent());
            msgNotice.setIsRead("0");
            msgNotice.setUserId(userId);
            tMsgNoticeList.add(msgNotice);
        }
        return tMsgNoticeList;
    }

    /**
     * 解析消息模板
     *
     * @param msgTemplate
     * @param variablesMap
     * @return
     */
    public String analysisMsgTemplate(String msgTemplate, Map<String, String> variablesMap) {
        if (StrUtil.isBlank(msgTemplate) || variablesMap == null || variablesMap.size() == 0) {
            return null;
        }
        System.out.println("analysisMsgTemplate msgTemplate="+msgTemplate);
        System.out.println("analysisMsgTemplate variablesMap="+variablesMap);
        if (msgTemplate.indexOf("{") < 0) { // 没有参数，不需要处理
            return msgTemplate;
        }

        String pattern = "\\{[^}]*\\}"; // 匹配{} 的表达式
        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(msgTemplate);
        StringBuffer sb = new StringBuffer();
        while (m.find()) {
            String matchKey = m.group(0); // matchKey: {title}
            String key = matchKey.substring(1,matchKey.length()-1);
            String value = null;
            if(!StrUtil.isBlank(key)) {
                value = variablesMap.get(key);
            }
            m.appendReplacement(sb, value == null ? "" : value);
        }
        m.appendTail(sb);
        return sb.toString();
    }

    /**
     *  处理  除两种基本消息外的 消息
     * @param msgOtherTemplateMap
     * @return
     */
    public List<TMsgNotice> handleOtherMsgTemplate(String businessKey, String bizKeyId, Map<String, MsgTemplateVO> msgOtherTemplateMap, Map variablesMap) {
        if(msgOtherTemplateMap == null || msgOtherTemplateMap.size() == 0) {
            return null;
        }
        List<TMsgNotice> tMsgNoticeOtherList =  new ArrayList<>();
        for (Map.Entry<String, MsgTemplateVO> entry : msgOtherTemplateMap.entrySet()) {

            MsgTemplateVO templateVO = entry.getValue();
            if(templateVO.getTemplateReceiverObj() == null) {
                return null;
            }
            String receiverObj = templateVO.getTemplateReceiverObj().toString();
            if(variablesMap.get(receiverObj) == null) {
                return null;
            }
            String receiverObjValue = variablesMap.get(receiverObj).toString();
            if(StrUtil.isBlank(receiverObjValue)) {
                return null;
            }

            MsgTemplateVO finalMsgTemplateVO = new MsgTemplateVO();
            BeanUtil.copyProperties(templateVO, finalMsgTemplateVO);
            // 处理解析 消息模型 逻辑
            String msgContent = analysisMsgTemplate(finalMsgTemplateVO.getTemplateContent(), variablesMap);
            finalMsgTemplateVO.setTemplateContent(msgContent);

            List<String> list = new ArrayList<>();
            Collections.addAll(list,receiverObjValue.split(","));

            List<TMsgNotice> tMsgNoticeList = generateMsgNotice(businessKey, bizKeyId, list, finalMsgTemplateVO);
            tMsgNoticeOtherList.addAll(tMsgNoticeList);
        }

        return tMsgNoticeOtherList;
    }

    /**
     * 标记为已读
     * @param msgNoticeId
     */
    public boolean read(String msgNoticeId){
        if(StrUtil.isBlank(msgNoticeId)) {
            return false;
        }

        UpdateWrapper<TMsgNotice> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", msgNoticeId);
        updateWrapper.eq("user_id", ContextUtils.getLoginUserId());
        updateWrapper.set("is_read", "1");
        int result = tMsgNoticeDao.update(null, updateWrapper);
        return true;
    }

    /**
     * 标记为已读
     * @param businessKey 模块类型
     * @param businessId  业务id
     */
    public boolean read(String businessKey, String businessId) {
        if(StrUtil.isBlank(businessKey) || StrUtil.isBlank(businessId)) {
            return false;
        }

        UpdateWrapper<TMsgNotice> updateWrapper = new UpdateWrapper<>();
        if(!StrUtil.isBlank(businessKey)) {
            updateWrapper.eq("business_key", businessKey);
        }
        updateWrapper.eq("business_id", businessId);
        updateWrapper.eq("user_id", ContextUtils.getLoginUserId());
        updateWrapper.eq("status", StatusEnum.USE.getCode());
        updateWrapper.set("is_read", "1");
        tMsgNoticeDao.update(null, updateWrapper);
        return true;
    }

    /**
     * 批量标记为已读
     * @param msgNoticeIds
     */
    public boolean readByArr(String msgNoticeIds){
        if(StrUtil.isBlank(msgNoticeIds)) {
            return false;
        }

        UpdateWrapper<TMsgNotice> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("user_id", ContextUtils.getLoginUserId());
        if(!"-1".equals(msgNoticeIds)) {
            List<String> ids = Arrays.asList(msgNoticeIds.split(","));
            updateWrapper.in("id", ids);
        }
        updateWrapper.set("is_read", "1");
        update(null, updateWrapper);
        return true;
    }

    /**
     * 批量标记为已读
     */
    public boolean readByArr(String businessKey, String businessIds){
        if(StrUtil.isBlank(businessKey) && StrUtil.isBlank(businessIds) ) {
            return false;
        }

        UpdateWrapper<TMsgNotice> updateWrapper = new UpdateWrapper<>();
        if(!StrUtil.isBlank(businessKey)) {
            updateWrapper.eq("business_key", businessKey);
        }
        if(!StrUtil.isBlank(businessIds)) {
            List<String> businessIdList = Arrays.asList(businessIds.split(","));
            updateWrapper.in("business_id", businessIdList);
        }
        updateWrapper.eq("user_id", ContextUtils.getLoginUserId());
        updateWrapper.eq("status", StatusEnum.USE.getCode());
        updateWrapper.set("is_read", "1");
        tMsgNoticeDao.update(null, updateWrapper);
        return true;
    }

    /**
     * 统计用户 每个流程定义中 未读的个数
     */
    public List<Map> countUnRead(@Param("userId") String userId){
        if(StrUtil.isBlank(userId)) {
            return null;
        }
        return tMsgNoticeDao.countUnRead(userId);
    }
}
