package com.yeejoin.amos.patrol.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.yeejoin.amos.boot.biz.common.bo.DepartmentBo;
import com.yeejoin.amos.boot.biz.common.bo.RoleBo;
import com.yeejoin.amos.boot.biz.common.service.impl.WorkflowExcuteServiceImpl;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.DepartmentModel;
import com.yeejoin.amos.patrol.business.constants.XJConstant;
import com.yeejoin.amos.patrol.business.dao.mapper.CheckInputMapper;
import com.yeejoin.amos.patrol.business.dao.mapper.LatentDangerFlowRecordMapper;
import com.yeejoin.amos.patrol.business.dao.mapper.LatentDangerMapper;
import com.yeejoin.amos.patrol.business.dao.mapper.LatentDangerPatrolMapper;
import com.yeejoin.amos.patrol.business.dao.mapper.RiskFactorCmMapper;
import com.yeejoin.amos.patrol.business.dao.mapper.RiskFactorMapper;
import com.yeejoin.amos.patrol.business.dao.mapper.RiskSourceMapper;
import com.yeejoin.amos.patrol.business.dao.repository.ICheckDao;
import com.yeejoin.amos.patrol.business.dao.repository.ICheckShotDao;
import com.yeejoin.amos.patrol.business.dao.repository.IInputItemDao;
import com.yeejoin.amos.patrol.business.dao.repository.IPointClassifyDao;
import com.yeejoin.amos.patrol.business.dto.DangerExecuteSubmitDto;
import com.yeejoin.amos.patrol.business.dto.InputCheckDto;
import com.yeejoin.amos.patrol.business.entity.mybatis.DangerResultBo;
import com.yeejoin.amos.patrol.business.entity.mybatis.DictBo;
import com.yeejoin.amos.patrol.business.entity.mybatis.RiskFactorBo;
import com.yeejoin.amos.patrol.business.entity.mybatis.RiskSourceBo;
import com.yeejoin.amos.patrol.business.entity.mybatis.extend.LatentDangerBo;
import com.yeejoin.amos.patrol.business.entity.mybatis.extend.LatentDangerFlowRecordBo;
import com.yeejoin.amos.patrol.business.entity.mybatis.extend.LatentDangerNoticeBo;
import com.yeejoin.amos.patrol.business.entity.mybatis.extend.LatentDangerPatrolBo;
import com.yeejoin.amos.patrol.business.feign.Business;
import com.yeejoin.amos.patrol.business.feign.EquipFeign;
import com.yeejoin.amos.patrol.business.feign.JcsFeignClient;
import com.yeejoin.amos.patrol.business.param.LatentDangerExcuteParam;
import com.yeejoin.amos.patrol.business.param.LatentDangerListParam;
import com.yeejoin.amos.patrol.business.param.LatentDangerNormalParam;
import com.yeejoin.amos.patrol.business.param.LatentDangerPatrolItemParam;
import com.yeejoin.amos.patrol.business.param.LatentDangerPatrolParam;
import com.yeejoin.amos.patrol.business.param.PageParam;
import com.yeejoin.amos.patrol.business.service.intfc.ILatentDangerService;
import com.yeejoin.amos.patrol.business.service.intfc.IRiskJudgmentTaskService;
import com.yeejoin.amos.patrol.business.util.CommonResponse;
import com.yeejoin.amos.patrol.business.util.CommonResponseUtil;
import com.yeejoin.amos.patrol.business.util.DateUtil;
import com.yeejoin.amos.patrol.business.util.RandomUtil;
import com.yeejoin.amos.patrol.business.vo.DangerTimeAxisVo;
import com.yeejoin.amos.patrol.business.vo.LatentDangerDetailRiskVo;
import com.yeejoin.amos.patrol.business.vo.LatentDangerDetailVo;
import com.yeejoin.amos.patrol.business.vo.LatentDangerListVo;
import com.yeejoin.amos.patrol.common.enums.CheckModeEnum;
import com.yeejoin.amos.patrol.common.enums.DangerHandleStateEnum;
import com.yeejoin.amos.patrol.common.enums.DictTypeEnum;
import com.yeejoin.amos.patrol.common.enums.ExecuteStateEnum;
import com.yeejoin.amos.patrol.common.enums.InstanceKeyEnum;
import com.yeejoin.amos.patrol.common.enums.LatentDangerExcuteTypeEnum;
import com.yeejoin.amos.patrol.common.enums.LatentDangerLevelEnum;
import com.yeejoin.amos.patrol.common.enums.LatentDangerOvertimeStateEnum;
import com.yeejoin.amos.patrol.common.enums.LatentDangerReformTypeEnum;
import com.yeejoin.amos.patrol.common.enums.LatentDangerStateEnum;
import com.yeejoin.amos.patrol.common.enums.LatentDangerTypeEnum;
import com.yeejoin.amos.patrol.common.enums.RiskFactorsCmStatusEnum;
import com.yeejoin.amos.patrol.common.remote.RemoteSpcService;
import com.yeejoin.amos.patrol.common.remote.RemoteWebSocketServer;
import com.yeejoin.amos.patrol.common.remote.RemoteWorkFlowService;
import com.yeejoin.amos.patrol.core.async.AsyncTask;
import com.yeejoin.amos.patrol.core.common.request.LatentDangerResultPushSpcRequest;
import com.yeejoin.amos.patrol.core.common.response.DangerListResponse;
import com.yeejoin.amos.patrol.core.util.StringUtil;
import com.yeejoin.amos.patrol.dao.entity.Check;
import com.yeejoin.amos.patrol.dao.entity.CheckShot;
import com.yeejoin.amos.patrol.dao.entity.InputItem;
import com.yeejoin.amos.patrol.dao.entity.PointClassify;
import com.yeejoin.amos.patrol.exception.YeeException;
import com.yeejoin.amos.patrol.feign.RemoteSecurityService;
import com.yeejoin.amos.patrol.mqtt.WebMqttComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static org.typroject.tyboot.core.foundation.context.RequestContext.getProduct;

@Service("latentDangerService")
public class LatentDangerServiceImpl implements ILatentDangerService {

    private final Logger logger = LoggerFactory.getLogger(LatentDangerServiceImpl.class);

    @Autowired
    private RemoteWorkFlowService remoteWorkFlowService;

    @Autowired
    private RemoteSecurityService remoteSecurityService;

    @Autowired
    private LatentDangerMapper latentDangerMapper;

    @Autowired
    private RiskFactorMapper riskFactorMapper;

    @Autowired
    private RiskFactorCmMapper riskFactorCmMapper;

    @Autowired
    private RiskSourceMapper riskSourceMapper;

    @Autowired
    private LatentDangerFlowRecordMapper latentDangerFlowRecordMapper;

    @Autowired
    private LatentDangerPatrolMapper latentDangerPatrolMapper;

    @Autowired
    private IPointClassifyDao iPointClassifyDao;

    @Autowired
    private CheckInputMapper checkInputMapper;

    @Autowired
    private IInputItemDao iInputItemDao;

    @Autowired
    private RemoteSpcService remoteSpcService;

    @Autowired
    private ICheckShotDao iCheckShotDao;

    @Autowired
    private ICheckDao iCheckDao;

    @Autowired
    private AsyncTask asyncTask;

    @Autowired
    private RemoteWebSocketServer remoteWebSocketServer;

    @Autowired
    private IRiskJudgmentTaskService iRiskJudgmentTaskService;

    @Autowired
    private Business business;

    @Autowired
    EquipFeign equipFeign;

    @Autowired
    JcsFeignClient jcsFeignClient;

    @Autowired
    private WorkflowExcuteServiceImpl workflowExecuteService;

    private static final String permissionType = "SUBMENU";

    private static final String acctivePermissionType = "activitiItem";

    private static final String path = "AppNormalLatentDangerReview";

    @Value("${server.port}")
    private String port;

//    @Value("${LatentDanger.flow.photoUrls}")
//    private String photoUrlPre;
//    @Value("${file.url}")
//    private String fileUrl;
    
    @Value("${file.url}")
    private String fileServerAddress;

    @Value("${params.work.flow.processDefinitionKey}")
    private String processDefinitionKey;

    @Value("${params.work.flow.normalProcessDefinitionKey}")
    private String normalProcessDefinitionKey;

    @Value("${amosRefresh.danger.topic}")
    private String dangerTopic;
    @Autowired
    private WebMqttComponent webMqttComponent;

    private String bizType = "patrol";

    @Value("${emergency.command.section.id}")
    private String emergencyCommandSectionId;

