package com.skua.modules.quartz;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngines;
import org.flowable.engine.TaskService;
import org.flowable.identitylink.api.IdentityLink;
import org.flowable.identitylink.api.IdentityLinkType;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.skua.core.context.SpringContextUtils;
import com.skua.core.util.ConvertUtils;
import com.skua.core.util.DateUtils;
import com.skua.core.util.chuanglan.HttpSenderMsg;
import com.skua.core.util.push.IPushService;
import com.skua.core.util.push.MessageEntity;
import com.skua.core.util.push.PushMessageFactory;
import com.skua.modules.alarmtmp.entity.AlarmCustomRuleRepository;
import com.skua.modules.alarmtmp.entity.AlarmMessageHistory;
import com.skua.modules.alarmtmp.entity.AlarmRecordHistory;
import com.skua.modules.alarmtmp.entity.AlarmRuleConfigPublicTab;
import com.skua.modules.alarmtmp.entity.AlarmRuleLevelConfig;
import com.skua.modules.alarmtmp.entity.AlarmRuleLevelConfigTemplate;
import com.skua.modules.alarmtmp.service.AlarmMessageHistoryService;
import com.skua.modules.alarmtmp.service.AlarmRecordHistoryService;
import com.skua.modules.alarmtmp.service.AlarmRuleConfigService;
import com.skua.modules.alarmtmp.service.IAlarmCustomRuleRepositoryService;
import com.skua.modules.alarmtmp.service.IAlarmRuleConfigPublicTabService;
import com.skua.modules.alarmtmp.service.IAlarmRuleLevelConfigTemplateService;
import com.skua.modules.alarmtmp.vo.AlarmRuleConfigAndLevelVO;
import com.skua.modules.alarmtmp.vo.SystemNoticeVO;
import com.skua.modules.flow.business.service.FlowBusinessService;
import com.skua.modules.flow.business.service.IFlowService;
import com.skua.modules.flow.core.constant.ProcessConstant;
import com.skua.modules.flow.core.entity.BladeFlow;
import com.skua.modules.flow.core.utils.FlowUtil;
import com.skua.modules.flow.support.Kv;
import com.skua.modules.flow.utils.Func;
import com.skua.modules.system.entity.SysUser;
import com.skua.modules.system.service.IPgService;
import com.skua.modules.system.service.ISysUserService;
import com.skua.modules.util.SysMessagePushService;
import com.skua.modules.util.SystemNoticeUtils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
/**
 * @program: skboot
 * @description: 实时判断是否存在超时的警告
 * @author: xie chao
 * @create: 2020-11-02 13:48
 */
@Slf4j
@Component
public class RealTimeAlarmJob implements Job {
    @Autowired
    private AlarmRuleConfigService alarmRuleConfigService;
    @Value("${skua.alarmTimeInterval:}")
    private String alarmTimeInterval;//获取时间间隔
    @Autowired
    private AlarmRecordHistoryService alarmRecordHistoryService;
    @Autowired
    private AlarmMessageHistoryService alarmMessageHistoryService;
    @Autowired
    private IAlarmRuleLevelConfigTemplateService alarmRuleLevelConfigTemplateService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private SystemNoticeUtils systemNoticeUtils;
    @Autowired
    private IPgService pgService;
    @Autowired
    private IFlowService flowService;
    @Autowired
    private FlowBusinessService flowBusinessService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private IAlarmRuleConfigPublicTabService alarmRuleConfigPublicTabService;
    @Autowired
    private IAlarmCustomRuleRepositoryService alarmCustomRuleRepositoryService;

    private static String prefix = "【金控数矿】在";
    private static String departNameTemplete = "${departName}";
    private static String contentTemplete = "${alarmParamName}:${actualAvgValue}(${limit})${alarmParamUnit}";
    private static String suffix = ",请注意!";
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            log.info("水质实时数据报警任务开始");
            //获取水质、水量、工艺报警规则信息
            List<AlarmRuleConfigAndLevelVO> alarmRuleAndAlarmRuleLevelVOList = alarmRuleConfigService.getAlarmRuleAndAlarmRuleLeveList("realTimeAlarmJob");
            //获取设备参数报警规则信息
            List<AlarmRuleConfigAndLevelVO> equipAlarmRuleAndAlarmRuleLevelVOList = alarmRuleConfigService.getAlarmRuleAndAlarmRuleLeveList("equipRealTimeAlarmJob");
            //将报警规则合并
            List<AlarmRuleConfigAndLevelVO> allAlarmRuleAndAlarmRuleLevelVOList = new ArrayList<AlarmRuleConfigAndLevelVO>();
            if(alarmRuleAndAlarmRuleLevelVOList!=null&&alarmRuleAndAlarmRuleLevelVOList.size()>0) {
            	allAlarmRuleAndAlarmRuleLevelVOList.addAll(alarmRuleAndAlarmRuleLevelVOList);
            }
            if(equipAlarmRuleAndAlarmRuleLevelVOList!=null&&equipAlarmRuleAndAlarmRuleLevelVOList.size()>0) {
            	allAlarmRuleAndAlarmRuleLevelVOList.addAll(equipAlarmRuleAndAlarmRuleLevelVOList);
            }