    @Transactional
    @Override
    public CommonResponse saveNormal(LatentDangerNormalParam latentDangerParam, String userId, String userRealName, String departmentId, String departmentName, String companyId, String orgCode, RoleBo role) {
        String businessKey = RandomUtil.buildOrderNo();
        LatentDangerBo latentDangerBo = saveLatentDanger("", "", latentDangerParam.getRemark(),
                                                         userId, departmentId, businessKey, orgCode, latentDangerParam.getDangerName(), latentDangerParam.getDangerLevel()
                , latentDangerParam.getDangerPosition(), LatentDangerTypeEnum.随手拍,
                                                         latentDangerParam.getPhotoUrls(), 0L, latentDangerParam.getStructureId(), latentDangerParam.getStructureName(), InstanceKeyEnum.NORMAL.getCode());
        // 更新p_check_input表state字段
        updateCheckInputDangerState(latentDangerBo.getBizId(), DangerHandleStateEnum.HANDLE.getCode());
        Long dangerId = latentDangerBo.getId();
        Date startDate = new Date();
        JSONObject jsonObject = remoteWorkFlowService.startNew(dangerId, businessKey, processDefinitionKey);
//        if(!jsonObject.getString("msg").equals("操作成功")){
//            return CommonResponseUtil.failure(jsonObject.getString("msg"));
//        }
        Date endDate = new Date();
        logger.info("-------------------------提交隐患时间" +(endDate.getTime()-startDate.getTime()));
        if (jsonObject == null) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return CommonResponseUtil.failure("启动流程失败");
        }
        JSONObject instance = jsonObject.getJSONObject("data");
        if(instance==null){
            return CommonResponseUtil.failure("无提交隐患权限");
        }
        //提交隐患
//        jsonObject = remoteWorkFlowService.excute(instance.getString("id"), null);
//        JSONObject task = jsonObject.getJSONObject("data");
        latentDangerBo.setInstanceId(instance.getString("id"));
        JSONObject flowJson = new JSONObject();
        flowJson.put("photoUrls", latentDangerParam.getPhotoUrls());
        LatentDangerFlowRecordBo record = saveFlowRecord(instance.getString("id"), "提交隐患", userId, departmentId, flowJson, dangerId, role, LatentDangerExcuteTypeEnum.填写隐患完成.getName(),latentDangerParam.getRemark());
        latentDangerBo.setCurrentFlowRecordId(record.getId());
        latentDangerMapper.update(latentDangerBo);
        sendMessage(latentDangerBo, LatentDangerExcuteTypeEnum.填写隐患完成, null,
                    "隐患排查与治理", this.getNextExecuteUsers(latentDangerBo.getInstanceId()), userRealName, departmentName);
        try {
            webMqttComponent.publish(dangerTopic, "");
        }catch (Exception e){
            logger.error("隐患提交数字换流站页面推送失败-----------"+e.getMessage());
        }
        return CommonResponseUtil.success();
    }

    @Transactional
    @Override
    public CommonResponse savePatrol(LatentDangerPatrolParam latentDangerPatrolParam, String userId, String userRealName, String departmentId, String departmentName, String companyId, String orgCode, RoleBo role) {
        List<LatentDangerPatrolItemParam> itemList = latentDangerPatrolParam.getItemList();
        Long checkId = latentDangerPatrolParam.getCheckId();
        Check check = iCheckDao.getById(checkId);
        if (CollectionUtils.isEmpty(itemList)) {
            return CommonResponseUtil.failure("请求参数有误");
        }
//        Set<String> inputUserIdsStr = getUserIdsStrByTypeAndDefKey("B_1");
//        Set<String> reviewUserIdsStr = getUserIdsStrByTypeAndDefKey("B_2");
        //获取装备全路径
        LinkedHashMap<String,Object> positionAll  = equipFeign.getBuildingAbsolutePosition();
        LinkedHashMap<String,Object> position =  new LinkedHashMap<>();
        if("200".equals(positionAll.get("status").toString())){
             position = (LinkedHashMap<String, Object>) positionAll.get("result");
        }

        for (LatentDangerPatrolItemParam param : itemList) {
            InputCheckDto inputCheckDto = checkInputMapper.getByCheckIdAndItemIdAndRoutePointItemId(checkId,
                                                                                                    param.getItemId(), param.getRoutePointItemId(), null);
            if (CheckModeEnum.WEB_OUT.getCode().equals(check.getCheckMode())) {
                // 如果是外来检查，这里itemList里面无法区分InputCheckDto...
                // 在LatentDangerPatrolItemParam中增加checkInputId字段来区分
                inputCheckDto = checkInputMapper.getByCheckIdAndItemIdAndRoutePointItemId(null, null,
                                                                                          null, param.getCheckInputId());
            }
            if (inputCheckDto == null) {
                return CommonResponseUtil.failure("检查项不存在");
            }
            InputItem inputItem = iInputItemDao.getOne(inputCheckDto.getItemId());
            if (inputItem == null && !CheckModeEnum.WEB_OUT.getCode().equals(check.getCheckMode())) {
                return CommonResponseUtil.failure("检查项不存在");
            }
            String businessKey = RandomUtil.buildOrderNo();
            LatentDangerLevelEnum levelEnum = LatentDangerLevelEnum.getByCode(param.getDangerLevel());
            if (levelEnum == null) {
                return CommonResponseUtil.failure("请求参数有误");
            }
            String remark = param.getRemark();
            String photoUrls = "";
            List<CheckShot> checkShots = iCheckShotDao.findAllByCheckIdAndCheckInputId(inputCheckDto.getCheckId(),
                                                                                       inputCheckDto.getCheckInputId());
            if (!CollectionUtils.isEmpty(checkShots)) {
                List<String> photos = checkShots.stream().map(e -> {
                    if (e != null) {
                        return fileServerAddress + e.getPhotoData().replaceAll("\\\\", "/");
                    } else {
                        return "";
                    }
                }).collect(Collectors.toList());
                photoUrls = Joiner.on(",").join(photos);
            }
            LatentDangerTypeEnum dangerTypeEnum = null;
            String dangerName = "";
            if (check.getPlanId() > 0) {
                dangerTypeEnum = LatentDangerTypeEnum.计划检查;
            } else if (CheckModeEnum.WEB_OUT.getCode().equals(check.getCheckMode())) {
                dangerTypeEnum = LatentDangerTypeEnum.无码检查;
            } else {
                dangerTypeEnum = LatentDangerTypeEnum.无计划检查;
            }
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(param.getName())){
                dangerName = param.getName();
            }else {
                dangerName = inputItem.getName();
            }
            Long riskSourceId = null;
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(inputCheckDto.getRiskSourceId())){
                riskSourceId =  Long.parseLong(inputCheckDto.getRiskSourceId());
            }

            LatentDangerBo latentDangerBo = saveLatentDanger("", "", remark, userId, departmentId,
                                                             businessKey, orgCode, dangerName, levelEnum.getCode(),
                                                             null, dangerTypeEnum, photoUrls, inputCheckDto.getCheckInputId(), riskSourceId,
                    position.get(inputCheckDto.getRiskSourceId())==null?"":position.get(inputCheckDto.getRiskSourceId()).toString(), InstanceKeyEnum.PATROL.getCode());
            // 更新p_check_input表state字段
            updateCheckInputDangerState(latentDangerBo.getBizId(), DangerHandleStateEnum.HANDLE.getCode());
            Long dangerId = latentDangerBo.getId();
            Date startDate = new Date();
            JSONObject jsonObject = remoteWorkFlowService.startNew(dangerId, businessKey, processDefinitionKey);
            Date endDate = new Date();
            logger.info("-------------------------提交隐患时间" +(endDate.getTime()-startDate.getTime()));
            if (jsonObject == null) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return CommonResponseUtil.failure("启动流程失败");
            }
            JSONObject instance = jsonObject.getJSONObject("data");
            if(instance==null){
                return CommonResponseUtil.failure("无提交隐患权限");
            }
            LatentDangerFlowRecordBo inputRecord = saveFlowRecord(instance.getString("id"), "提交隐患", userId, departmentId,
                                                                  null, dangerId, role, LatentDangerExcuteTypeEnum.填写隐患完成.getName(),latentDangerBo.getRemark());

            JSONObject flowJson = new JSONObject();
            flowJson.put("photoUrls", photoUrls);
            updateFlowRecord(inputRecord, LatentDangerExcuteTypeEnum.填写隐患完成, userId, departmentId, remark, flowJson);
            if (LatentDangerTypeEnum.计划检查.getCode().equals(latentDangerBo.getDangerType())
                    || LatentDangerTypeEnum.无计划检查.getCode().equals(latentDangerBo.getDangerType())) {
                LatentDangerPatrolBo latentDangerPatrolBo = new LatentDangerPatrolBo();
                latentDangerPatrolBo.setCheckId(inputCheckDto.getCheckId());
                latentDangerPatrolBo.setPointClassifyId(inputCheckDto.getPointClassifyId());
                latentDangerPatrolBo.setItemId(inputCheckDto.getItemId());
                latentDangerPatrolBo.setRouteId(inputCheckDto.getRouteId());
                latentDangerPatrolBo.setPointId(inputCheckDto.getPointId());
                latentDangerPatrolBo.setLatentDangerId(latentDangerBo.getId());
                latentDangerPatrolBo.setRoutePointItemId(inputCheckDto.getRoutePointItemId());
                latentDangerPatrolMapper.save(latentDangerPatrolBo);
            }
            latentDangerBo.setCurrentFlowRecordId(inputRecord.getId());
            latentDangerBo.setInstanceId(instance.getString("id"));
            latentDangerMapper.update(latentDangerBo);
            //修改管控措施的状态为失效
            LatentDangerPatrolBo patrolBo = latentDangerPatrolMapper.getByDangerId(latentDangerBo.getId());
            sendMessage(latentDangerBo, LatentDangerExcuteTypeEnum.填写隐患完成, patrolBo,
                        "巡检隐患排查与治理", this.getNextExecuteUsers(latentDangerBo.getInstanceId()), userRealName, departmentName);
            try {
                webMqttComponent.publish(dangerTopic, "");
            }catch (Exception e){
                logger.error("巡检隐患提交数字换流站页面推送失败-----------"+e.getMessage());
            }
        }
        return CommonResponseUtil.success();
    }

    private void updateCheckInputDangerState(Long id, int code) {
        latentDangerMapper.updateCheckInputDangerState(id, code);
    }

    private String buildLocalHost() {
        try {
            String ip = InetAddress.getLocalHost().getHostAddress();
            return "http://" + ip + ":" + port + "/";
        } catch (Exception e) {
            return "";
        }
    }

    private void updateMeasuresContentStatus(Long riskFactorId, Long measuresContentId, String evaluateId, RiskFactorsCmStatusEnum riskFactorsCmStatusEnum) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("riskFactorId", riskFactorId);
        map.put("measuresContentId", measuresContentId);
        map.put("evaluateId", evaluateId);
        map.put("status", riskFactorsCmStatusEnum.getCode());
        riskFactorCmMapper.updateStatusByMap(map);
        RiskFactorBo riskFactorBo = new RiskFactorBo();
        riskFactorBo.setId(riskFactorId);
        Long outControlNumber = riskFactorCmMapper.countOutControl(map);
        if (outControlNumber.equals(0L)) {
            riskFactorBo.setControlStatus(RiskFactorsCmStatusEnum.Control.getName());
        } else {
            riskFactorBo.setControlStatus(RiskFactorsCmStatusEnum.outOfControl.getName());
        }
        riskFactorMapper.updateControlStatus(riskFactorBo);
    }

    public LatentDangerBo saveLatentDanger(String instanceId, String problemDescription, String remark, String userId,
                                           String departmentId, String businessKey, String orgCode, String dangerName,
                                           Integer level, String position, LatentDangerTypeEnum dangerTypeEnum,
                                           String photoUrls, Long checkInputId, Long structureId, String structureName, String instanceKey) {
        LatentDangerBo latentDangerBo = new LatentDangerBo();
        latentDangerBo.setBizType(bizType);
        latentDangerBo.setInstanceId(instanceId);
        latentDangerBo.setProblemDescription(problemDescription);
        latentDangerBo.setRemark(remark);
        latentDangerBo.setDangerState(LatentDangerStateEnum.待评审.getCode().toString());
        latentDangerBo.setDiscovererUserId(userId);
        latentDangerBo.setDiscovererDepartmentId(departmentId);
        latentDangerBo.setBusinessKey(businessKey);
        latentDangerBo.setOrgCode(orgCode);
        latentDangerBo.setDangerName(dangerName);
        latentDangerBo.setDangerLevel(level.toString());
        latentDangerBo.setDangerLevelName(LatentDangerLevelEnum.getByCode(level).getName());
        latentDangerBo.setDangerPosition(position);
        latentDangerBo.setDangerType(dangerTypeEnum.getCode().toString());
        latentDangerBo.setDangerTypeName(dangerTypeEnum.getName());
        latentDangerBo.setDangerStateName(LatentDangerStateEnum.待评审.getName());
        StringBuilder photoUrlsB = new StringBuilder();
        if(org.apache.commons.lang3.StringUtils.isNotBlank(photoUrls)){
            String[] photoUrlsList = photoUrls.split(",");
            for (String url : photoUrlsList) {
                if (!"".equals(url)){
//                    photoUrlsB.append(fileUrl+url);
                    photoUrlsB.append(url);
                    photoUrlsB.append(",");
                }
            }
        }
        latentDangerBo.setPhotoUrls(photoUrlsB.toString());
        latentDangerBo.setBizId(checkInputId);
        latentDangerBo.setStructureId(structureId);
        latentDangerBo.setStructureName(structureName);
        latentDangerBo.setInstanceKey(instanceKey);
        latentDangerMapper.save(latentDangerBo);
        return latentDangerBo;
    }

    public LatentDangerFlowRecordBo saveFlowRecord(String taskId, String taskName, String userId, String departmentId,
                                                   JSONObject flowJson, Long dangerId, RoleBo role, String executeResult,String remark) {
        LatentDangerFlowRecordBo record = new LatentDangerFlowRecordBo();
        record.setFlowTaskId(taskId);
        record.setExecuteUserId(userId);
        record.setExecuteDepartmentId(departmentId);
        if(flowJson != null && org.apache.commons.lang3.StringUtils.isNotBlank(flowJson.getString("photoUrls"))){
//            flowJson.put("photoUrls",fileUrl+flowJson.getString("photoUrls"));
            flowJson.put("photoUrls",flowJson.getString("photoUrls"));
        }
        record.setFlowJson(flowJson != null ? flowJson.toJSONString() : null);
        record.setFlowTaskName(taskName);
        record.setDangerId(dangerId);
//        record.setExcuteUserId(RequestContext.getLoginId());
        record.setExecuteResult(executeResult);
        record.setDeleted(0);
        record.setActionFlag(taskName);
        record.setRemark(remark);
        latentDangerFlowRecordMapper.save(record);
        return record;
    }

    public LatentDangerFlowRecordBo saveFlowRecord(String taskId, String userIds, String taskName,
                                                   String taskDefinitionKey, Long dangerId) {
        LatentDangerFlowRecordBo record = new LatentDangerFlowRecordBo();
        record.setFlowTaskId(taskId);
        record.setFlowTaskUserIds(userIds);
        record.setFlowTaskName(taskName);
        record.setActionFlag(taskDefinitionKey);
        record.setDangerId(dangerId);
        latentDangerFlowRecordMapper.save(record);
        return record;
    }

    public void updateFlowRecord(LatentDangerFlowRecordBo flowRecord, LatentDangerExcuteTypeEnum excuteTypeEnum,
                                 String userId, String departmentId, String remark, JSONObject flowJson) {
        flowRecord.setExecuteState(excuteTypeEnum.getExcuteState().getCode());
        flowRecord.setExecuteDepartmentId(departmentId);
        flowRecord.setExecuteUserId(userId);
        flowRecord.setExecuteResult(excuteTypeEnum.getName());
        if (!StringUtils.isEmpty(remark)) {
            flowRecord.setRemark(remark);
        }
        if (flowJson != null) {
            flowRecord.setFlowJson(flowJson.toJSONString());
        }
        latentDangerFlowRecordMapper.update(flowRecord);
    }

    private Set<String> getUserIdsStrByTypeAndDefKey(String definitionKey) {
        List<AgencyUserModel> users = remoteSecurityService.listUserByMenuCode(acctivePermissionType, definitionKey);
        if (CollectionUtils.isEmpty(users)) {
            return Sets.newHashSet();
        } else {
            return Sets.newHashSet(Lists.transform(users, AgencyUserModel::getUserId));
        }
    }

    private Set<String> getUserIdsStrByPerTypeAndDefKey(JSONObject jsonObject) {
        String taskDefinitionKey = jsonObject.getString("taskDefinitionKey");
//        List<UserModel> users = remoteSecurityService.listUserByMenuCode(acctivePermissionType, taskDefinitionKey);
//        if (CollectionUtils.isEmpty(users)) {
//            return Sets.newHashSet();
//        } else {
//            return Sets.newHashSet(Lists.transform(users, UserModel::getUserId));
//        }
        return getUserIdsStrByTypeAndDefKey(taskDefinitionKey);
    }

    private Map<String, Object> buildQueryMapForList(LatentDangerListParam latentDangerListParam, String userId) {
        Map<String, Object> map = Maps.newHashMap();
        Long offset = latentDangerListParam.getOffset();
        map.put("offset", offset);
        map.put("limit", latentDangerListParam.getPageSize());
        if (latentDangerListParam.getIsHandle() != null) {
            List<Integer> states = Lists.newArrayList();
            if (latentDangerListParam.getIsHandle()) {
                states.add(LatentDangerStateEnum.治理完毕.getCode());
                states.add(LatentDangerStateEnum.已撤销.getCode());
            } else {
                states.add(LatentDangerStateEnum.待验证.getCode());
                states.add(LatentDangerStateEnum.延期治理申请.getCode());
                states.add(LatentDangerStateEnum.安措计划中.getCode());
                states.add(LatentDangerStateEnum.待治理.getCode());
                states.add(LatentDangerStateEnum.待评审.getCode());
                states.add(LatentDangerStateEnum.延期治理申请待车间部门审核.getCode());
                states.add(LatentDangerStateEnum.延期治理申请待公司审核.getCode());
            }
            map.put("states", states);
        }
        if (!latentDangerListParam.getBelongType().equals(0)) {
            map.put("userId", userId);
        }
        if (!latentDangerListParam.getDangerLevel().equals(-1)) {
            map.put("dangerLevel", latentDangerListParam.getDangerLevel());
        }
        if (!latentDangerListParam.getDangerState().equals(0)) {
            map.put("dangerState", latentDangerListParam.getDangerState());
        }
        if (!StringUtils.isEmpty(latentDangerListParam.getDangerName())) {
            map.put("dangerName", latentDangerListParam.getDangerName());
        }
        return map;
    }

    @Override
    public CommonResponse list(String toke,
                               String product,
                               String appKey,
                               LatentDangerListParam latentDangerListParam,
                               AgencyUserModel user,
                               String loginOrgCode,
                               String deptId) {
        JSONObject respBody;
        Date startDate = new Date();
        if (latentDangerListParam.getIsHandle()) {
            respBody = remoteWorkFlowService.completedPageTask(user.getUserName(),latentDangerListParam.getBelongType());
        } else {
            respBody = remoteWorkFlowService.pageTask(user.getUserId(),latentDangerListParam.getBelongType());
        }
        Date endDate = new Date();
        logger.info("-------------------------工作流列表时间" + (endDate.getTime() - startDate.getTime()));
        JSONArray taskJsonList = respBody.getJSONArray("data");
        List<JSONObject> taskList = Lists.newArrayList();
        if (!ValidationUtil.isEmpty(taskJsonList)) {
            taskList = JSONObject.parseArray(taskJsonList.toJSONString(), JSONObject.class);
        }
        List<String> bussinessKeys = new ArrayList<>();
        for (JSONObject json : taskList) {
            bussinessKeys.add(json.getString("businessKey"));
        }
        if (0 == latentDangerListParam.getBelongType()) {
            latentDangerListParam.setUserId(null);
        }
        if (-1 == latentDangerListParam.getDangerLevel()) {
            latentDangerListParam.setDangerLevel(null);
        }
        if (0 == latentDangerListParam.getDangerState()) {
            latentDangerListParam.setDangerState(null);
        }
        Date  startDate1 = new Date();;
        int dangerListSize = latentDangerMapper.countByBathBusinessKeys(bussinessKeys, latentDangerListParam);
        List<LatentDangerBo> dangerList = latentDangerMapper.getByBathBusinessKeys(bussinessKeys, latentDangerListParam);
        Date  endDate1 = new Date();
        logger.info("-------------------------sql时间" +(endDate1.getTime()-startDate1.getTime()));
//        Map<String, Object> map = buildQueryMapForList(latentDangerListParam, userId);
//        map.put("org_code", loginOrgCode);
//        map.put("discoverer_department_id", deptId);
//        String permissions = hasProcessBPermission(userId, acctivePermissionType);
//        map.put("permissions", permissions);
//        List<LatentDangerBo> list = latentDangerMapper.listByMap(map);
//        Long count = 0L;
        List<LatentDangerListVo> voList = Lists.newArrayList();
        Date date = new Date();
        if (!CollectionUtils.isEmpty(dangerList)) {
            Set<String> userIds = Sets.newHashSet();
            dangerList.forEach(e -> userIds.add(e.getDiscovererUserId()));
            String userIdsStr = Joiner.on(",").join(userIds);
            List<AgencyUserModel> users = remoteSecurityService.listUserByUserIds(toke, product, appKey, userIdsStr);
            Map<String, AgencyUserModel> userMap = Maps.uniqueIndex(users, AgencyUserModel::getUserId);
            for (LatentDangerBo bo : dangerList) {
                List<JSONObject> filterTaskList =
                        taskList.stream().filter(t -> t.getString("businessKey").equals(bo.getBusinessKey())).collect(Collectors.toList());
                LatentDangerListVo vo = new LatentDangerListVo();
                if (!ValidationUtil.isEmpty(filterTaskList)) {
                    JSONObject task = filterTaskList.get(0);
                    vo.setTaskId(task.getString("id"));
                }
                vo.setDangerId(bo.getId());
                vo.setOvertimeState(bo.getOvertimeState());
                vo.setDangerName(bo.getDangerName());
                vo.setDiscovererUserName(userMap.get(bo.getDiscovererUserId()).getRealName());
                vo.setLevel(bo.getDangerLevel());
                LatentDangerLevelEnum levelEnum = LatentDangerLevelEnum.getByCode(Integer.parseInt(bo.getDangerLevel()));
                if (levelEnum != null) {
                    vo.setLevelDesc(levelEnum.getName());
                }
                vo.setState(bo.getDangerState());
                LatentDangerStateEnum stateEnum = LatentDangerStateEnum.getByCode(Integer.parseInt(bo.getDangerState()));
                if (stateEnum != null) {
                    vo.setStateDesc(stateEnum.getName());
                }
                vo.setLimitDesc(getLimitDesc(bo, date));
                voList.add(vo);
            }
//            count = latentDangerMapper.countByMap(map);
        }
//        return CommonResponseUtil.success(new PageImpl<>(newList, latentDangerListParam, respBody.getLong("total")));
        return CommonResponseUtil.success(new PageImpl<>(voList, latentDangerListParam, dangerListSize));
    }

    /**
     * 获取指定用户具有隐患权限的code
     *
     * @param userId         指定用户id
     * @param permissionType “activitiItem”
     * @return permissions 具有隐患权限的code（逗号分割）
     */
    private String hasProcessBPermission(String userId, String permissionType) {
        String permissions = "";
        // 根据用户id和许可类型获取用户所有的授权操作菜单路径（"B"、"B_1"、"G_1_1"、"A"、"A_1"、"C".....）
        JSONArray jsonArray = remoteSecurityService.getMenuPathByUserIdAndPermissionType(userId, permissionType);
        if (CollectionUtils.isEmpty(jsonArray)) {
            return "";
        }
        // 过滤出隐患权限菜单路径（"B_1,B_2.....B_10"）
        Object obj = jsonArray.stream().filter(i -> i.toString().matches("^B_\\d+")).collect(Collectors.toList());
        if (StringUtil.isNotEmpty(obj) && ((List<String>) obj).size() > 0) {
            permissions = Joiner.on(",").join((List<String>) obj);
        }
        return permissions;
    }

    private String getLimitDesc(LatentDangerBo bo, Date start) {
        Integer dangerState = Integer.parseInt(bo.getDangerState());
        if (LatentDangerStateEnum.已撤销.getCode().equals(dangerState) || LatentDangerStateEnum.治理完毕.getCode().equals(dangerState)) {
            if (bo.getOvertimeState().equals(LatentDangerOvertimeStateEnum.已超时.getCode())) {
                return "逾期治理";
            } else {
                return "按期治理";
            }
        } else {
            Date end = bo.getReformLimitDate();
            if (end == null) {
                return "";
            }
            if (bo.getOvertimeState().equals(LatentDangerOvertimeStateEnum.已超时.getCode())) {
                return "逾期未治理";
            } else {
                long betweenSecond = (end.getTime() - start.getTime()) / 1000;
                if (betweenSecond < 0) {
                    return "逾期未治理";
                } else {
                    String str = "";
                    if (betweenSecond > 3600) {
                        long hour = betweenSecond / 3600;
                        str += hour + "时";
                        betweenSecond = betweenSecond % 3600;
                    }
                    if (betweenSecond > 60) {
                        long minute = betweenSecond / 60;
                        str += minute + "分";
                        betweenSecond = betweenSecond % 60;
                    }
                    if (betweenSecond > 0) {
                        str += betweenSecond + "秒";
                    }
                    return str;
                }
            }
        }
    }

    @Transactional
    @Override
    public DangerExecuteSubmitDto execute(LatentDangerExcuteParam latentDangerExcuteParam, String userId, String userRealName, String departmentId, String departmentName, RoleBo role) {
        DangerExecuteSubmitDto executeSubmitDto = new DangerExecuteSubmitDto();
        LatentDangerBo latentDangerBo = null;
        if (StringUtil.isNotEmpty(latentDangerExcuteParam.getDangerId())) {
            latentDangerBo = latentDangerMapper.getById(latentDangerExcuteParam.getDangerId());
        }
        if(StringUtil.isNotEmpty(latentDangerExcuteParam.getReformLimitDate())){
            latentDangerExcuteParam.setReformLimitDate(latentDangerExcuteParam.getReformLimitDate()+" 23:59:59");
        }
        LatentDangerExcuteTypeEnum executeTypeEnum = LatentDangerExcuteTypeEnum.getByCode(latentDangerExcuteParam.getExcuteType());
        if (executeTypeEnum == null) {
            executeSubmitDto.setIsOk(false);
            executeSubmitDto.setMsg("执行类型有误");
            return executeSubmitDto;
        }
        // 延期治理时，根据用户选择是否需要公司来构造参数调用工作流
        if (StringUtil.isNotEmpty(latentDangerExcuteParam.getNeedCompanyVerify())
                && executeTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患延期治理车间部门审核通过)) {
            String requestBody = "";
            if (latentDangerExcuteParam.getNeedCompanyVerify() == 0) {// 延期治理申请 不需要公司审核
                requestBody = "{\"needCompanyApproval\": \"否\",\"approveResult\": \"通过\"}";
            } else {// 延期治理申请 需要公司审核
                requestBody = "{\"needCompanyApproval\": \"是\",\"approveResult\": \"通过\"}";
            }
            executeTypeEnum.setRequestBody(requestBody);
        }
        // 延期治理选择的延期日期不能早于整改日期校验
        if (executeTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患延期治理)) {
            if (latentDangerBo.getReformLimitDate().compareTo(DateUtil.longStr2Date(latentDangerExcuteParam.getDelayLimitDate())) >= 0) {
                executeSubmitDto.setIsOk(false);
                executeSubmitDto.setMsg("延期日期不能早于整改期限");
                return executeSubmitDto;
            }
        }

        DangerExecuteSubmitDto dangerExecuteSubmitDto=  executeSubmit(latentDangerExcuteParam, executeTypeEnum, latentDangerBo, userId, userRealName, departmentId, departmentName, executeSubmitDto, role);
        try {
            webMqttComponent.publish(dangerTopic, "");
        }catch (Exception e){
            logger.error("隐患执行提交数字换流站页面推送失败-----------"+e.getMessage());
        }

        return dangerExecuteSubmitDto;
    }

    @Override
    public CommonResponse detail(String id, String userId, boolean isFinish) {
        JSONObject jsonObject;
        if (isFinish) {
            jsonObject = remoteWorkFlowService.queryFinishTaskDetail(id);
        } else {
            jsonObject = remoteWorkFlowService.queryTaskDetail(id);
        }

        if (ValidationUtil.isEmpty(jsonObject)) {
            return null;
        }

        JSONObject task = jsonObject.getJSONObject("data");
        LatentDangerBo latentDangerBo = latentDangerMapper.getbyBusinessKey(task.getString("businessKey"));

//        LinkedHashMap<String,Object> positionAll  = equipFeign.getBuildingAbsolutePosition();
//        LinkedHashMap<String,Object> position =  new LinkedHashMap<>();
//        if("200".equals(positionAll.get("status").toString())){
//             position = (LinkedHashMap<String, Object>) positionAll.get("result");
//        }

        LatentDangerDetailVo detailVo = new LatentDangerDetailVo();
        if (latentDangerBo != null) {
            detailVo.setDangerId(latentDangerBo.getId());
            detailVo.setDangerIdWeb(String.valueOf(latentDangerBo.getId()));
            detailVo.setDangerType(latentDangerBo.getDangerType());
//            if(position.size()>0){
//                detailVo.setPosition(position.get(latentDangerBo.getStructureId()).toString());
//            }else {
//                detailVo.setPosition(latentDangerBo.getDangerPosition());
//            }
           if(StringUtils.isEmpty(latentDangerBo.getDangerPosition())){
                detailVo.setPosition(latentDangerBo.getStructureName());
            }else{
               detailVo.setPosition(latentDangerBo.getStructureName()+"·"+latentDangerBo.getDangerPosition());
           }

            detailVo.setDangerState(latentDangerBo.getDangerState());
            detailVo.setProblemDescription(latentDangerBo.getProblemDescription());
            detailVo.setReasonAnalysis(latentDangerBo.getReasonAnalysis());
            detailVo.setInferOtherThings(latentDangerBo.getInferOtherThings());
            detailVo.setProblemDescription(latentDangerBo.getProblemDescription());
            LatentDangerStateEnum dangerStateEnum = LatentDangerStateEnum.getByCode(latentDangerBo.getDangerState());
            if (dangerStateEnum != null) {
                detailVo.setDangerStateDesc(dangerStateEnum.getName());
            }
            detailVo.setDangerName(latentDangerBo.getDangerName());
            detailVo.setLevel(latentDangerBo.getDangerLevel());
            LatentDangerLevelEnum levelEnum = LatentDangerLevelEnum.getByCode(latentDangerBo.getDangerLevel());
            if (levelEnum != null) {
                detailVo.setLevelDesc(levelEnum.getName());
            }
            detailVo.setRemark(latentDangerBo.getRemark());
            if (latentDangerBo.getReformType() != null) {
                LatentDangerReformTypeEnum typeEnum = LatentDangerReformTypeEnum.getByCode(latentDangerBo.getReformType());
                if (typeEnum != null) {
                    detailVo.setReformTypeDesc(typeEnum.getName());
                }
            }
            if (latentDangerBo.getReformLimitDate() != null) {
                detailVo.setReformLimitDate(DateUtil.date2Str(latentDangerBo.getReformLimitDate(), DateUtil.DATETIME_DEFAULT_FORMAT));
            }
            if (latentDangerBo.getDelayLimitDate() != null) {
                detailVo.setDelayLimitDate(DateUtil.date2Str(latentDangerBo.getDelayLimitDate(),
                                                             DateUtil.DATETIME_DEFAULT_FORMAT));
            }
//            detailVo.setCurrentUserCanExcute(false);
//            if (!latentDangerBo.getCurrentFlowRecordId().equals(-1L)) {
//                LatentDangerFlowRecordBo currentRecord = latentDangerFlowRecordMapper.getById(latentDangerBo.getCurrentFlowRecordId());
//                String userIdsStr = currentRecord.getFlowTaskUserIds();
//                List<String> userIds = Arrays.asList(userIdsStr.split(","));
//                if (userIds.contains(userId) || hasProcessBPermission(userId, acctivePermissionType).contains(currentRecord.getActionFlag())) {
//                    detailVo.setCurrentUserCanExcute(true);
//                }
//            }
            detailVo.setCurrentFlowRecordId(latentDangerBo.getCurrentFlowRecordId());
            detailVo.setCurrentFlowRecordIdWeb(String.valueOf(latentDangerBo.getCurrentFlowRecordId()));
            if (!StringUtils.isEmpty(latentDangerBo.getReformJson())) {
                detailVo.setReformJson(JSONObject.parseObject(latentDangerBo.getReformJson()));
            }
            if (!StringUtils.isEmpty(latentDangerBo.getPhotoUrls())) {
                List<String> photoUrls = Lists.newArrayList(latentDangerBo.getPhotoUrls().split(","));
                detailVo.setPhotoUrls(photoUrls);
            }
            buildOfDifferentDangerType(latentDangerBo, detailVo);
            detailVo.setTaskId(task.getString("id"));
        }
        return CommonResponseUtil.success(detailVo);
    }

    private void buildOfDifferentDangerType(LatentDangerBo latentDangerBo, LatentDangerDetailVo detailVo) {
        if (latentDangerBo.getDangerType().equals(LatentDangerTypeEnum.计划检查.getCode())
                || latentDangerBo.getDangerType().equals(LatentDangerTypeEnum.无计划检查.getCode())) {
            LatentDangerPatrolBo patrolBo = latentDangerPatrolMapper.getByDangerId(latentDangerBo.getId());
            if (patrolBo != null) {
                LatentDangerDetailRiskVo riskVo = new LatentDangerDetailRiskVo();
                List<String> basis = new ArrayList<>();
                if(!StringUtils.isEmpty(patrolBo.getItemBasis())){
                    basis.add(patrolBo.getItemBasis());
                }
                riskVo.setBasis(basis);
                riskVo.setPointName(patrolBo.getPointName());
                riskVo.setPointNo(patrolBo.getPointNo());
                riskVo.setPointLevel(StringUtil.isNotEmpty(patrolBo.getPointLevel()) ? patrolBo.getPointLevel() : "");
                riskVo.setPlanName(patrolBo.getPlanName());
                riskVo.setCheckTime(patrolBo.getCheckTime());
                AgencyUserModel checkUser = remoteSecurityService.getUserById(RequestContext.getToken(),RequestContext.getProduct(),RequestContext.getAppKey(), patrolBo.getCheckUserId());
                if (StringUtil.isNotEmpty(checkUser)) {
                    riskVo.setCheckUser(checkUser.getRealName());
                }
                RiskFactorBo riskFactorBo = StringUtil.isNotEmpty(patrolBo.getClassifyOriginalId()) ? riskFactorMapper.getById(Long.valueOf(patrolBo.getClassifyOriginalId())) : null;
                if (riskFactorBo != null && riskFactorBo.getEquipmentDepartmentId() != null) {
                    DepartmentModel department = remoteSecurityService.getDepartmentByDeptId(RequestContext.getToken(), getProduct(),RequestContext.getAppKey(),riskFactorBo.getEquipmentDepartmentId().toString());
                    if (department != null) {
                        riskVo.setBelongDepartmentName(department.getDepartmentName());
                    }
                }
                List<CheckShot> checkShots = iCheckShotDao.findAllByCheckIdAndCheckInputId(patrolBo.getCheckId(),
                                                                                           latentDangerBo.getBizId());
                if (!CollectionUtils.isEmpty(checkShots)) {
                    List<String> photos = Lists.transform(checkShots, e -> {
                        if (e != null) {
                            return fileServerAddress + e.getPhotoData().replaceAll("\\\\", "/");
                        } else {
                            return "";
                        }
                    });
                    detailVo.setPhotoUrls(photos);
                }
                detailVo.setRiskInfo(riskVo);
            }
        }
    }

    @Override
    public CommonResponse getByInstanceId(String instanceId) {
        LatentDangerBo latentDangerBo = latentDangerMapper.getByInstanceId(instanceId);
        if (latentDangerBo == null) {
            return CommonResponseUtil.failure("隐患不存在");
        }
        JSONObject result = new JSONObject();
        JSONObject baseInfo = new JSONObject();
        JSONObject reviewInfo = new JSONObject();
        JSONObject dangerInfo = new JSONObject();
        Set<String> userIds = Sets.newHashSet();
        userIds.add(latentDangerBo.getDiscovererUserId());
        LatentDangerPatrolBo patrolBo = null;
        if (latentDangerBo.getDangerType().equals(LatentDangerTypeEnum.计划检查.getCode())) {
            patrolBo = latentDangerPatrolMapper.getByDangerId(latentDangerBo.getId());
            JSONArray checkTypeArry = remoteSecurityService.listDictionaryByDictCode(RequestContext.getToken(), getProduct(),
                                                                                     RequestContext.getAppKey(), XJConstant.CHECK_TYPE);
            Map<String, String> checkTypeMap = Maps.newHashMap();
            for (int i = 0; i < checkTypeArry.size(); i++) {
                JSONObject categoryJson = checkTypeArry.getJSONObject(i);
                checkTypeMap.put(categoryJson.getString("dictDataKey"), categoryJson.getString("dictDataValue"));
            }
            if (patrolBo != null) {
                PointClassify classify = iPointClassifyDao.getOne(patrolBo.getPointClassifyId());
                RiskFactorBo riskFactorBo = riskFactorMapper.getById(Long.valueOf(classify.getOriginalId()));
                String jsonStr = patrolBo.getItemBasis();
                String itemBasis = "";
                if (!StringUtils.isEmpty(jsonStr)) {
                    StringBuilder itemBasisBuilder = new StringBuilder();
                    JSONArray arr = JSONArray.parseArray(jsonStr);
                    for (int i = 0; i < arr.size(); i++) {
                        JSONObject object = arr.getJSONObject(i);
                        itemBasisBuilder.append(object.getString("name")).append(",");
                    }
                    itemBasis = itemBasisBuilder.length() > 0 ? itemBasisBuilder.substring(0, itemBasisBuilder.length() - 1) : itemBasis;
                }
                if (riskFactorBo != null) {
                    userIds.add(patrolBo.getCheckUserId());
                    dangerInfo.put("type", "设备设施类");
                    dangerInfo.put("equipmentCode", riskFactorBo.getEquipmentCode());
                    dangerInfo.put("isCheckWithPlan", "是");
                    dangerInfo.put("planName", patrolBo.getPlanName());
                    dangerInfo.put("planType", checkTypeMap.get(patrolBo.getCheckType()));
                    dangerInfo.put("routeName", patrolBo.getRouteName());
                    dangerInfo.put("classifyName", patrolBo.getClassifyName());
                    dangerInfo.put("itemName", patrolBo.getItemName());
                    dangerInfo.put("itemBasis", itemBasis);
                    dangerInfo.put("itemRemark", patrolBo.getItemRemark());
                    dangerInfo.put("checkTime", DateUtil.str2Date(patrolBo.getCheckTime(), DateUtil.DATETIME_DEFAULT_FORMAT));
                }
            }
        }
        LatentDangerFlowRecordBo reviewRecordBo = latentDangerFlowRecordMapper.getByDangerIdAndActionFlag(latentDangerBo.getId(), "B_2");
        LatentDangerFlowRecordBo reformRecordBo = latentDangerFlowRecordMapper.getByDangerIdAndActionFlag(latentDangerBo.getId(), "B_3");
        if (reviewRecordBo != null) {
            userIds.add(reviewRecordBo.getExecuteUserId());
        }
        if (reformRecordBo != null) {
            userIds.add(reformRecordBo.getExecuteUserId());
        }
        userIds.removeAll(Collections.singleton(null));
        List<AgencyUserModel> userModels = remoteSecurityService.listUserByUserIds(Joiner.on(",").join(userIds));
        Map<String, AgencyUserModel> userMap = Maps.uniqueIndex(userModels, AgencyUserModel::getUserId);
        AgencyUserModel user = userMap.get(latentDangerBo.getDiscovererUserId());
        baseInfo.put("orderNo", latentDangerBo.getBusinessKey());
        baseInfo.put("startTime", latentDangerBo.getCreateDate());
        if (user != null) {
            baseInfo.put("userName", user.getRealName());
        }
        DepartmentBo departmentBo = remoteSecurityService.getDepartmentByDeptId(latentDangerBo.getDiscovererDepartmentId());
        if (departmentBo != null) {
            baseInfo.put("department", departmentBo.getDepartmentName());
        }
        LatentDangerLevelEnum levelEnum = LatentDangerLevelEnum.getByCode(latentDangerBo.getDangerLevel());
        if (levelEnum != null) {
            dangerInfo.put("latentDangerLevel", levelEnum.getName());
        }
        dangerInfo.put("latentDangerName", latentDangerBo.getDangerName());
        if (!StringUtils.isEmpty(latentDangerBo.getReformJson())) {
            String str = JSONObject.parseObject(latentDangerBo.getReformJson()).getString("rectMeasures");
            dangerInfo.put("reformJson", str.replace("\\n", "\\\\n"));
        }
        dangerInfo.put("reformLimitDate", latentDangerBo.getReformLimitDate());
        if (reformRecordBo != null) {
            AgencyUserModel reformUser = userMap.get(reformRecordBo.getExecuteUserId());
            if (reformUser != null) {
                dangerInfo.put("reformUserName", reformUser.getRealName());
            }
        }
        if (patrolBo != null) {
            if (patrolBo.getCheckUserId() != null) {
                AgencyUserModel checkUser = userMap.get(patrolBo.getCheckUserId());
                if (checkUser != null) {
                    dangerInfo.put("checkUserName", checkUser.getRealName());
                }
            }
            if (patrolBo.getCheckDepartmentId() != null) {
                DepartmentBo checkDepartment = remoteSecurityService.getDepartmentByDeptId(patrolBo.getCheckDepartmentId());
                if (checkDepartment != null) {
                    dangerInfo.put("checkUserDeptName", checkDepartment.getDepartmentName());
                }
            }
        }
        if (reviewRecordBo != null) {
            AgencyUserModel reviewUser = userMap.get(reviewRecordBo.getExecuteUserId());
            reviewInfo.put("reviewUserName", StringUtil.isNotEmpty(reviewUser) ? reviewUser.getRealName() : "");
            reviewInfo.put("reviewDate", StringUtil.isNotEmpty(reviewUser) ? reviewRecordBo.getUpdateDate() : "");
            reviewInfo.put("reviewResult", StringUtil.isNotEmpty(reviewUser) ? reviewRecordBo.getExecuteResult() : "");
        }
        result.put("baseInfo", baseInfo);
        result.put("dangerInfo", dangerInfo);
        result.put("reviewInfo", reviewInfo);
        result.put("latentDangerType", latentDangerBo.getDangerType());
        LatentDangerTypeEnum typeEnum = LatentDangerTypeEnum.getByCode(latentDangerBo.getDangerType());
        if (typeEnum != null) {
            result.put("latentDangerTypeDesc", typeEnum.getName());
        }
        return CommonResponseUtil.success(result);
    }

    @Transactional
    @Override
    public DangerExecuteSubmitDto excuteCallBack(String instanceId, Integer actionType, String remark, String token,
                                                 String userId, String userRealName, String departmentId, String departmentName) {
        DangerExecuteSubmitDto executeSubmitDto = new DangerExecuteSubmitDto();
        executeSubmitDto.setIsOk(true);
        LatentDangerBo latentDangerBo = latentDangerMapper.getByInstanceId(instanceId);
        if (latentDangerBo != null) {
            LatentDangerFlowRecordBo currentRecord = latentDangerFlowRecordMapper.getById(latentDangerBo.getCurrentFlowRecordId());
            if (actionType.equals(1)) {
                //通过
                LatentDangerExcuteTypeEnum excuteTypeEnum = LatentDangerExcuteTypeEnum.公司负责人审核通过;
                updateFlowRecord(currentRecord, excuteTypeEnum, userId, departmentId, remark, null);
                JSONObject flowJson = remoteWorkFlowService.allTasksInProcessInstanceId(latentDangerBo.getInstanceId());
                if (flowJson == null) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return executeSubmitDto;
                }
                LatentDangerPatrolBo patrolBo = null;
                String userIds;
                if (latentDangerBo.getDangerType().equals(LatentDangerTypeEnum.计划检查.getCode())) {
                    patrolBo = latentDangerPatrolMapper.getByDangerId(latentDangerBo.getId());
                    userIds = Joiner.on(",").join(getUserIdsStrByPerTypeAndDefKey(flowJson));
                } else {
                    LatentDangerFlowRecordBo recordBo = latentDangerFlowRecordMapper.getByDangerIdAndActionFlag(latentDangerBo.getId(), "B_8");
                    userIds = recordBo.getFlowTaskUserIds();
                }
                LatentDangerFlowRecordBo record = saveFlowRecord(flowJson.getString("id"), userIds,
                                                                 flowJson.getString("name"), flowJson.getString("taskDefinitionKey"), latentDangerBo.getId());
                latentDangerBo.setCurrentFlowRecordId(record.getId());
                latentDangerBo.setDangerState(excuteTypeEnum.getNextState().getCode().toString());
                latentDangerMapper.update(latentDangerBo);
                ///web推送刷新消息
//                dangerStateChangeWebSockte(latentDangerBo);
//                Set<String> nextExecuteUserIds = Sets.newHashSet(Arrays.asList(userIds.split(",")));
                sendMessage(latentDangerBo, excuteTypeEnum, patrolBo, currentRecord.getFlowTaskName(), this.getNextExecuteUsers(latentDangerBo.getInstanceId()), userRealName, departmentName);
            } else if (actionType.equals(2)) {
                //终止
                latentDangerBo.setDangerState(LatentDangerStateEnum.已撤销.getCode().toString());
                latentDangerMapper.update(latentDangerBo);
//                remoteWorkFlowService.stop(latentDangerBo.getInstanceId());
                if (latentDangerBo.getDangerType().equals(LatentDangerTypeEnum.计划检查.getCode())) {
                    LatentDangerPatrolBo patrolBo = latentDangerPatrolMapper.getByDangerId(latentDangerBo.getId());
                    if (patrolBo.getClassifyOriginalId() != null && patrolBo.getItemOriginalId() != null) {
                        updateMeasuresContentStatus(Long.valueOf(patrolBo.getClassifyOriginalId()), Long.valueOf(patrolBo.getItemOriginalId()),
                                                    patrolBo.getRiskFactorFlowId(), RiskFactorsCmStatusEnum.Control);
                    }
                    LatentDangerLevelEnum levelEnum = LatentDangerLevelEnum.getByCode(latentDangerBo.getDangerLevel());
                    if (levelEnum != null) {
                        updateRiskSourceDangerState(false, Long.valueOf(patrolBo.getPointOriginalId()), levelEnum, patrolBo.getPointId(), latentDangerBo.getId());
                    }
                    executeSubmitDto.setDangerId(latentDangerBo.getId());
                    executeSubmitDto.setDangerName(latentDangerBo.getDangerName());
                    executeSubmitDto.setPointOriginalId(patrolBo.getPointOriginalId());
                    executeSubmitDto.setPointId(patrolBo.getPointId());
                    executeSubmitDto.setExecuteTypeEnum(LatentDangerExcuteTypeEnum.隐患评审拒绝);
                }
            } else if (actionType.equals(3)) {
                //拒绝
                LatentDangerExcuteTypeEnum excuteTypeEnum = LatentDangerExcuteTypeEnum.公司负责人审核拒绝;
                updateFlowRecord(currentRecord, excuteTypeEnum, userId, departmentId, remark, null);
                JSONObject flowJson = remoteWorkFlowService.allTasksInProcessInstanceId(latentDangerBo.getInstanceId());
                if (flowJson == null) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return executeSubmitDto;
                }
                LatentDangerPatrolBo patrolBo = null;
                String userIds;
                if (latentDangerBo.getDangerType().equals(LatentDangerTypeEnum.计划检查.getCode())) {
                    patrolBo = latentDangerPatrolMapper.getByDangerId(latentDangerBo.getId());
                    userIds = Joiner.on(",").join(getUserIdsStrByPerTypeAndDefKey(flowJson));
                } else {
                    LatentDangerFlowRecordBo recordBo = latentDangerFlowRecordMapper.getByDangerIdAndActionFlag(latentDangerBo.getId(), "B_3");
                    userIds = recordBo.getFlowTaskUserIds();
                }
                LatentDangerFlowRecordBo record = saveFlowRecord(flowJson.getString("id"), userIds,
                                                                 flowJson.getString("name"), flowJson.getString("taskDefinitionKey"), latentDangerBo.getId());
                latentDangerBo.setCurrentFlowRecordId(record.getId());
                latentDangerBo.setDangerState(excuteTypeEnum.getNextState().getCode().toString());
                latentDangerMapper.update(latentDangerBo);
                ///web推送刷新消息
//                dangerStateChangeWebSockte(latentDangerBo);
//                Set<String> nextExecuteUserIds = Sets.newHashSet(Arrays.asList(userIds.split(",")));
                sendMessage(latentDangerBo, excuteTypeEnum, patrolBo, currentRecord.getFlowTaskName(), this.getNextExecuteUsers(latentDangerBo.getInstanceId()), userRealName, departmentName);
            }
        }
        return executeSubmitDto;
    }

    @Override
    public void updateDangerStateOfOvertime() {
        logger.info("修改治理过期隐患的逾期状态");
        List<LatentDangerBo> overtimeList = latentDangerMapper.listOfOvertime();
        for (LatentDangerBo latentDangerBo : overtimeList) {
            latentDangerBo.setOvertimeState(LatentDangerOvertimeStateEnum.已超时.getCode());
            latentDangerMapper.update(latentDangerBo);
            if (latentDangerBo.getDangerType().equals(LatentDangerTypeEnum.计划检查.getCode())) {
                LatentDangerPatrolBo patrolBo = latentDangerPatrolMapper.getByDangerId(latentDangerBo.getId());
                LatentDangerResultPushSpcRequest spcRequest = new LatentDangerResultPushSpcRequest();
                spcRequest.setProcessingTime(DateUtil.date2Str(new Date(), DateUtil.DATETIME_DEFAULT_FORMAT));
                spcRequest.setHiddenTroubleName(latentDangerBo.getDangerName());
                spcRequest.setRiskSourceId(patrolBo.getPointOriginalId());
                spcRequest.setHiddenTroubleStatus("治理逾期");
                spcRequest.setTroubleList(getTroubleList(patrolBo.getPointId()));
                remoteSpcService.pushLatentDangerExcuteResult(spcRequest);
            }
        }
        //推送页面刷新
//        remoteWebSocketServer.wsDataRefresh("dangerOverdue");

        // 即将逾期的隐患发送消息提醒用户
        List<LatentDangerNoticeBo> needNoticeDangerList = latentDangerMapper.listNeedNoticeDanger();
        if (!CollectionUtils.isEmpty(needNoticeDangerList)) {
            logger.info("隐患治理即将逾期通知》》》》");
            needNoticeDangerList.forEach(danger -> {
                asyncTask.pushLatentDangerReformLimitDateExpireMessage(this.getNextExecuteUsers(danger.getInstanceId()),
                                                                       danger.getOrgCode(),
                                                                       danger.getDangerName(), DateUtil.date2Str(danger.getReformLimitDate(), DateUtil.DATETIME_DEFAULT_FORMAT),
                                                                       danger.getDangerId(),
                                                                       danger.getInstanceId(),
                                                                       danger.getDangerState(),"");
            });
        }
    }

    /**
     * web安全态势预控 （ 隐患按车间/部门统计） 模块推送刷新消息
     */
    private void dangerStateChangeWebSockte(LatentDangerBo latentDangerBo) {
        Integer state = Integer.parseInt(latentDangerBo.getDangerState());
        Integer type = Integer.parseInt(latentDangerBo.getDangerType());
        if (LatentDangerTypeEnum.计划检查.getCode().equals(type)
                || LatentDangerTypeEnum.无计划检查.getCode().equals(type)) {
            if (LatentDangerStateEnum.待治理.getCode().equals(state)
//                    || LatentDangerStateEnum.安措计划中.getCode().equals(state)
                    || LatentDangerStateEnum.待验证.getCode().equals(state)) {
                remoteWebSocketServer.wsDataRefresh("dangerExecute");
            }
        }
    }

    @Override
    public CommonResponse listFlowRecord(String token, String product, String appKey, Long id) {
        LatentDangerBo latentDangerBo = latentDangerMapper.getById(id);
        if (latentDangerBo == null) {
            return CommonResponseUtil.failure("隐患不存在");
        }
        LatentDangerDetailVo detailVo = new LatentDangerDetailVo();
        detailVo.setDangerName(latentDangerBo.getDangerName());
        detailVo.setLevel(latentDangerBo.getDangerLevel());
        detailVo.setPosition(latentDangerBo.getStructureName());
        LatentDangerLevelEnum levelEnum = LatentDangerLevelEnum.getByCode(latentDangerBo.getDangerLevel());
        if (levelEnum != null) {
            detailVo.setLevelDesc(levelEnum.getName());
        }
        List<LatentDangerFlowRecordBo> records = latentDangerFlowRecordMapper.listByDangerId(latentDangerBo.getId());
        if (!CollectionUtils.isEmpty(records)) {
            Set<String> userIds = Sets.newHashSet();
            Set<String> deptIds = Sets.newHashSet();
            records.forEach(e -> {
                if (!StringUtils.isEmpty(e.getExecuteUserId())) {
                    userIds.add(e.getExecuteUserId());
                }
                if (!StringUtils.isEmpty(e.getExecuteDepartmentId())) {
                    deptIds.add(e.getExecuteDepartmentId());
                }
            });
            List<DepartmentModel> departmentBos = remoteSecurityService.getlistDepartmentByDeptIds(token,product,appKey,Joiner.on(",").join(deptIds));
            List<AgencyUserModel> userModels = remoteSecurityService.listUserByUserIds(token,product,appKey,Joiner.on(",").join(userIds));
            Map<String, AgencyUserModel> userMap = Maps.uniqueIndex(userModels, AgencyUserModel::getUserId);
            Map<Long, DepartmentModel> departmentBoMap = Maps.uniqueIndex(departmentBos, DepartmentModel::getSequenceNbr);
            for (LatentDangerFlowRecordBo recordBo : records) {
                AgencyUserModel user = userMap.get(recordBo.getExecuteUserId());
                if (user != null) {
                    recordBo.setExecuteUserName(user.getRealName());
                }
                DepartmentModel departmentBo = departmentBoMap.get(recordBo.getExecuteDepartmentId());
                if (departmentBo != null) {
                    recordBo.setExecuteDepartmentName(departmentBo.getDepartmentName());
                }
                recordBo.setExecuteTime(DateUtil.date2Str(recordBo.getCreateDate(), DateUtil.DATETIME_DEFAULT_FORMAT));
            }
            detailVo.setRecords(records);
        }
        return CommonResponseUtil.success(detailVo);
    }

//    private void resetMeasuresContentStatus(LatentDangerBo latentDangerBo) {
//        if (latentDangerBo.getDangerType().equals(LatentDangerTypeEnum.巡检隐患.getCode())
//                || latentDangerBo.getDangerType().equals(LatentDangerTypeEnum.有码无计划隐患.getCode())) {
//            logger.info("重置管控内容的状态为受控");
//            //重置管控内容的状态为受控
//
//        }
//    }

    public DangerExecuteSubmitDto executeSubmit(LatentDangerExcuteParam executeParam,
                                                LatentDangerExcuteTypeEnum executeTypeEnum,
                                                LatentDangerBo latentDangerBo,
                                                String userId,
                                                String userRealName,
                                                String departmentId,
                                                String departmentName,
                                                DangerExecuteSubmitDto executeSubmitDto,
                                                RoleBo role) {
        String governUserId = null;
        if (executeTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患评审通过)) {
            // 消防巡查需求:评审通过后指定治理人
            // 1.获取治理人员对应的amos平台人员
            List<AgencyUserModel> userModelList =
                    jcsFeignClient.getAmosUserByUserId(executeParam.getReviewUserIds()).getResult();
            if (ValidationUtil.isEmpty(userModelList)) {
                executeSubmitDto.setIsOk(false);
                executeSubmitDto.setMsg("治理人员指定失败");
                return executeSubmitDto;
            }
            governUserId = Joiner.on(",").join(Lists.transform(userModelList, AgencyUserModel::getUserName));
        }
        JSONObject executeJson = remoteWorkFlowService.execute(executeParam.getTaskId(), executeTypeEnum.getRequestBody());
        if (executeJson == null) {
            executeSubmitDto.setIsOk(false);
            executeSubmitDto.setMsg("执行失败");
            return executeSubmitDto;
        }
        LatentDangerPatrolBo patrolBo = null;
        if (latentDangerBo.getDangerType().equals(LatentDangerTypeEnum.计划检查.getCode())) {
            patrolBo = latentDangerPatrolMapper.getByDangerId(latentDangerBo.getId());
        }
        JSONObject data = executeJson.getJSONObject("data");
        if (executeTypeEnum.getNextState().equals(LatentDangerStateEnum.已撤销)) {
            latentDangerBo.setDangerState(executeTypeEnum.getNextState().getCode().toString());
            saveFlowRecord(executeJson.getString("id"), data.getString("name"), userId, departmentId,
                           executeParam.getFlowJson(), executeParam.getDangerId(), role, executeTypeEnum.getName(),executeParam.getRemark());
        } else if (executeTypeEnum.getNextState().equals(LatentDangerStateEnum.治理完毕)) {
            latentDangerBo.setDangerState(executeTypeEnum.getNextState().getCode().toString());
            saveFlowRecord(executeJson.getString("id"), data.getString("name"), userId, departmentId,
                           executeParam.getFlowJson(), executeParam.getDangerId(), role, executeTypeEnum.getName(),executeParam.getRemark());
        } else {
            if (executeTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患评审通过)) {
                // 将指定的治理人保存在日志记录
                executeParam.getFlowJson().put("governUserId", governUserId);
            }
            LatentDangerFlowRecordBo flowRecord = saveFlowRecord(executeJson.getString("id"), data.getString("name"), userId, departmentId,
                                                                 executeParam.getFlowJson(), executeParam.getDangerId(), role, executeTypeEnum.getName(),executeParam.getRemark());
            latentDangerBo.setCurrentFlowRecordId(flowRecord.getId());
            latentDangerBo.setDangerState(executeTypeEnum.getNextState().getCode().toString());
            if (executeTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患常规治理)) {
                latentDangerBo.setReformType(LatentDangerReformTypeEnum.常规整改.getCode().toString());
                JSONObject reformJsonObj = JSONObject.parseObject(latentDangerBo.getReformJson());
                if (ValidationUtil.isEmpty(reformJsonObj)) {
                    reformJsonObj = executeParam.getFlowJson();
                } else {
                    reformJsonObj.putAll(executeParam.getFlowJson());
                }
                latentDangerBo.setReformJson(reformJsonObj.toJSONString());
                latentDangerBo.setInferOtherThings(executeParam.getInferOtherThings());
                latentDangerBo.setProblemDescription(ValidationUtil.isEmpty(executeParam.getProblemDescription()) ?
                        executeParam.getRemark() : executeParam.getProblemDescription());
                latentDangerBo.setReasonAnalysis(executeParam.getReasonAnalysis());
            } else if (executeTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患延期治理)) {
                latentDangerBo.setReformType(LatentDangerReformTypeEnum.延期治理.getCode().toString());
//                latentDangerBo.setReformJson(executeParam.getFlowJson().toJSONString());
//                latentDangerBo.setInferOtherThings(executeParam.getInferOtherThings());
//                latentDangerBo.setProblemDescription(executeParam.getRemark());
//                latentDangerBo.setReasonAnalysis(executeParam.getReasonAnalysis());
                latentDangerBo.setDelayLimitDate(DateUtil.str2Date(executeParam.getDelayLimitDate(), DateUtil.DATETIME_DEFAULT_FORMAT));
            }
            if (executeTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患评审通过)) {
                latentDangerBo.setReformLimitDate(DateUtil.str2Date(executeParam.getReformLimitDate(), DateUtil.DATETIME_DEFAULT_FORMAT));
                latentDangerBo.setDangerLevel(executeParam.getDangerLevel().toString());
//                JSONObject reformJsonObject = JSONObject.parseObject(latentDangerBo.getReformJson());
                JSONObject reformJsonObject = executeParam.getFlowJson();
                if (ValidationUtil.isEmpty(reformJsonObject)) {
                    reformJsonObject = new JSONObject();
                }
                reformJsonObject.put("governUserId", governUserId);
                latentDangerBo.setReformJson(reformJsonObject.toJSONString());

                // 消防巡查需求:评审通过后指定治理人
                // 2.指定治理执行人
                Object result = workflowExecuteService.setTaskAssign(latentDangerBo.getInstanceId(), governUserId);
                if (!(Boolean) result) {
                    executeSubmitDto.setIsOk(false);
                    executeSubmitDto.setMsg("设置治理行人失败");
                    return executeSubmitDto;
                }
            }
        }
        if (executeTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患延期治理车间部门审核通过)) {
            // 延期治理评审通过且 不需要 公司审核
            if (executeParam.getNeedCompanyVerify() == 0) {
                latentDangerBo.setDangerState(LatentDangerStateEnum.延期治理申请.getCode().toString());
                latentDangerBo.setReformLimitDate(latentDangerBo.getDelayLimitDate());

                if (!assignGovernUser(latentDangerBo, executeSubmitDto)) {
                    return executeSubmitDto;
                }
            } else {// 延期治理评审通过且 需要 公司审核
                latentDangerBo.setDangerState(LatentDangerStateEnum.延期治理申请待公司审核.getCode().toString());
                LatentDangerFlowRecordBo recordBo =
                        latentDangerFlowRecordMapper.getByDangerIdAndCreate(latentDangerBo.getId());
                String flowJsonStr = recordBo.getFlowJson();
                JSONObject flowJson = JSONObject.parseObject(flowJsonStr);
                flowJson.put("needCompanyVerify", executeParam.getNeedCompanyVerify());
                recordBo.setFlowJson(flowJson.toJSONString());
                latentDangerFlowRecordMapper.update(recordBo);
            }
        } else if (LatentDangerExcuteTypeEnum.隐患延期治理车间部门审核拒绝.equals(executeTypeEnum)
                || LatentDangerExcuteTypeEnum.隐患延期治理公司审核拒绝.equals(executeTypeEnum)
                || LatentDangerExcuteTypeEnum.隐患验证拒绝.equals(executeTypeEnum)) {
            latentDangerBo.setDangerState(LatentDangerStateEnum.待治理.getCode().toString());
            if (!assignGovernUser(latentDangerBo, executeSubmitDto)) {
                return executeSubmitDto;
            }

        } else if (executeTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患延期治理公司审核通过)) {
            latentDangerBo.setDangerState(LatentDangerStateEnum.延期治理申请.getCode().toString());
            latentDangerBo.setReformLimitDate(latentDangerBo.getDelayLimitDate());
            if (!assignGovernUser(latentDangerBo, executeSubmitDto)) {
                return executeSubmitDto;
            }
        } /**else if (executeTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患延期治理公司审核拒绝)) {
            // TODO 待需求确认是回到部门审核还是回到隐患治理节点
            latentDangerBo.setDangerState(LatentDangerStateEnum.延期治理申请待车间部门审核.getCode().toString());
        }**/
        latentDangerMapper.update(latentDangerBo);
        if (patrolBo != null) {
            executeSubmitDto.setPointOriginalId(patrolBo.getPointOriginalId());
            executeSubmitDto.setPointId(patrolBo.getPointId());
        }
        executeSubmitDto.setIsOk(true);
        executeSubmitDto.setExecuteTypeEnum(executeTypeEnum);
        executeSubmitDto.setDangerName(latentDangerBo.getDangerName());
        executeSubmitDto.setDangerId(latentDangerBo.getId());

        sendMessage(latentDangerBo, executeTypeEnum, patrolBo, executeTypeEnum.getName(), this.getNextExecuteUsers(latentDangerBo.getInstanceId()), userRealName, departmentName);
        return executeSubmitDto;
    }

    /**
     * 设置治理人到流程执行节点（平台人员用户名）
     *
     * @param latentDangerBo
     * @param executeSubmitDto
     * @return
     */
    public boolean assignGovernUser(LatentDangerBo latentDangerBo, DangerExecuteSubmitDto executeSubmitDto) {
        // 获取最后一次评审时选择的治理人
        LatentDangerFlowRecordBo record = latentDangerFlowRecordMapper.getByDangerIdAndActionFlag(latentDangerBo.getId(), "隐患评审");
        JSONObject recordObj = JSONObject.parseObject(record.getFlowJson());
        if (!ValidationUtil.isEmpty(recordObj.get("governUserId"))) {
            Object result = workflowExecuteService.setTaskAssign(latentDangerBo.getInstanceId(),
                    (String) recordObj.get("governUserId"));
            if (!(Boolean) result) {
                executeSubmitDto.setIsOk(false);
                executeSubmitDto.setMsg("指定治理人失败");
                return false;
            }
        }
        return true;
    }

    private void sendMessage(LatentDangerBo latentDangerBo, LatentDangerExcuteTypeEnum excuteTypeEnum,
                             LatentDangerPatrolBo patrolBo, String flowTaskName, String informerList,
                             String userRealName, String departmentName) {
        try {
            if (excuteTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患评审拒绝)) {
                String pointName = null;
                if (patrolBo != null) {
                    pointName = patrolBo.getPointName();
                }
                Set<String> sendUserIds = Sets.newHashSet(latentDangerBo.getDiscovererUserId());
                asyncTask.pushLatentDangerExecuteMessage(informerList, latentDangerBo.getOrgCode(),
                                                         latentDangerBo.getDangerName(), pointName,
                                                         departmentName, latentDangerBo.getId(), latentDangerBo.getInstanceId(), userRealName,
                                                         flowTaskName, ExecuteStateEnum.驳回.getName(),
                                                         DateUtil.date2Str(new Date(), DateUtil.DATETIME_DEFAULT_FORMAT),
                                                         Integer.parseInt(latentDangerBo.getDangerState()));
            } else if (excuteTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患验证通过)) {
                if (patrolBo != null) {
                    // 更新p_check_input表state字段
                    updateCheckInputDangerState(latentDangerBo.getBizId(), DangerHandleStateEnum.COMPLETED.getCode());
                    DangerResultBo dangerResultBo = new DangerResultBo();
                    try {
                        business.processProtalDataFromDanger(dangerResultBo);
                    } catch (Exception e) {
                        throw new RuntimeException("隐患治理完成调用站端接口出错！");
                    }
                }
            } else {
                String pointName = null;
                if (patrolBo != null) {
                    pointName = patrolBo.getPointName();
                }
                asyncTask.pushLatentDangerExecuteMessage(informerList, latentDangerBo.getOrgCode(),
                                                         latentDangerBo.getDangerName(), pointName,
                                                         departmentName, latentDangerBo.getId(), latentDangerBo.getInstanceId(), userRealName,
                                                         flowTaskName, excuteTypeEnum.getExcuteState().getName(),
                                                         DateUtil.date2Str(new Date(), DateUtil.DATETIME_DEFAULT_FORMAT),
                                                         Integer.parseInt(latentDangerBo.getDangerState()));
                if (excuteTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患评审通过)) {
                    // 隐患治理到期时间为当天，则立即提示消息
                    Date reformLimitDate = latentDangerBo.getReformLimitDate();
                    if (DateUtil.getDateFormat(new Date()).equals(DateUtil.getDateFormat(reformLimitDate))) {
                        asyncTask.pushLatentDangerReformLimitDateExpireMessage(informerList,
                                                                               latentDangerBo.getOrgCode(), latentDangerBo.getDangerName(),
                                                                               DateUtil.date2Str(latentDangerBo.getReformLimitDate(), DateUtil.DATETIME_DEFAULT_FORMAT),
                                                                               latentDangerBo.getId(),
                                                                               latentDangerBo.getInstanceId(),
                                                                               Integer.parseInt(latentDangerBo.getDangerState()),userRealName);
                    }
                }
            }
        } catch (Exception e) {
            logger.error("隐患执行发送消息失败", e);
        }
    }

    private void updateSpcStateToControl(LatentDangerPatrolBo patrolBo, LatentDangerBo latentDangerBo) {
        if (patrolBo.getClassifyOriginalId() != null && patrolBo.getItemOriginalId() != null) {
            updateMeasuresContentStatus(Long.valueOf(patrolBo.getClassifyOriginalId()), Long.valueOf(patrolBo.getItemOriginalId()),
                                        patrolBo.getRiskFactorFlowId(), RiskFactorsCmStatusEnum.Control);
        }
        LatentDangerLevelEnum levelEnum = LatentDangerLevelEnum.getByCode(latentDangerBo.getDangerLevel());
        if (levelEnum != null) {
            updateRiskSourceDangerState(false, Long.valueOf(patrolBo.getPointOriginalId()), levelEnum, patrolBo.getPointId(), latentDangerBo.getId());
        }
    }