            //查询pg数据超标警报
            Map<String, Object> excessAlarmPgList = checkPgExcessAlarm(allAlarmRuleAndAlarmRuleLevelVOList);
            sendMessage(excessAlarmPgList);
            log.info("水质实时数据任务开始结束");
        } catch (Exception e) {
        	e.printStackTrace();
            log.error("水质实时数据任务异常" + e);
        }
    }
    /**
     * 判断pg数据库中超标的警报
     *
     * @param pgExcessAlarmList
     */
    public Map<String, Object> checkPgExcessAlarm(List<AlarmRuleConfigAndLevelVO> pgExcessAlarmList) {
        Map<String, Object> result = Maps.newHashMap();
        //存放厂ID和指标的List集合
        Map<String, String> stringMap = new HashMap<>();
        pgExcessAlarmList.forEach(alarmRuleAndAlarmRuleLevelVO -> {
            String alarmProgramCode = stringMap.get(alarmRuleAndAlarmRuleLevelVO.getDepartId());
            if (StringUtils.isBlank(alarmProgramCode)) {
                stringMap.put(alarmRuleAndAlarmRuleLevelVO.getDepartId(), alarmRuleAndAlarmRuleLevelVO.getAlarmProgramCode());
            } else {
                stringMap.put(alarmRuleAndAlarmRuleLevelVO.getDepartId(), alarmProgramCode + "," + alarmRuleAndAlarmRuleLevelVO.getAlarmProgramCode());
            }
        });
        Map<String, List<Map<String, Object>>> resultListMap = new HashMap<>();
        Long now = DateUtils.getMillis() / 1000;
        //循环将计算数据取出
        stringMap.forEach((departId, alarmProgramCodeStr) -> {
            Long start = now - Integer.parseInt(alarmTimeInterval);
            //根据departId查询数据库的数据,查询的时候注意将超标的字段设置为查询字段
            List<Map<String, Object>> maps = pgService.queryAlarmInfoByXT(departId, alarmProgramCodeStr, start.toString(), now.toString());
            if (maps != null && maps.size() > 0) {
                resultListMap.put(departId, maps);
            }
        });
        Map<String, Map<String, Map<String,Object>>> tmp = new HashMap<>();
        //先按照机构id分组,内部在按照指标名称分组
        if (resultListMap != null && resultListMap.size() > 0) {
            resultListMap.forEach((departId, maps) -> {
                Map<String, List<Map<String, Object>>> nm = maps.stream().collect(Collectors.groupingBy(v -> (String) v.get("nm")));
                nm.forEach((key, value) -> {
                	//获取最大值,最小值
                	value = value.stream().sorted((i, j) -> Double.compare(ConvertUtils.getDouble(i.get("v"), 0), ConvertUtils.getDouble(j.get("v"), 0))).collect(Collectors.toList());
                    //DoubleSummaryStatistics summaryStatistics = value.stream().mapToDouble(value1 -> Double.parseDouble((String) value1.get("v"))).summaryStatistics();
                	Map<String, Map<String,Object>> map = Maps.newHashMap();
                	if(value!=null&&value.size()>0) {
                		map.put("max", CollUtil.getLast(value));
                		map.put("min", CollUtil.getFirst(value));
                    }
                    tmp.put(key, map);
                });
            });
        }

        //存放超标数据
        List<AlarmRuleConfigAndLevelVO> excessList = new ArrayList<>();
        //超出有效上下限
        List<AlarmRuleConfigAndLevelVO> errorList = new ArrayList<>();
        for (AlarmRuleConfigAndLevelVO alarmRuleAndAlarmRuleLevelVO : pgExcessAlarmList) {
            String alarmProgramCode = alarmRuleAndAlarmRuleLevelVO.getAlarmProgramCode();
            Map<String, Map<String,Object>> value = tmp.get(alarmProgramCode);
            if (value == null || value.isEmpty()) {
                continue;
            }

            Double max = ConvertUtils.getDouble(value.get("max").get("v"), 0);
            String maxTime = DateUtil.format(DateUtil.date(DateUtil.calendar(Long.parseLong(ConvertUtils.getString(value.get("max").get("ts"))+"000"))), "yyyy-MM-dd HH:mm:ss");
            Double min = ConvertUtils.getDouble(value.get("min").get("v"), 0);
            String minTime = DateUtil.format(DateUtil.date(DateUtil.calendar(Long.parseLong(ConvertUtils.getString(value.get("min").get("ts"))+"000"))), "yyyy-MM-dd HH:mm:ss");

            //先判断是否超出有效上下限
            String effectiveLowerLimit = alarmRuleAndAlarmRuleLevelVO.getEffectiveLowerLimit();
            String effectiveUpperLimit = alarmRuleAndAlarmRuleLevelVO.getEffectiveUpperLimit();
            if (StringUtils.isNotBlank(effectiveLowerLimit)) {
                double effectiveLower = Double.parseDouble(effectiveLowerLimit);
                if (min < effectiveLower) {
                    alarmRuleAndAlarmRuleLevelVO.setValue(min);
                    alarmRuleAndAlarmRuleLevelVO.setRecordTime(minTime);
                    errorList.add(alarmRuleAndAlarmRuleLevelVO);
                    continue;
                }
            }
            if (StringUtils.isNotBlank(effectiveUpperLimit)) {
                double effectiveUpper = Double.parseDouble(effectiveUpperLimit);
                if (max > effectiveUpper) {
                    alarmRuleAndAlarmRuleLevelVO.setValue(max);
                    alarmRuleAndAlarmRuleLevelVO.setRecordTime(maxTime);
                    errorList.add(alarmRuleAndAlarmRuleLevelVO);
                    continue;
                }
            }
            List<AlarmRuleLevelConfig> alarmRuleLevelConfigList = alarmRuleAndAlarmRuleLevelVO.getAlarmRuleLevelConfigList();
            for (AlarmRuleLevelConfig alarmRuleLevelConfig : alarmRuleLevelConfigList) {
                //判断是否超过数据上下限
                String lowerLimitData = alarmRuleLevelConfig.getAlarmParamLowerLimit();
                String upperLimitData = alarmRuleLevelConfig.getAlarmParamUpperLimit();
                if (StringUtils.isNotBlank(lowerLimitData)) {
                    if (min < Double.parseDouble(lowerLimitData)) {
                        alarmRuleAndAlarmRuleLevelVO.setValue(min);
                        alarmRuleAndAlarmRuleLevelVO.setRecordTime(minTime);
                        alarmRuleAndAlarmRuleLevelVO.setAlarmRuleLevelConfig(alarmRuleLevelConfig);
                        excessList.add(alarmRuleAndAlarmRuleLevelVO);
                        break;
                    }
                }
                if (StringUtils.isNotBlank(upperLimitData)) {
                    if (upperLimitData.contains("(")) {
                        String[] split = upperLimitData.split("\\(");
                        upperLimitData = split[0];
                    }
                    if (max > Double.parseDouble(upperLimitData)) {
                        alarmRuleAndAlarmRuleLevelVO.setValue(max);
                        alarmRuleAndAlarmRuleLevelVO.setRecordTime(maxTime);
                        alarmRuleAndAlarmRuleLevelVO.setAlarmRuleLevelConfig(alarmRuleLevelConfig);
                        excessList.add(alarmRuleAndAlarmRuleLevelVO);
                        break;
                    }
                }
            }
        }
        result.put("excessList", excessList);

        if(errorList!=null&&errorList.size()>0) {
        	//无效数据报警添加报警类别
        	QueryWrapper<AlarmRuleConfigPublicTab> alarmTypeQueryWrapper = new QueryWrapper<>();
        	alarmTypeQueryWrapper.eq("java_bean_tag", "invalidDataAlarmJob");
        	AlarmRuleConfigPublicTab alarmRuleConfigPublicTab = alarmRuleConfigPublicTabService.getOne(alarmTypeQueryWrapper);
        	String alarmTypeTreePath = alarmRuleConfigPublicTab.getTreePath();
        	//获取无效数据报警方案规则类别
            QueryWrapper<AlarmCustomRuleRepository> alarmRuleConfigQueryWrapper = new QueryWrapper<AlarmCustomRuleRepository>();
            alarmRuleConfigQueryWrapper.eq("bean_service_name", "invalidDataAlarmJob");
            AlarmCustomRuleRepository alarmCustomRuleRepository = alarmCustomRuleRepositoryService.getOne(alarmRuleConfigQueryWrapper);
            //报警方案规则类别
            String alarmCustomRuleTypeTreepath = alarmCustomRuleRepository.getAlarmRuleTypeTreepath();
            //报警方案规则id
            String alarmRepositoryId = alarmCustomRuleRepository.getId();

            errorList.forEach(v ->{
            	//向报警规则对象装入报警方案规则类别相关数据
            	String[] alarmCustomRuleTypeTreeArray = alarmCustomRuleTypeTreepath.split(",");
            	v.setAlarmCustomRuleTopType(alarmCustomRuleTypeTreeArray[0]);
            	//预留报警方案规则类别二级配置
            	//v.setAlarmCustomRuleSecondType(alarmCustomRuleTypeTreeArray[1]);
            	v.setAlarmCustomRuleType(alarmRepositoryId);
            	//预留报警方案id配置
            	//v.setAlarmCustomRuleId("");

            	//向报警报警规则对象装入报警类别相关数据
           	 	String[] treeArray = alarmTypeTreePath.split(",");
                v.setAlarmRuleTopType(treeArray[0]);
                v.setAlarmRuleSecondType(treeArray[1]);
            });

        }

        result.put("errorList", errorList);
        return result;
    }
    /**
     * 判断是否需要发送短信和通知
     *
     * @param resultList
     */
    public void sendMessage(Map<String, Object> resultList) {
        //超标报警
        List<AlarmRuleConfigAndLevelVO> excessList = (List<AlarmRuleConfigAndLevelVO>) resultList.get("excessList");
        if (excessList != null && excessList.size() > 0) {
            excessList.forEach(alarmRuleAndAlarmRuleLevelVO -> {
                dealCBData(alarmRuleAndAlarmRuleLevelVO);
            });
        }
        //将报警恢复成正常状态
        dealStatus(excessList);
        //质量超出上下限
        List<AlarmRuleConfigAndLevelVO> errorList = (List<AlarmRuleConfigAndLevelVO>) resultList.get("errorList");
        if (errorList != null && errorList.size() > 0) {
            errorList.forEach(alarmRuleAndAlarmRuleLevelVO -> {
                dealZLData(alarmRuleAndAlarmRuleLevelVO);
            });
        }
        //将报警恢复成正常状态
        dealSZLtatus(errorList);
    }
    /**
     * @return void
     * @Description 将质量报警恢复成正常状态
     * @Date 2021-09-10 13:54
     * @Param [errorList]
     **/
    private void dealSZLtatus(List<AlarmRuleConfigAndLevelVO> errorList) {
        //查询报警记录置为正常状态
        QueryWrapper<AlarmRecordHistory> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("alarm_rule_type", Lists.newArrayList("6"));
        queryWrapper.eq("alarm_param_type", "数据超过有效上下限报警配置");
        queryWrapper.in("handle_status", 0);
        List<AlarmRecordHistory> list = alarmRecordHistoryService.list(queryWrapper);
        if (list != null && list.size() > 0) {
            Set<String> tmp = Sets.newHashSet();
            errorList.forEach(alarmRuleConfigAndLevelVO -> {
                tmp.add(alarmRuleConfigAndLevelVO.getAlarmProgramCode());
            });
            List<AlarmRecordHistory> alarmRecordHistories = Lists.newArrayList();
            list.forEach(v -> {
                if (!tmp.contains(v.getAlarmParamCode())) {
                    v.setHandleStatus(1);
                    v.setHandleTime(DateUtils.getDate());
                    //v.setHandleUser("admin");
                    alarmRecordHistories.add(v);
                }
            });
            if (alarmRecordHistories.size() > 0) {
                alarmRecordHistoryService.updateBatchById(alarmRecordHistories);
            }
        }
    }
    /**
     * @return void
     * @Description 将报警恢复成正常状态
     * @Date 2021-09-03 9:44
     * @Param [excessList]
     **/
    private void dealStatus(List<AlarmRuleConfigAndLevelVO> excessList) {
        //查询报警记录置为正常状态
        QueryWrapper<AlarmRecordHistory> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("alarm_rule_type", Lists.newArrayList("1", "2", "3", "5", "8"));
        queryWrapper.in("handle_status", 0);
        List<AlarmRecordHistory> list = alarmRecordHistoryService.list(queryWrapper);
        if (list != null && list.size() > 0) {
            Set<String> tmp = Sets.newHashSet();
            excessList.forEach(alarmRuleConfigAndLevelVO -> {
                AlarmRuleLevelConfig alarmRuleLevelConfig = alarmRuleConfigAndLevelVO.getAlarmRuleLevelConfig();
                tmp.add(alarmRuleConfigAndLevelVO.getAlarmProgramCode() + alarmRuleLevelConfig.getId());
            });
            List<AlarmRecordHistory> alarmRecordHistories = Lists.newArrayList();
            list.forEach(v -> {
                if (!tmp.contains(v.getAlarmParamCode() + v.getAlarmRuleLevelId())) {
                    v.setHandleStatus(1);
                    v.setHandleTime(DateUtils.getDate());
                    v.setHandleUser("admin");
                    alarmRecordHistories.add(v);
                }
            });
            if (alarmRecordHistories.size() > 0) {
                alarmRecordHistoryService.updateBatchById(alarmRecordHistories);
            }
        }
    }
    /**
     * @return void
     * @Description 处理超标报警
     * @Date 2021-09-03 9:18
     * @Param [alarmRuleAndAlarmRuleLevelVO]
     **/
    private void dealCBData(AlarmRuleConfigAndLevelVO alarmRuleAndAlarmRuleLevelVO) {
        String date = DateUtils.getDate("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //查询质量报警配置
        String departId = alarmRuleAndAlarmRuleLevelVO.getDepartId();
        AlarmRuleLevelConfig alarmRuleLevelConfig = alarmRuleAndAlarmRuleLevelVO.getAlarmRuleLevelConfig();
        Double alarmValue = alarmRuleAndAlarmRuleLevelVO.getValue();
        Double minValue = Double.parseDouble(alarmRuleLevelConfig.getAlarmParamLowerLimit());
        Double maxValue = Double.parseDouble(alarmRuleLevelConfig.getAlarmParamUpperLimit());
        String alarmParamCode = alarmRuleAndAlarmRuleLevelVO.getAlarmProgramCode();
        String alarmParamName = alarmRuleAndAlarmRuleLevelVO.getAlarmParamName();
        String alarmRuleType = alarmRuleAndAlarmRuleLevelVO.getAlarmRuleType();
        String alarmRuleLevelName = alarmRuleLevelConfig.getAlarmRuleLevelName();
        String alarmRuleLevelConfigId = alarmRuleLevelConfig.getId();
        String content = "";
        String departName = departNameTemplete.replace("${departName}", alarmRuleAndAlarmRuleLevelVO.getDepartName());
        String unit = "";
        if (alarmRuleAndAlarmRuleLevelVO.getAlarmParamUnit() != null) {
            unit = alarmRuleAndAlarmRuleLevelVO.getAlarmParamUnit();
        }
        if (alarmValue > maxValue) {
            //最大值超标
            content = contentTemplete.replace("${alarmParamName}", alarmParamName)
                    .replace("${actualAvgValue}", alarmValue.doubleValue() + "")
                    .replace("${limit}", ">" + maxValue)
                    .replace("${alarmParamUnit}", unit);
            content = content +"大于上限";
        } else {
            //最小值超标
            content = contentTemplete.replace("${alarmParamName}", alarmParamName)
                    .replace("${actualAvgValue}", alarmValue.doubleValue() + "")
                    .replace("${limit}", "<" + minValue)
                    .replace("${alarmParamUnit}", unit);
            content = content +"小于下限";
        }
        //查询短信上一条报警是否处理,未处理就不新增报警记录
        //TODO 先从数据库中获取,后期优化放redis中
        QueryWrapper<AlarmRecordHistory> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("depart_id", departId);
        queryWrapper.eq("alarm_rule_type", alarmRuleType);
        queryWrapper.eq("alarm_rule_level_id", alarmRuleLevelConfigId);
        queryWrapper.orderByDesc("record_time").last("limit 1");
        AlarmRecordHistory alarmRecordHistoryOne = alarmRecordHistoryService.getOne(queryWrapper);
        //获取上次信息发送的时间,如果满足则发送
        //TODO 先从数据库中获取,后期优化方redis中
        QueryWrapper<AlarmMessageHistory> alarmMessageHistoryQueryWrapper = new QueryWrapper<>();
        alarmMessageHistoryQueryWrapper.eq("alarm_param_code", alarmParamCode);
        alarmMessageHistoryQueryWrapper.eq("alarm_send_type", "1");
        alarmMessageHistoryQueryWrapper.eq("alarm_rule_type", alarmRuleType);
        alarmMessageHistoryQueryWrapper.eq("alarm_rule_level_id", alarmRuleLevelConfigId);
        alarmMessageHistoryQueryWrapper.orderByDesc("alarm_send_time").last("limit 1");
        AlarmMessageHistory messageHistoryOne = alarmMessageHistoryService.getOne(alarmMessageHistoryQueryWrapper);
        Long nowDateLong = null;
        try {
            nowDateLong = simpleDateFormat1.parse(date).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //如果没有上条记录或者处理状态(0:未处理,1:已处理)为已处理
        if ((alarmRecordHistoryOne == null || alarmRecordHistoryOne.getHandleStatus() == 1)) {
            AlarmRecordHistory alarmRecordHistory = new AlarmRecordHistory();
            //手动创建UUID,用于报警自动送审
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            alarmRecordHistory.setId(uuid);
            alarmRecordHistory.setAlarmParamCode(alarmParamCode);
            alarmRecordHistory.setAlarmParamName(alarmParamName);
            alarmRecordHistory.setAlarmWorkName(alarmParamName+"报警");
            alarmRecordHistory.setAlarmRuleLevelName(alarmRuleLevelName);
            alarmRecordHistory.setAlarmRuleType(alarmRuleType);
            alarmRecordHistory.setAlarmRuleLevelId(alarmRuleLevelConfigId);
            try {
                //alarmRecordHistory.setRecordTime(simpleDateFormat1.parse(date));
                alarmRecordHistory.setRecordTime(simpleDateFormat1.parse(alarmRuleAndAlarmRuleLevelVO.getRecordTime()));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            alarmRecordHistory.setAlarmParamUpperLimit(maxValue.toString());
            alarmRecordHistory.setAlarmParamLowerLimit(minValue.toString());
            alarmRecordHistory.setAlarmParamUnit(alarmRuleAndAlarmRuleLevelVO.getAlarmParamUnit());
            alarmRecordHistory.setDepartId(departId);
            alarmRecordHistory.setActualAvgValue(alarmValue.toString());
            alarmRecordHistory.setHandleStatus(0);
            alarmRecordHistory.setDelFlag(1);

            //添加报警类别数据
            alarmRecordHistory.setHandleMethon(alarmRuleAndAlarmRuleLevelVO.getAlarmRecommend());
            alarmRecordHistory.setAlarmRuleTopType(alarmRuleAndAlarmRuleLevelVO.getAlarmRuleTopType());
            alarmRecordHistory.setAlarmRuleSecondType(alarmRuleAndAlarmRuleLevelVO.getAlarmRuleSecondType());
            alarmRecordHistory.setAlarmRuleTypeTreepath(alarmRuleAndAlarmRuleLevelVO.getAlarmRuleTypeTreepath());

            //添加报警方案规则类别数据
            alarmRecordHistory.setAlarmCustomRuleTopType(alarmRuleAndAlarmRuleLevelVO.getAlarmCustomRuleTopType());
            alarmRecordHistory.setAlarmCustomRuleSecondType(alarmRuleAndAlarmRuleLevelVO.getAlarmCustomRuleSecondType());
            alarmRecordHistory.setAlarmCustomRuleType(alarmRuleAndAlarmRuleLevelVO.getAlarmCustomRuleType());
            alarmRecordHistory.setAlarmCustomRuleTypeTreepath(alarmRuleAndAlarmRuleLevelVO.getAlarmCustomRuleTypeTreepath());

            //构造报警指标数据json
            List<Map<String,Object>> indexDataList = new ArrayList<Map<String,Object>>();
            Map<String,Object> indexJsonMap = new HashMap<String,Object>();
            indexJsonMap.put("indexCode", alarmParamCode);
            indexJsonMap.put("indexName", alarmParamName);
            indexJsonMap.put("indexValue", alarmValue.toString());
            indexDataList.add(indexJsonMap);
            alarmRecordHistory.setAlarmCustomIndexJsonData(JSONUtil.toJsonStr(indexDataList));

            //${start}采集数据${conent}已超标,请注意!
            alarmRecordHistory.setAlarmContent("采集数据" + content + suffix);
            alarmRecordHistory.setCreateBy("system");//标记为系统创建
            //alarmRecordHistory.setHandleUser(alarmRuleLevelConfig.getAlarmWorkRecipient());
            //流程添加定义ID
            String processDefinitionId = flowBusinessService.getProcessDefinitionLastVersionId("productAlarmProcess");
            alarmRecordHistory.setProcessDefinitionId(processDefinitionId);
            alarmRecordHistoryService.save(alarmRecordHistory);


            //判断是否需要发送系统通知 (内容跟报警记录信息相同)
            if ("1".equals(alarmRuleLevelConfig.getIsSendNotice())) {
                if (StringUtils.isNotBlank(alarmRuleLevelConfig.getAlarmNoticeRecipient())) {
                    //义乌报警存在特定参数逻辑,不适用产品原有消息推送流程
                    SysMessagePushService sysMessagePushService = (SysMessagePushService) SpringContextUtils.getBean("sysMessagePushService");
                    sysMessagePushService.pushAlarmRecordMsgNoProcess(alarmRecordHistory);

                    //SystemNoticeVO systemNoticeVO = new SystemNoticeVO(alarmRuleLevelConfig.getAlarmNoticeRecipient(),alarmRuleLevelName, "在" + date + "时" + departName + "采集数据" + content + suffix, departId, alarmRuleType);
                    //systemNoticeUtils.dealNoticeMessage(systemNoticeVO);
                }
            }
            //判断是否需要自动发起工作流
            if("1".equals(alarmRuleLevelConfig.getIsFlowWork())) {
            	if(StringUtils.isNotBlank(alarmRuleLevelConfig.getAlarmWorkRecipient())) {
            		//自动发起工作流 (改成到Mybatis拦截器里面去发起工单了)
            		startProcessFlow("alarm_record_history","productAlarmProcess",Arrays.asList(alarmRuleLevelConfig.getAlarmWorkRecipient().split(",")),uuid,alarmRecordHistory);
            	}
            }
        }
        //判断是否需要发送短信,1表示发送
        if (alarmRuleLevelConfig.getIsSendSms().equals("1")) {
            //判读是否在发送时间内
            Date allowStartDate = null;
            Date allowEndDate = null;
            Date nowDate = null;
            try {
            	//JSONObject jsonObject = (JSONObject) JSONObject.toJSON(alarmRuleLevelConfig);
            	//System.err.println("****************************************************");
                //System.out.println(jsonObject);
                //System.err.println("****************************************************");
                allowEndDate = simpleDateFormat.parse(alarmRuleLevelConfig.getSmsAllowSendTime().split("-")[1]);
                allowStartDate = simpleDateFormat.parse(alarmRuleLevelConfig.getSmsAllowSendTime().split("-")[0]);
                nowDate = simpleDateFormat.parse(date.substring(11, 16));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            //如果在发送时间内,则发送
            if (isEffectiveDate(nowDate, allowStartDate, allowEndDate)) {
                Date lastTime1 = null;
                //如果数据库没有上次时间,则设置一个默认时间
                if (messageHistoryOne != null) {
                    lastTime1 = messageHistoryOne.getAlarmSendTime();
                } else {
                    try {
                        lastTime1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2020-01-01 00:00:00");
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
                //判断是否满足报警频率,将两个时间转为毫秒
                Long lastTimeLong1 = lastTime1.getTime();
                if (nowDateLong - lastTimeLong1 > Double.parseDouble(alarmRuleLevelConfig.getSmsSendFrequency()) * 60 * 60 * 1000) {
                    List<String> userList = new ArrayList<>();
                    String alarmSmsRecipient = alarmRuleLevelConfig.getAlarmSmsRecipient();
                    //获取需要发送短信的手机号
                    if (StringUtils.isNotBlank(alarmSmsRecipient)) {
                        String[] userArr = alarmSmsRecipient.split(",");
                        for (int i = 0; i < userArr.length; i++) {
                            userList.add(userArr[i]);
                        }
                        QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
                        sysUserQueryWrapper.in("id", userList);
                        List<SysUser> sysUserList = sysUserService.list(sysUserQueryWrapper);
                        //获取报警接收人的手机号
                        StringBuilder phoneStringBuilder = new StringBuilder();
                        for (int i = 0; i < sysUserList.size(); i++) {
                            phoneStringBuilder.append(",");
                            String phone1 = sysUserList.get(i).getPhone();
                            if (StringUtils.isNotBlank(phone1)) {
                                phoneStringBuilder.append(phone1);
                                //发送短信
                                HttpSenderMsg.sendMsg(prefix + date + "时" + departName + "采集数据" + content + suffix, phone1);
                                log.info("短信发送成功手机号:" + phone1 + ",内容:" + content);
                            }
                        }
                        String phone = phoneStringBuilder.toString().replaceFirst(",", "");
                        if (StringUtils.isNotBlank(phone)) {
                            //将发送的短信保存到数据库
                            AlarmMessageHistory alarmMessageHistory = new AlarmMessageHistory();
                            alarmMessageHistory.setAlarmSendUser(alarmSmsRecipient);
                            alarmMessageHistory.setAlarmSendPhone(phone);
                            try {
                                alarmMessageHistory.setAlarmSendTime(simpleDateFormat1.parse(date));
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                            alarmMessageHistory.setAlarmSendContent(prefix + date + "时" + departName + "采集数据" + content + suffix);
                            alarmMessageHistory.setAlarmSendType("1");
                            alarmMessageHistory.setAlarmParamCode(alarmParamCode);
                            alarmMessageHistory.setAlarmParamName(alarmParamName);
                            alarmMessageHistory.setAlarmRuleLevelId(alarmRuleLevelConfigId);
                            alarmMessageHistory.setAlarmRuleType(alarmRuleType);
                            alarmMessageHistory.setAlarmParamUpperLimit(maxValue.toString());
                            alarmMessageHistory.setAlarmParamLowerLimit(minValue.toString());
                            alarmMessageHistory.setAlarmParamUnit(alarmRuleAndAlarmRuleLevelVO.getAlarmParamUnit());
                            alarmMessageHistory.setDepartId(departId);
                            alarmMessageHistory.setActualAvgValue(alarmValue.toString());
                            alarmMessageHistoryService.save(alarmMessageHistory);
                        }
                    }
                }
            }
        }
    }
    /**
     * @param businessTable
     * @param flowKey
     * @param candidateUserList
     * @param bussinessId
     * @param alarmRecordHistory
     */
    public void startProcessFlow(String businessTable,String flowKey,List<String> candidateUserList,String bussinessId,AlarmRecordHistory alarmRecordHistory) {
        // 启动流程
        Kv variables = Kv.create().set(ProcessConstant.TASK_VARIABLE_CREATE_USER, "");
        String processDefinitionId = flowBusinessService.getProcessDefinitionLastVersionId(flowKey);
        alarmRecordHistory.setProcessDefinitionId(processDefinitionId);
        BladeFlow flow = flowService.startProcessInstanceById(processDefinitionId, FlowUtil.getBusinessKey(businessTable, String.valueOf(bussinessId)), variables);
        if (Func.isNotEmpty(flow)) {
            log.debug("流程已启动,流程ID: " + flow.getProcessInstanceId());
            //动态添加下一节点候选用户
            if(candidateUserList!=null&&candidateUserList.size()>0) {
            	//获取当前活动任务
                TaskEntity taskEntity=(TaskEntity)taskService.createTaskQuery().processInstanceId(flow.getProcessInstanceId()).singleResult();
                String taskId = taskEntity.getId();
                ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
                //获取当前结点审批人  考虑到有多个审批人的情况  需要先查询出所有的审批人   所以涉及到identityLink
                List<String> userIds = processEngine.getTaskService().getIdentityLinksForTask(taskId).stream().map(IdentityLink::getUserId).distinct().collect(Collectors.toList());
                //删除identityLink中的用户关系
                for (String userId : userIds) {
                    taskService.deleteUserIdentityLink(taskId, userId, IdentityLinkType.CANDIDATE);
                }
                //清空task中的assignee
                taskService.unclaim(taskId);
                //当前节点审核人列表 清空申请人
                userIds = new ArrayList<>();
                //当前节点审核人列表 追加流转人
                userIds.addAll(candidateUserList);
                //给当前任务节点分配审核人
                for (String userId : userIds) {
                	taskService.addCandidateUser(taskId, "taskUser_"+userId);
                }
                //工单消息推送

                if (userIds != null && userIds.size() > 0) {
                    List<String> userCidList = new ArrayList<>();
                    userCidList = sysUserService.getCidByUserIds(String.join(",", userIds));

                    //获取用户列表后做消息推送
                    MessageEntity messageEntity = new MessageEntity();
                    messageEntity.setMessageTitle("流程审批消息");
                    messageEntity.setMessageBody("您有一条" + alarmRecordHistory.getAlarmWorkName() + "待审批,请及时处理");
                    messageEntity.setReceiveUser(userIds);
                    messageEntity.setReceiveUserCid(userCidList);
                    messageEntity.setSendUser("系统");
                    messageEntity.setForwardTag("todo");
                    IPushService appPushService = PushMessageFactory.getPushService("MOB");
                    IPushService webPushService = PushMessageFactory.getPushService("WEB");
                    appPushService.pushMessage(messageEntity);
                    webPushService.pushMessage(messageEntity);
                }

            }
            //返回流程id写入leave
            alarmRecordHistory.setProcessInstanceId(flow.getProcessInstanceId());
            alarmRecordHistoryService.saveOrUpdate(alarmRecordHistory);
            log.debug("流程发起成功");
        } else {
        	log.debug("流程发起失败");
        }
    }


    /**
     * 判断当前时间是否在[startTime, endTime]区间,注意时间格式要一致
     *
     * @param nowTime   当前时间
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return
     * @author xiechao
     */
    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }
        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);
        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);
        Calendar end = Calendar.getInstance();
        end.setTime(endTime);
        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * @return void
     * @Description 处理质量报警
     * @Date 2021-09-01 17:25
     * @Param [alarmRuleAndAlarmRuleLevelVO]
     **/
    private void dealZLData(AlarmRuleConfigAndLevelVO alarmRuleAndAlarmRuleLevelVO) {
    	//获取无效数据报警类别
    	QueryWrapper<AlarmRuleConfigPublicTab> alarmRuleConfigPublicTabQueryWrapper = new QueryWrapper<AlarmRuleConfigPublicTab>();
    	alarmRuleConfigPublicTabQueryWrapper.eq("java_bean_tag", "invalidDataAlarmJob");
    	AlarmRuleConfigPublicTab alarmRuleConfigPublicTab = alarmRuleConfigPublicTabService.getOne(alarmRuleConfigPublicTabQueryWrapper);
        //获取设备信号报警方案规则类别
        QueryWrapper<AlarmCustomRuleRepository> alarmRuleConfigQueryWrapper = new QueryWrapper<AlarmCustomRuleRepository>();
        alarmRuleConfigQueryWrapper.eq("bean_service_name", "invalidDataAlarmJob");
        AlarmCustomRuleRepository alarmCustomRuleRepository = alarmCustomRuleRepositoryService.getOne(alarmRuleConfigQueryWrapper);
        //报警方案规则类别
        String alarmCustomRuleTypeTreepath = alarmCustomRuleRepository.getAlarmRuleTypeTreepath();
        //报警方案规则id
        String alarmRepositoryId = alarmCustomRuleRepository.getId();
    	//获取无效数据报警方案规则类别

        DecimalFormat df = new DecimalFormat("#.##");
        String date = DateUtils.getDate("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //查询质量报警配置
        String departId = alarmRuleAndAlarmRuleLevelVO.getDepartId();
        QueryWrapper<AlarmRuleLevelConfigTemplate> alarmRuleLevelConfigTemplateQueryWrapper = new QueryWrapper<>();
        alarmRuleLevelConfigTemplateQueryWrapper.eq("depart_id", departId);
        alarmRuleLevelConfigTemplateQueryWrapper.eq("alarm_template_type", "C001C001");

        AlarmRuleLevelConfigTemplate alarmRuleLevelConfigTemplate = alarmRuleLevelConfigTemplateService.getOne(alarmRuleLevelConfigTemplateQueryWrapper);
        Double alarmValue = alarmRuleAndAlarmRuleLevelVO.getValue();
        Double minValue = Double.parseDouble(alarmRuleAndAlarmRuleLevelVO.getEffectiveLowerLimit());
        Double maxValue = Double.parseDouble(alarmRuleAndAlarmRuleLevelVO.getEffectiveUpperLimit());
        String alarmParamCode = alarmRuleAndAlarmRuleLevelVO.getAlarmProgramCode();
        String alarmParamName = alarmRuleAndAlarmRuleLevelVO.getAlarmParamName();
        String content = "";
        String departName = departNameTemplete.replace("${departName}", alarmRuleAndAlarmRuleLevelVO.getDepartName());
        String unit = "";
        if (alarmRuleAndAlarmRuleLevelVO.getAlarmParamUnit() != null) {
            unit = alarmRuleAndAlarmRuleLevelVO.getAlarmParamUnit();
        }
        if (alarmValue > maxValue) {
            //最大值超标
            content = contentTemplete.replace("${alarmParamName}", alarmParamName)
                    .replace("${actualAvgValue}", alarmValue.doubleValue() + "")
                    .replace("${limit}", ">" + maxValue)
                    .replace("${alarmParamUnit}", unit);
            content = content +"大于上限";
        } else {
            //最小值超标
            content = contentTemplete.replace("${alarmParamName}", alarmParamName)
                    .replace("${actualAvgValue}", alarmValue.doubleValue() + "")
                    .replace("${limit}", "<" + minValue)
                    .replace("${alarmParamUnit}", unit);
            content = content +"小于下限";
        }
        //查询短信上一条报警是否处理,未处理就不新增报警记录
        //TODO 先从数据库中获取,后期优化放redis中
        QueryWrapper<AlarmRecordHistory> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("depart_id", departId);
        queryWrapper.eq("alarm_param_code", alarmParamCode);
        queryWrapper.eq("alarm_param_type", alarmRuleLevelConfigTemplate.getAlarmTemplateName());
        queryWrapper.eq("alarm_rule_type", alarmRuleLevelConfigTemplate.getAlarmTemplateType());
        queryWrapper.orderByDesc("record_time").last("limit 1");
        AlarmRecordHistory alarmRecordHistoryOne = alarmRecordHistoryService.getOne(queryWrapper);
        //如果没有上条记录或者处理状态(0:未处理,1:已处理)为已处理
        if ((alarmRecordHistoryOne == null || alarmRecordHistoryOne.getHandleStatus() == 1)) {
            AlarmRecordHistory alarmRecordHistory = new AlarmRecordHistory();
            //手动创建UUID,用于报警自动送审
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            alarmRecordHistory.setId(uuid);
            alarmRecordHistory.setAlarmParamCode(alarmParamCode);
            alarmRecordHistory.setAlarmParamName(alarmParamName);
            alarmRecordHistory.setAlarmRuleLevelName(alarmRuleLevelConfigTemplate.getAlarmTemplateLevelName());
            alarmRecordHistory.setAlarmRuleType(alarmRuleLevelConfigTemplate.getAlarmTemplateType());
            alarmRecordHistory.setAlarmParamType(alarmRuleLevelConfigTemplate.getAlarmTemplateName());
            try {
                //alarmRecordHistory.setRecordTime(simpleDateFormat1.parse(date));
                alarmRecordHistory.setRecordTime(simpleDateFormat1.parse(alarmRuleAndAlarmRuleLevelVO.getRecordTime()));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            alarmRecordHistory.setAlarmParamUpperLimit(maxValue.toString());
            alarmRecordHistory.setAlarmParamLowerLimit(minValue.toString());
            alarmRecordHistory.setAlarmParamUnit(alarmRuleAndAlarmRuleLevelVO.getAlarmParamUnit());
            alarmRecordHistory.setDepartId(departId);
            alarmRecordHistory.setActualAvgValue(alarmValue.toString());
            alarmRecordHistory.setHandleStatus(0);
            alarmRecordHistory.setDelFlag(1);

            //添加报警类别数据
            //向报警规则对象装入报警方案规则类别相关数据
        	String[] alarmCustomRuleTypeTreeArray = alarmCustomRuleTypeTreepath.split(",");
        	//报警类别树
        	String alarmTypeTreePath = alarmRuleConfigPublicTab.getTreePath();
        	String[] treeArray = alarmTypeTreePath.split(",");

            alarmRecordHistory.setHandleMethon(alarmRuleAndAlarmRuleLevelVO.getAlarmRecommend());
            alarmRecordHistory.setAlarmRuleTopType(treeArray[0]);
            alarmRecordHistory.setAlarmRuleSecondType(treeArray[1]);
            alarmRecordHistory.setAlarmRuleTypeTreepath(alarmTypeTreePath);

            //添加报警方案规则类别数据
            alarmRecordHistory.setAlarmCustomRuleTopType(alarmCustomRuleTypeTreeArray[0]);
            alarmRecordHistory.setAlarmCustomRuleSecondType("");
            alarmRecordHistory.setAlarmCustomRuleType(alarmRepositoryId);
            alarmRecordHistory.setAlarmCustomRuleTypeTreepath(alarmCustomRuleTypeTreepath+","+alarmRepositoryId);

            //构造报警指标数据json
            List<Map<String,Object>> indexDataList = new ArrayList<Map<String,Object>>();
            Map<String,Object> indexJsonMap = new HashMap<String,Object>();
            indexJsonMap.put("indexCode", alarmParamCode);
            indexJsonMap.put("indexName", alarmParamName);
            indexJsonMap.put("indexValue", alarmValue.toString());
            indexDataList.add(indexJsonMap);
            alarmRecordHistory.setAlarmCustomIndexJsonData(JSONUtil.toJsonStr(indexDataList));

            //${start}采集数据${conent}已超标,请注意!
            alarmRecordHistory.setAlarmContent("采集数据" + content + suffix);
            alarmRecordHistory.setCreateBy("system");
            alarmRecordHistoryService.save(alarmRecordHistory);
            //判断是否需要发送系统通知 (内容跟报警记录信息相同)
            if ("1".equals(alarmRuleLevelConfigTemplate.getIsSendNotice())) {
                if (StringUtils.isNotBlank(alarmRuleLevelConfigTemplate.getAlarmNoticeRecipient())) {
                    SystemNoticeVO systemNoticeVO = new SystemNoticeVO(alarmRuleLevelConfigTemplate.getAlarmNoticeRecipient(),
                            alarmRuleLevelConfigTemplate.getAlarmTemplateLevelName(), "在" + date + "时" + departName + "采集数据" + content + suffix, departId, "6");
                    systemNoticeUtils.dealNoticeMessage(systemNoticeVO);
                }
            }
        }
    }
}