//    private void wakeUpRiskFactorFlow(LatentDangerPatrolBo patrolBo, String token) {
//        Integer notFinishFlow = latentDangerMapper.countNotFinishByFlowId(patrolBo.getRiskFactorFlowId());
//        if (notFinishFlow == 0) {
//            logger.info("解冻原来的A流程");
//            //解冻原来的A流程
//            remoteSpcService.wakeUpOrRestartRiskFactorFlow(patrolBo.getRiskFactorFlowId(), WorkFlowRiskFactorUriEnum.流程回调, token, RiskFactorWorkFlowActionTypeEnum.唤起流程);
//        }
//    }

    @Async
    @Override
    public void sendLatentDangerExcuteResult(DangerExecuteSubmitDto executeSubmitDto) {
        LatentDangerExcuteTypeEnum excuteTypeEnum = executeSubmitDto.getExecuteTypeEnum();
        String dangerName = executeSubmitDto.getDangerName();
        String pointOriginalId = executeSubmitDto.getPointOriginalId();
        Long pointId = executeSubmitDto.getPointId();
        String status = null;
        if (excuteTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患评审通过)) {
            status = "隐患评审通过";
        } else if (excuteTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患评审拒绝)) {
            status = "隐患评审不通过";
        } else if (excuteTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患验证拒绝)) {
            status = "治理验证不通过";
        } else if (excuteTypeEnum.equals(LatentDangerExcuteTypeEnum.隐患验证通过)) {
            status = "治理验证完成";
        }
        if (status != null) {
            LatentDangerResultPushSpcRequest spcRequest = new LatentDangerResultPushSpcRequest();
            spcRequest.setProcessingTime(DateUtil.date2Str(new Date(), DateUtil.DATETIME_DEFAULT_FORMAT));
            spcRequest.setHiddenTroubleName(dangerName);
            spcRequest.setRiskSourceId(pointOriginalId);
            spcRequest.setHiddenTroubleStatus(status);
            spcRequest.setTroubleList(getTroubleList(pointId));
            remoteSpcService.pushLatentDangerExcuteResult(spcRequest);
        }
    }

    private List<String> getTroubleList(Long pointId) {
        List<String> troubleList = Lists.newArrayList();
        List<LatentDangerPatrolBo> patrolList = latentDangerPatrolMapper.listByPointId(pointId);
        if (!CollectionUtils.isEmpty(patrolList)) {
            List<Long> dangerIds = Lists.transform(patrolList, LatentDangerPatrolBo::getLatentDangerId);
            List<LatentDangerFlowRecordBo> flowRecordBos = latentDangerFlowRecordMapper.listNewestRecordByDangerIds(dangerIds);
            flowRecordBos.forEach(l -> {
                String status = null;
                if (l.getDangerState().equals(LatentDangerStateEnum.待治理.getCode())
                        && l.getDangerOvertimeState().equals(LatentDangerOvertimeStateEnum.已超时.getCode())) {
                    status = "治理逾期";
                } else {
                    if (l.getExecuteResult().equals(LatentDangerExcuteTypeEnum.隐患评审通过.getName())) {
                        status = "隐患评审通过";
                    } else if (l.getExecuteResult().equals(LatentDangerExcuteTypeEnum.隐患评审拒绝.getName())) {
                        status = "隐患评审不通过";
                    } else if (l.getExecuteResult().equals(LatentDangerExcuteTypeEnum.隐患验证拒绝.getName())) {
                        status = "治理验证不通过";
                    } else if (l.getExecuteResult().equals(LatentDangerExcuteTypeEnum.隐患验证通过.getName())) {
                        status = "治理验证完成";
                    }
                }
                if (status != null) {
                    troubleList.add(status);
                }
            });
        }
        return troubleList;
    }

    private void updateRiskSourceDangerState(Boolean isSave, Long riskSourceId, LatentDangerLevelEnum
            levelEnum, Long pointId, Long dangerId) {
        RiskSourceBo riskSourceBo = riskSourceMapper.getById(riskSourceId);
        if (riskSourceBo != null) {
            if (isSave) {
                //添加隐患
                riskSourceBo.setIsDanger(true);
                if (riskSourceBo.getDangerLevel() == null) {
                    riskSourceBo.setDangerLevel(levelEnum.getRiskSourceDangerLevelCode());
                } else {
//                    if (riskSourceBo.getDangerLevel().equals(LatentDangerLevelEnum.一般隐患.getRiskSourceDangerLevelCode())
//                            && levelEnum.equals(LatentDangerLevelEnum.重大隐患)) {
//                        riskSourceBo.setDangerLevel(levelEnum.getRiskSourceDangerLevelCode());
//                    }
                    if (Integer.parseInt(riskSourceBo.getDangerLevel()) < Integer.parseInt(levelEnum.getRiskSourceDangerLevelCode())) {
                        riskSourceBo.setDangerLevel(levelEnum.getRiskSourceDangerLevelCode());
                    }
                }
            } else {
                //撤销、完成隐患
                HashMap<String, Object> params = new HashMap<>();
                params.put("pointId", pointId);
                params.put("dangerId", dangerId);
                List<LatentDangerBo> latentDangerBos = latentDangerMapper.listNotFinishByPointId(params);
                if (CollectionUtils.isEmpty(latentDangerBos)) {
                    riskSourceBo.setIsDanger(false);
                } else {
                    riskSourceBo.setIsDanger(true);
                    String dangerLevel = checkHasSeriousDanger(latentDangerBos);
                    riskSourceBo.setDangerLevel(dangerLevel);
                }
            }
            riskSourceMapper.updateDangerState(riskSourceBo);
        }
    }

    private String checkHasSeriousDanger(List<LatentDangerBo> latentDangerBos) {
        String dangerLevel = LatentDangerLevelEnum.安全问题.getRiskSourceDangerLevelCode();
        for (LatentDangerBo latentDangerBo : latentDangerBos) {
//            if (latentDangerBo.getDangerLevel().equals(LatentDangerLevelEnum.重大隐患.getCode())) {
//                return LatentDangerLevelEnum.重大隐患.getRiskSourceDangerLevelCode();
//            }
        }
        int code = latentDangerBos.stream().mapToInt(this::toIntFun).max().getAsInt();
        dangerLevel = LatentDangerLevelEnum.getByCode(code).getRiskSourceDangerLevelCode();
        return dangerLevel;
    }

    public Integer toIntFun(LatentDangerBo dangerBo) {
        return Integer.parseInt(dangerBo.getDangerLevel());
    }

    @Override
    public void freshRiskJudgmentLangerCount(LatentDangerExcuteParam latentDangerExcuteParam) {
        Long currentFlowRecordId = latentDangerExcuteParam.getFlowRecordId();
        LatentDangerFlowRecordBo currentRecord = latentDangerFlowRecordMapper.getById(currentFlowRecordId);
        if (currentRecord == null) {
            return;
        }
        LatentDangerBo latentDangerBo = latentDangerMapper.getById(currentRecord.getDangerId());
        if (latentDangerBo == null) {
            return;
        }
        LatentDangerPatrolBo patrolBo = latentDangerPatrolMapper.getByDangerId(latentDangerBo.getId());
        if (patrolBo != null && StringUtil.isNotEmpty(patrolBo.getPointOriginalId())) {
            iRiskJudgmentTaskService.freshRiskJudgmentLangerCount(Long.parseLong(patrolBo.getPointOriginalId()));
        }
    }

    @Override
    public Object getDangerLevel(String token, String product, String appKey, String dictCode) {
        JSONArray jsonArray = remoteSecurityService.listDictionaryByDictCode(token, product, appKey, dictCode);
        return jsonArray;
    }

    @Override
    public JSONObject getDangerLevelJsonObject(String dangerLevelStr, String token, String product, String appKey, String dictCode) {
        JSONArray dangerLevelList = (JSONArray) this.getDangerLevel(token, product, appKey, dictCode);
        JSONObject dangerLevel = new JSONObject();
        List<Object> objs =
                dangerLevelList.stream().filter(level -> ((JSONObject) level).get("dictDataKey").equals(dangerLevelStr)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(objs)) {
            dangerLevel = (JSONObject) objs.get(0);
        }
        return dangerLevel;
    }

    @Override
    public JSONObject getReviewInfo(Long dangerId) {
        List<HashMap<String, Object>> result = latentDangerMapper.getReViewInfo(dangerId);
        Set<String> userIdSet = Sets.newHashSet();
        result.forEach(r -> {
            userIdSet.add((String) r.get("executeUserId"));
            if (StringUtil.isNotEmpty(r.get("handleUserIds"))) {
                List<String> handleUserIds = Arrays.asList(r.get("handleUserIds").toString().split(","));
                userIdSet.addAll(handleUserIds);
            }
        });
        userIdSet.removeAll(Collections.singleton(null));

        List<AgencyUserModel> userModels = remoteSecurityService.listUserByUserIds(Joiner.on(",").join(userIdSet));
        if (StringUtil.isNotEmpty(userModels)) {
            Map<String, AgencyUserModel> userMap = Maps.uniqueIndex(userModels, AgencyUserModel::getUserId);
            result.forEach(r -> {
                r.put("executeUserName", StringUtil.isNotEmpty(r.get("executeUserId")) ? userMap.get(r.get(
                        "executeUserId")).getRealName() : "");
                List<String> handleUserNames = Lists.newArrayList();
                if (StringUtil.isNotEmpty(r.get("handleUserIds"))) {
                    List<String> handleUserIds = Arrays.asList(r.get("handleUserIds").toString().split(","));
                    handleUserIds.forEach(id -> handleUserNames.add(userMap.get(id).getRealName()));
                }
                r.put("handleUserName", Joiner.on(",").join(handleUserNames));
            });
        }
        JSONObject resultObjJson = new JSONObject();
        result.forEach(r -> {
            r.put("flowJson", JSON.parseObject((String) r.get("flowJson")));
            resultObjJson.put((String) r.get("actionFlag"), JSONObject.toJSON(r));
        });
        return resultObjJson;
    }

    @Override
    public Page<DangerListResponse> listDanger(PageParam pageParam) {
        String idsStr = (String) pageParam.get("dangerIds");
        if (StringUtil.isNotEmpty(idsStr)) {
            List<String> dangerIdList = Lists.newArrayList(idsStr.split(","));
            pageParam.put("dangerIds", dangerIdList);
        }
        if (StringUtil.isNotEmpty(pageParam.get("pageNumber")) && StringUtil.isNotEmpty(pageParam.get("pageSize"))) {
            int offSet = (int) pageParam.get("pageNumber") * (int) pageParam.get("pageSize");
            pageParam.put("offset", offSet);
        }
        // 获取隐患地点的子节点
        Object structureId = pageParam.get("structureId");
        List<Long> structureIdList = null;
        if (structureId != null && structureId.toString().trim().length() > 0) {
            LinkedHashMap<String,Object> o = equipFeign.getBuildingTree();
            if(o==null||!"200".equals(o.get("status").toString())) {
                throw new YeeException("获取建筑树出错");
            }
            List<Map<String, Object>> buildingTree = (List<Map<String, Object>>) o.get("result");
            Map<String, Object> node = getAllNodes(buildingTree).stream().filter(map -> structureId.equals(map.get("id"))).findFirst().orElse(null);
            if (node != null) {
                structureIdList = findBuildChildrenIds(node);
            }
        }
        pageParam.put("structureId", structureIdList);
        List<DangerListResponse> dangerListResponseList = latentDangerMapper.dangerListByMap(pageParam);
        Map<Long, String> buildingAbsolutePositionMap = new HashMap<>();
        try {
            LinkedHashMap<String, Object> buildingAbsolutePosition = equipFeign.getBuildingAbsolutePosition();
            if (buildingAbsolutePosition == null || !"200".equals(buildingAbsolutePosition.get("status").toString())) {
                throw new YeeException("获取建筑树出错");
            }
            buildingAbsolutePositionMap = (Map<Long, String>) buildingAbsolutePosition.get("result");
        } catch (Exception e) {
        }
        if (!dangerListResponseList.isEmpty()) {
            Map<Long, String> finalBuildingAbsolutePositionMap = buildingAbsolutePositionMap;
            dangerListResponseList.forEach(danger->danger.setStructureName(finalBuildingAbsolutePositionMap.get(danger.getStructureId())));
        }
        Long count = latentDangerMapper.countDangerListByMap(pageParam);
        if (CollectionUtils.isEmpty(dangerListResponseList)) {
            return new PageImpl<>(dangerListResponseList, pageParam, 0L);
        }
        return new PageImpl<>(dangerList(dangerListResponseList), pageParam, count);
    }

    private List<Map<String, Object>> getAllNodes(List<Map<String, Object>> buildingTree) {
        List<Map<String, Object>> res = new LinkedList<>();
        if (buildingTree != null && !buildingTree.isEmpty()) {
            res.addAll(buildingTree);
            buildingTree.forEach(building -> {
                List<Map<String, Object>> childrenTree = (List<Map<String, Object>>) building.get("children");
                res.addAll(getAllNodes(childrenTree));
            });
        }
        return res;
    }

    private List<Long> findBuildChildrenIds(Map<String, Object> building) {
        List<Map<String, Object>> buildingTree = getAllNodes(Collections.singletonList(building));
        return buildingTree.stream().map(building123 -> Long.valueOf(building123.get("id").toString())).collect(Collectors.toList());
    }

    @Override
    public List<DangerListResponse> export(PageParam pageParam) {
        String idsStr = (String) pageParam.get("dangerIds");
        if (StringUtil.isNotEmpty(idsStr)) {
            List<String> dangerIdList = Lists.newArrayList(idsStr.split(","));
            pageParam.put("dangerIds", dangerIdList);
        }
        List<DangerListResponse> dangerListResponseList = latentDangerMapper.dangerListByMap(pageParam);
        return dangerList(dangerListResponseList);
    }

    @Override
    public List<DangerTimeAxisVo> queryExecuteLog(Integer dateTime) {
        Map<String, Object> param = new HashMap<>();
//        String endTime = com.yeejoin.amos.patrol.core.util.DateUtil.getShortCurrentDate();
        String beginTime = "";
        if (dateTime != null && dateTime == 7) {
            beginTime = com.yeejoin.amos.patrol.core.util.DateUtil.getIntervalDateStr(new Date(), -7, "yyyy-MM-dd");
        } else if (dateTime != null && dateTime == 30) {
            beginTime = com.yeejoin.amos.patrol.core.util.DateUtil.getIntervalDateStr(new Date(), -30, "yyyy-MM-dd");
        } else {
            beginTime = com.yeejoin.amos.patrol.core.util.DateUtil.getShortCurrentDate();
        }
        param.put("beginTime", beginTime + " 00:00:00");
//        param.put("endTime",endTime + " 23:59:59");
        List<DangerTimeAxisVo> list = latentDangerFlowRecordMapper.listExecuteLog(param);
        String d;
        if (0 < list.size()) {
            for (DangerTimeAxisVo vo : list) {
                AgencyUserModel userModel = remoteSecurityService.getUserById(RequestContext.getToken(), getProduct(), RequestContext.getAppKey(), vo.getExecuteUserId().toString());
                vo.setUserName(userModel.getRealName());
                vo.setDangerState(LatentDangerStateEnum.getEnumName(Integer.valueOf(vo.getDangerState())));
                vo.setXAxis(null == vo.getUpdateDate() ? DateUtil.getDateFormat(new Date(), DateUtil.DATETIME_DEFAULT_FORMAT) : DateUtil.getDateFormat(vo.getUpdateDate(), DateUtil.DATETIME_DEFAULT_FORMAT));
                vo.setRow1(vo.getUserName() + "-" + vo.getDangerState() + "-" + vo.getDangerName());
                if ("3".equals(vo.getReformType())) {
                    d = null == vo.getDelayLimitDate() ? "无" : DateUtil.getDateFormat(vo.getDelayLimitDate(), DateUtil.DATETIME_DEFAULT_FORMAT);
                } else {
                    d = null == vo.getReformLimitDate() ? "无" : DateUtil.getDateFormat(vo.getReformLimitDate(), DateUtil.DATETIME_DEFAULT_FORMAT);
                }
                vo.setRow2(vo.getStructureName() + "-" + d);
            }
        }
        return list;
    }

    private List<DangerListResponse> dangerList(List<DangerListResponse> dangerListResponseList) {
        JSONArray array = remoteSecurityService.listDictionaryByDictCode(RequestContext.getToken(), getProduct(), RequestContext.getAppKey(),
                                                                         DictTypeEnum.DANGERLEVEL.getCode());
        List<DictBo> dangerLevelList = JSONArray.parseArray(array.toJSONString(), DictBo.class);
        for (DangerListResponse e : dangerListResponseList) {
            e.setDangerState(LatentDangerStateEnum.getEnumName(Integer.valueOf(e.getDangerState())));
            DictBo dangerLevel =
                    dangerLevelList.stream().filter(item -> item.getDictDataKey().equals(e.getDangerLevel())).collect(Collectors.toList()).get(0);
            e.setDangerLevel(dangerLevel.getDictDataValue());
            e.setReformType(!StringUtil.isNotEmpty(e.getReformType()) ? "" :
                                    LatentDangerReformTypeEnum.getByCode(Integer.valueOf(e.getReformType())).getName());
            e.setOvertimeState("0".equals(e.getOvertimeState()) ? "否" : "是");
            e.setDangerTypeName(LatentDangerTypeEnum.getEnumName(Integer.valueOf(e.getDangerType())));
            e.setDeadline(null == e.getDeadlineDate() ? "" : DateUtil.getLongDate(e.getDeadlineDate()));
        }
        return dangerListResponseList;
    }

    //获取下一节点需要发消息的用户信息
    public  String getNextExecuteUsers(String  instanceId) {
        String informerList= "";
        JSONObject object =  remoteWorkFlowService.getChildNodeDetail(instanceId);
        if(object!=null){
            JSONArray array  = object.getJSONArray("data");
            if(array.size()>0){
                JSONObject workFlowDetail = array.getJSONObject(0);
                informerList =  workFlowDetail.getString("informerList");
            }
        }
        return informerList;
    }

    @Override
    public String queryTaskByInstanceId(String processInstanceId) {
        String taskId = null;
                JSONObject taskJson = remoteWorkFlowService.queryTask(processInstanceId);
        if (null != taskJson) {
            if (ValidationUtil.isEmpty(taskJson.get("data"))) {
                return null;
            }
            JSONObject dataJson = (JSONObject) taskJson.get("data");
            taskId = (String) dataJson.get("id");
        }
        return taskId;
    }

    @Override
    public List<Map<String, Object>> getPersonListByCompanyId() {
        List<Map<String, Object>> personList = jcsFeignClient.getPersonListByCompanyId(emergencyCommandSectionId).getResult();
        return personList;
    }
}
