package com.yeejoin.amos.boot.module.jg.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
import com.yeejoin.amos.boot.module.common.api.dao.ESEquipmentCategory;
import com.yeejoin.amos.boot.module.common.api.dto.ESEquipmentCategoryDto;
import com.yeejoin.amos.boot.module.common.api.service.ICompensateFlowDataOfRedis;
import com.yeejoin.amos.boot.module.common.biz.refresh.DataRefreshEvent;
import com.yeejoin.amos.boot.module.jg.api.dto.*;
import com.yeejoin.amos.boot.module.jg.api.entity.JgEnableDisable;
import com.yeejoin.amos.boot.module.jg.api.entity.JgEnableDisableEq;
import com.yeejoin.amos.boot.module.jg.api.entity.JgRegistrationHistory;
import com.yeejoin.amos.boot.module.jg.api.entity.JgUseRegistrationManage;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.CertificateStatusEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.CompanyTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgEnableDisableEqMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgEnableDisableMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgRegistrationHistoryMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgUseRegistrationManageMapper;
import com.yeejoin.amos.boot.module.jg.api.service.IJgEnableDisableService;
import com.yeejoin.amos.boot.module.jg.api.vo.SortVo;
import com.yeejoin.amos.boot.module.jg.biz.config.LocalBadRequest;
import com.yeejoin.amos.boot.module.jg.biz.context.EquipUsedCheckStrategyContext;
import com.yeejoin.amos.boot.module.jg.biz.context.FlowingEquipRedisContext;
import com.yeejoin.amos.boot.module.jg.biz.edit.permission.FillingEditPermForCurrentUser;
import com.yeejoin.amos.boot.module.jg.biz.edit.utils.JsonDiffUtil;
import com.yeejoin.amos.boot.module.jg.biz.event.publisher.EventPublisher;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.ICmWorkflowService;
import com.yeejoin.amos.boot.module.ymt.api.dto.IdxBizJgProjectContraptionDto;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgInspectionDetectionInfo;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgProjectContraption;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgUseInfo;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquipmentEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquipmentClassifityEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.IdxBizJgProjectContraptionMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.IdxBizJgUseInfoMapper;
import com.yeejoin.amos.feign.systemctl.model.TaskV2Model;
import com.yeejoin.amos.feign.workflow.Workflow;
import com.yeejoin.amos.feign.workflow.model.*;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.rdbms.service.BaseService;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toSet;

/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2023-12-25
 */
@Service
public class JgEnableDisableServiceImpl extends BaseService<JgEnableDisableDto, JgEnableDisable, JgEnableDisableMapper> implements IJgEnableDisableService, ICompensateFlowDataOfRedis<JgEnableDisable> {


    @Autowired
    JgEnableDisableEqServiceImpl jgEnableDisableEqService;

    @Autowired
    JgEnableDisableEqMapper jgEnableDisableEqMapper;

    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;

    @Autowired
    JgResumeInfoServiceImpl jgResumeInfoService;

    @Autowired
    private CommonServiceImpl commonService;

    @Autowired
    ICmWorkflowService iCmWorkflowService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private IdxBizJgUseInfoMapper idxBizJgUseInfoMapper;

    @Autowired
    private JgRegistrationHistoryMapper jgRegistrationHistoryMapper;

    @Autowired
    private SnowflakeIdUtil sequence;

    @Autowired
    private IdxBizJgInspectionDetectionInfoServiceImpl jgInspectionDetectionInfoService;

    @Autowired
    private JgUseRegistrationManageMapper jgUseRegistrationManageMapper;

    @Autowired
    private JgUseRegistrationManageServiceImpl useRegistrationManageService;

    @Autowired
    private EventPublisher eventPublisher;

    @Autowired
    private IdxBizJgProjectContraptionMapper jgProjectContraptionMapper;

    @Autowired
    private ESEquipmentCategory esEquipmentCategory;

    private final List<String> NOT_FLOWING_STATE = Collections.unmodifiableList(Arrays.asList("待提交", "已驳回", "已撤回", "已作废", "已完成"));

    private final String PROCESS_DEFINITION_KEY = "deactivateEnable";

    private static final String SUBMIT_TYPE_FLOW = "1";


    @Transactional(rollbackFor = Exception.class)
    public List<JgEnableDisable> saveOrUpdate(JSONObject map, ReginParams reginParams) {
        try {
            JgEnableDisable jgEnableDisable = new JgEnableDisable();
            if (org.apache.commons.lang3.StringUtils.isNotEmpty(map.getString("sequenceNbr"))) {
                jgEnableDisable = this.baseMapper.selectById(String.valueOf(map.get("sequenceNbr")));
                jgEnableDisable.setRemark(map.get("remark").toString());
            } else {
                // 获取申请编号
                ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.getCode.get(String.valueOf(map.get("businessCode"))), 1);
                jgEnableDisable.setApplyNo(listResponseModel.getResult().get(0));
                jgEnableDisable.setSequenceNbr(sequence.nextId());
            }
            jgEnableDisable.setCreateDate(new Date());
            String submit = String.valueOf(map.get("submit"));
            String pageType = String.valueOf(map.get("formType"));
            String equListCode = map.getString("equListCode");
            // 设备列表
            List<Map<String, Object>> equipments = (List<Map<String, Object>>) map.get("equipments");
            if (SUBMIT_TYPE_FLOW.equals(submit)) {// 校验设备不能再多个流程中
                CompanyBo company = reginParams.getCompany();
                this.repeatUsedEquipCheck(equipments,
                        CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ?
                                company.getCompanyCode().split("_")[1] :
                                company.getCompanyCode(), equListCode);
            }
            String businessCode = ObjectUtils.isEmpty(map.get("applyType")) ? String.valueOf(map.get("businessCode")) : String.valueOf(map.get("applyType"));
            // 接收机构
            String[] receiveOrgCode = String.valueOf(map.getString("receiveOrgCode")).split("_");
            List<WorkflowResultDto> workflowResultList = new ArrayList<>();

            WorkflowResultDto workflowResultDto = new WorkflowResultDto();
            List<ProcessTaskDTO> processTaskDTOS = new ArrayList<>();
            jgEnableDisable.setOtherAccessories(JSONObject.toJSONString(Optional.ofNullable(map.get("otherAccessories")).orElse(Collections.emptyMap())));

            if (SUBMIT_TYPE_FLOW.equals(submit)) {
                if (map.containsKey("instanceId") && !ObjectUtils.isEmpty(map.get("instanceId"))) {
                    String instanceId = String.valueOf(map.get("instanceId"));
                    LambdaQueryWrapper<JgEnableDisable> queryWrapper = new LambdaQueryWrapper<JgEnableDisable>().eq(JgEnableDisable::getInstanceId, instanceId);
                    JgEnableDisable jgEnableDisable1 = this.baseMapper.selectOne(queryWrapper);
                    BeanUtils.copyProperties(jgEnableDisable1, jgEnableDisable);
                    // 只调用执行API，返回下个节点信息，用于填充业务字段
                    // 组装信息
                    TaskResultDTO dto = new TaskResultDTO();
                    dto.setResultCode("approvalStatus");
                    dto.setTaskId(jgEnableDisable.getNextTaskId());
                    HashMap<String, Object> commMap = new HashMap<>();
                    if (FlowStatusEnum.REJECTED.getName().equals(jgEnableDisable.getAuditStatus()) || FlowStatusEnum.ROLLBACK.getName().equals(jgEnableDisable.getAuditStatus())) {
                        commMap.put("approvalStatus", "提交");
                        // 下一节点执行人单位（下节点接收机构code）
                        dto.setNextExecuteUserCompanyCode(jgEnableDisable.getReceiveCompanyCode());
                    } else {
                        commMap.put("approvalStatus", submit);
                        // 下一节点执行人单位（下节点接收机构code）
                        dto.setNextExecuteUserCompanyCode(jgEnableDisable.getUseUnitCreditCode());
                    }

                    dto.setVariable(commMap);
                    ProcessTaskDTO processTaskDTO = iCmWorkflowService.completeOrReject(jgEnableDisable.getNextTaskId(), dto, "0");
                    processTaskDTOS.add(processTaskDTO);
                    // 提取节点等信息
                    workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
                    workflowResultList.add(workflowResultDto);
                    if (!ObjectUtils.isEmpty(jgEnableDisable.getExecuteSequence())) {
                        jgEnableDisable.setExecuteSequence(jgEnableDisable.getExecuteSequence() + "," + workflowResultDto.getNextExecutorRoleIds());
                    } else {
                        jgEnableDisable.setExecuteSequence(workflowResultDto.getNextExecutorRoleIds());
                    }
                    jgEnableDisable.setPromoter(RequestContext.getExeUserId());
                    jgEnableDisable.setNextExecutorIds(String.join(",", workflowResultDto.getNextExecutorRoleIds()));
                    jgEnableDisable.setAuditStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getName()));
                    jgEnableDisable.setNextTaskId(workflowResultDto.getNextTaskId());
                    jgEnableDisable.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                    this.baseMapper.updateById(jgEnableDisable);
                    // 上个代办改为已办
                    HashMap<String, Object> map1 = new HashMap<>();
                    map1.put("taskStatus", FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    map1.put("taskStatusLabel", FlowStatusEnum.TO_BE_PROCESSED.getName());
                    map1.put("relationId", jgEnableDisable.getInstanceId());
                    map1.put("flowStatus", FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    map1.put("flowStatusLabel", FlowStatusEnum.TO_BE_PROCESSED.getName());
                    TaskV2Model taskV2Model = commonService.updateTaskModel(map1);
                    if (ObjectUtils.isEmpty(taskV2Model)) {
                        TaskModelDto taskModelDto = new TaskModelDto();
                        BeanUtils.copyProperties(taskV2Model, taskModelDto);
                        // 创建新的代办
                        TaskMessageDto taskMessageDto = new TaskMessageDto();
                        BeanUtils.copyProperties(jgEnableDisable, taskMessageDto);
                        taskModelDto.setModel(taskMessageDto);
                        taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
                        taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                        taskModelDto.setFlowStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
                        taskModelDto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                        taskModelDto.setFlowCode(jgEnableDisable.getNextTaskId());
                        taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
                        commonService.buildTaskModel(Collections.singletonList(taskModelDto));
                    }
                } else {
                    // 启用 选择的设备中有超过定期检验有效期的设备，下次检验日期在当前时间之前的，提示:启用的设备中存在超过定期检验有效期的设备。，不能继续下一步。
                    if (ApplicationFormTypeEnum.SBQY.getBusinessCode().equals(map.getString("applyType"))) {
                        if (!EquipmentClassifityEnum.YLGD.getCode().equals(equListCode)) {
                            List<String> record = equipments.stream().map(equ -> String.valueOf(equ.get("record"))).collect(Collectors.toList());
                            List<IdxBizJgInspectionDetectionInfo> inspectInfos = jgInspectionDetectionInfoService.checkInspectionInfo(record);
                            List<Date> nextInspectDates = inspectInfos.stream().map(IdxBizJgInspectionDetectionInfo::getNextInspectDate).collect(Collectors.toList());
                            Date currentDate = new Date();
                            nextInspectDates.stream().filter(Objects::nonNull).forEach(next -> {
                                // 下次检验日期在当前时间之前的
                                if (next.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()
                                        .isBefore(currentDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate())) {
                                    throw new BadRequest("启用的设备中存在超过定期检验有效期的设备");
                                }
                            });
                        }
                    }

                    // 启动工作流并返回信息
                    workflowResultList = workFlowInfo(submit, jgEnableDisable, receiveOrgCode[0]);
                    // 业务数据组装等
                    businessData(submit, reginParams, jgEnableDisable, map, equipments, workflowResultList);
                }

                commonService.saveExecuteFlowData2Redis(jgEnableDisable.getInstanceId(), buildInstanceRuntimeData(jgEnableDisable));
            } else {
                jgEnableDisable.setNextExecuteUserIds(reginParams.getUserModel().getUserId());
                jgEnableDisable.setCreateUserId(reginParams.getUserModel().getUserId());
                jgEnableDisable.setCreateUserName(reginParams.getUserModel().getRealName());
                jgEnableDisable.setUseUnitCreditCode(CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                        reginParams.getCompany().getCompanyCode().split("_")[1] :
                        reginParams.getCompany().getCompanyCode());
                jgEnableDisable.setUseUnitName(reginParams.getCompany().getCompanyName());
                jgEnableDisable.setReceiveCompanyCode(receiveOrgCode[0]);
                jgEnableDisable.setReceiveOrgName(receiveOrgCode[1]);
                jgEnableDisable.setEquListCode(equListCode);
                jgEnableDisable.setEquListName(EquipmentClassifityEnum.getNameByCode(equListCode));
                setCertInfoByEquList(map, jgEnableDisable);
                jgEnableDisable.setRemark(map.getString("remark"));
                jgEnableDisable.setApplyDate(new Date());
                jgEnableDisable.setApplyType(String.valueOf(map.get("applyType")));
                jgEnableDisable.setAuditStatus(ObjectUtils.isEmpty(jgEnableDisable.getAuditStatus()) ? FlowStatusEnum.TO_BE_SUBMITTED.getName() : jgEnableDisable.getAuditStatus());
            }
            // 仅保存
            this.saveOrUpdate(jgEnableDisable);
            if ("add".equals(pageType)) {
                buildTask(Arrays.asList(jgEnableDisable), businessCode, workflowResultList, Boolean.FALSE);
            } else {
                // 编辑
                this.baseMapper.updateById(jgEnableDisable);
                LambdaQueryWrapper<JgEnableDisableEq> wrapper = new LambdaQueryWrapper<JgEnableDisableEq>().eq(JgEnableDisableEq::getEnableDisableApplyId, jgEnableDisable.getSequenceNbr().toString());
                jgEnableDisableEqService.getBaseMapper().delete(wrapper);
                // 关联设备表
                for (Map<String, Object> equipment : equipments) {
                    JgEnableDisableEq jgEnableDisableEq = new JgEnableDisableEq();
                    jgEnableDisableEq.setEquId(String.valueOf(equipment.get(this.getRecordKey(jgEnableDisable))));
                    jgEnableDisableEq.setEnableDisableApplyId(jgEnableDisable.getSequenceNbr().toString());
                    jgEnableDisableEqService.saveOrUpdate(jgEnableDisableEq);
                }
            }
            if (!SUBMIT_TYPE_FLOW.equals(submit)) {
                // 暂存任务
                buildTaskDraft(jgEnableDisable);
            } else {
                buildTask(Collections.singletonList(jgEnableDisable), businessCode, workflowResultList, Boolean.TRUE);
            }
            // 保存历史表
            commonService.saveOrUpdateHistory(this.getRegistrationClass(jgEnableDisable), map, null, jgEnableDisable.getSequenceNbr().toString());
            // 前端显示需要将code转name
            jgEnableDisable.setApplyType(getRegistrationClass(jgEnableDisable));
            return Collections.singletonList(jgEnableDisable);
        } catch (BadRequest | LocalBadRequest e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw new BadRequest("保存失败！");
        } finally {
            FlowingEquipRedisContext.clean();
        }
    }

    private void setCertInfoByEquList(JSONObject map, JgEnableDisable jgEnableDisable) {
        if (!EquipmentClassifityEnum.YLGD.getCode().equals(jgEnableDisable.getEquListCode())) {
            // 使用登记证相关
            List<String> certificates = (List<String>) map.get("sequenceNbrs");
            LambdaQueryWrapper<JgUseRegistrationManage> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.in(JgUseRegistrationManage::getSequenceNbr, certificates.stream().map(Long::parseLong).collect(Collectors.toList()));
            lambdaQueryWrapper.select(JgUseRegistrationManage::getUseRegistrationCode);
            List<JgUseRegistrationManage> jgUseRegistrationManageList = jgUseRegistrationManageMapper.selectList(lambdaQueryWrapper);
            jgEnableDisable.setRegistrationManageId(String.join(",", certificates));
            jgEnableDisable.setUseRegistrationCode(jgUseRegistrationManageList.stream().map(JgUseRegistrationManage::getUseRegistrationCode).collect(Collectors.joining(",")));
        } else {
            jgEnableDisable.setUseRegistrationCode(map.getString("useRegistrationCode"));
            jgEnableDisable.setProjectContraptionId(map.getString("projectContraptionId"));
        }
    }

    private void repeatUsedEquipCheck(List<Map<String, Object>> equipList, String companyCode, String equListCode) {
        equipList.forEach(equipMap -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                .equipRepeatUsedCheck(String.valueOf(equipMap.get(this.getRecordKey(equListCode))), companyCode));
    }

    /**
     * 删除 redis校验重复引用设备的数据
     */
    private void delRepeatUseEquipData(JgEnableDisable notice) {
        if (NOT_FLOWING_STATE.contains(notice.getAuditStatus())) {
            LambdaQueryWrapper<JgEnableDisableEq> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JgEnableDisableEq::getEnableDisableApplyId, notice.getSequenceNbr());
            List<JgEnableDisableEq> noticeEqList = jgEnableDisableEqService.list(queryWrapper);
            noticeEqList.forEach(noticeEq -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                    .delDataForCheckEquipRepeatUsed(Collections.singletonList(noticeEq.getEquId()), notice.getUseUnitCreditCode()));
        }
    }

    private void rollBackForDelRedisData() {
        FlowingEquipRedisContext.getContext().forEach(e -> {
            EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                    .delDataForCheckWithKey(e.getData(), e.getRedisKey());
        });
    }

    private String getRegistrationClass(JgEnableDisable jgEnableDisable) {
        // SB_QY启用，SB_TY停用
        if (ApplicationFormTypeEnum.SBQY.getBusinessCode().equals(jgEnableDisable.getApplyType())) {
            return BusinessTypeEnum.JG_EQUIPMENT_START.getName();
        } else {
            return BusinessTypeEnum.JG_EQUIPMENT_STOP.getName();
        }
    }

    /**
     * 暂存任务生成待办
     *
     * @param jgEnableDisable 业务信息
     */
    private void buildTaskDraft(JgEnableDisable jgEnableDisable) {
        List<TaskModelDto> modelDtos = new ArrayList<>();

        TaskModelDto dto = new TaskModelDto();
        // 行数据
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtils.copyProperties(jgEnableDisable, taskMessageDto);
        dto.setModel(taskMessageDto);
        // 摘要 按原有规则组装
        dto.setTaskContent(
                String.format("来自%s的业务办理，【申请单号：%s】",
                        ObjectUtils.isEmpty(jgEnableDisable.getEquListName()) ? "" : jgEnableDisable.getEquListName(),
                        jgEnableDisable.getApplyNo()));
        // 申请单号
        dto.setTaskCode(jgEnableDisable.getApplyNo());
        // 业务类型枚举code值
        dto.setTaskType(BusinessTypeEnum.JG_EQUIPMENT_START.getCode());
        ////业务主键
        dto.setRelationId(jgEnableDisable.getSequenceNbr() + "");
        modelDtos.add(dto);

        commonService.buildTaskModel(modelDtos);
    }

    /**
     * 组装业务数据
     */
    private void businessData(String submitType, ReginParams reginParams, JgEnableDisable jgEnableDisable, JSONObject map, List<Map<String, Object>> equipments, List<WorkflowResultDto> workflowResultList) {
        // 接收机构
        String[] splitMaintenanceUnitCode = String.valueOf(map.getString("receiveOrgCode")).split("_");
        jgEnableDisable.setApplyDate(new Date());
        jgEnableDisable.setReceiveCompanyCode(splitMaintenanceUnitCode[0]);
        jgEnableDisable.setReceiveOrgName(splitMaintenanceUnitCode[1]);
        jgEnableDisable.setUseUnitCreditCode(CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                reginParams.getCompany().getCompanyCode().split("_")[1] :
                reginParams.getCompany().getCompanyCode());
        jgEnableDisable.setUseUnitName(reginParams.getCompany().getCompanyName());
        jgEnableDisable.setRemark(String.valueOf(map.get("remark")));
        jgEnableDisable.setApplyType(map.getString("applyType"));
        // 设备种类
        String equListCode = String.valueOf(map.getString("equListCode"));
        jgEnableDisable.setEquListCode(equListCode);
        jgEnableDisable.setEquListName(EquipmentClassifityEnum.getNameByCode(equListCode));
        jgEnableDisable.setCreateUserCompanyName(reginParams.getCompany().getCompanyName());
        jgEnableDisable.setPromoter(reginParams.getUserModel().getUserId());
        setCertInfoByEquList(map, jgEnableDisable);
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            if (!CollectionUtils.isEmpty(workflowResultList)) {
                jgEnableDisable.setNextExecuteUserIds(workflowResultList.get(0).getNextExecutorUserIds());
                jgEnableDisable.setInstanceId(workflowResultList.get(0).getInstanceId());
                jgEnableDisable.setAuditStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getName()));
                jgEnableDisable.setNextExecutorIds(workflowResultList.get(0).getNextExecutorRoleIds());
                jgEnableDisable.setExecuteSequence(workflowResultList.get(0).getNextExecutorRoleIds() + "," + workflowResultList.get(0).getExecutorRoleIds());
                jgEnableDisable.setPromoter(reginParams.getUserModel().getUserId());
                jgEnableDisable.setNextTaskId(workflowResultList.get(0).getNextTaskId());
            }
        } else {
            jgEnableDisable.setNextExecuteUserIds(reginParams.getUserModel().getUserId());
            jgEnableDisable.setAuditStatus(String.valueOf(FlowStatusEnum.TO_BE_SUBMITTED.getName()));
        }
        jgEnableDisable.setEquList(String.valueOf(map.get("equListDesc")));
        jgEnableDisable.setCreateUserName(reginParams.getUserModel().getRealName());
        jgEnableDisable.setCreateUserId(reginParams.getUserModel().getUserId());

        LambdaQueryWrapper<JgEnableDisableEq> wrapper = new LambdaQueryWrapper<JgEnableDisableEq>().eq(JgEnableDisableEq::getEnableDisableApplyId, jgEnableDisable.getSequenceNbr().toString());
        jgEnableDisableEqService.getBaseMapper().delete(wrapper);
        // 关联设备表
        for (Map<String, Object> equipment : equipments) {
            JgEnableDisableEq jgEnableDisableEq = new JgEnableDisableEq();
            jgEnableDisableEq.setEquId(String.valueOf(equipment.get(this.getRecordKey(jgEnableDisable))));
            jgEnableDisableEq.setEnableDisableApplyId(jgEnableDisable.getSequenceNbr().toString());
            jgEnableDisableEqService.save(jgEnableDisableEq);
        }
    }

    private String getRecordKey(JgEnableDisable jgEnableDisable) {
        return getRecordKey(jgEnableDisable.getEquListCode());
    }

    private String getRecordKey(String equListCode) {
        if (!EquipmentClassifityEnum.YLGD.getCode().equals(equListCode)) {
            return "SEQUENCE_NBR";
        } else {
            return "record";
        }
    }


    /**
     * 插入代办
     */
    private void buildTask(List<JgEnableDisable> list, String businessCode, List<WorkflowResultDto> workflowResultList, Boolean bool) {
        String taskType = businessCode.equals(ApplicationFormTypeEnum.SBQY.getBusinessCode()) ? BusinessTypeEnum.JG_EQUIPMENT_START.getCode() : BusinessTypeEnum.JG_EQUIPMENT_STOP.getCode();
        String taskTypeLabel = businessCode.equals(ApplicationFormTypeEnum.SBQY.getBusinessCode()) ? BusinessTypeEnum.JG_EQUIPMENT_START.getName() : BusinessTypeEnum.JG_EQUIPMENT_STOP.getName();
        List<TaskModelDto> taskModelDtoList = new ArrayList<>();
        list.forEach(item -> {
            TaskModelDto taskModelDto = new TaskModelDto();
            taskModelDto.setFlowCreateDate(item.getCreateDate());
            if (workflowResultList.size() > 0) {
                taskModelDto.setTaskName(workflowResultList.get(0).getNextTaskName()); // 工作流API返回
                taskModelDto.setExecuteUserIds(workflowResultList.get(0).getNextExecutorUserIds()); // 工作流API返回
            }
            taskModelDto.setTaskCode(item.getApplyNo());
            taskModelDto.setTaskType(taskType);
            taskModelDto.setTaskTypeLabel(taskTypeLabel);
            taskModelDto.setRelationId(item.getInstanceId());
            taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
            taskModelDto.setFlowStatus(commonService.getDictionaryCodeByName(FlowStatusEnum.TO_BE_PROCESSED.getName())); // 流程状态枚举
            taskModelDto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
            taskModelDto.setFlowCode(item.getNextTaskId());
            taskModelDto.setStartUserId(item.getCreateUserId());
            taskModelDto.setStartUser(item.getCreateUserName());
            taskModelDto.setStartUserCompanyName(item.getCreateUserCompanyName()); // 任务发起人所在单位
            taskModelDto.setStartDate(item.getCreateDate());
            TaskMessageDto taskMessageDto = new TaskMessageDto();
            BeanUtils.copyProperties(item, taskMessageDto);
            taskModelDto.setModel(taskMessageDto);
            taskModelDto.setNextExecuteUser(item.getExecuteSequence());
            taskModelDto.setTaskContent(String.format("来自%s的业务办理，【申请单号：%s】", item.getEquListName(), item.getApplyNo()));
            taskModelDtoList.add(taskModelDto);
            if (bool) {
                // 删除暂存时生成的待办
                commonService.deleteTasksByRelationId(item.getSequenceNbr() + "");
            }
        });
        if (bool) {
            commonService.buildTaskModel(taskModelDtoList);
        }
    }


    public Page<Map<String, Object>> pageList(Page<Map<String, Object>> page, String sort, JgEnableDisableDto dto, String client, ReginParams reginParams) {
        if ("company".equals(reginParams.getCompany().getLevel())) {
            dto.setUseUnitCreditCode(CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                    reginParams.getCompany().getCompanyCode().split("_")[1] :
                    reginParams.getCompany().getCompanyCode());
        } else {
            dto.setReceiveCompanyCode(reginParams.getCompany().getCompanyCode());
            dto.setOrgBranchCode(reginParams.getCompany().getOrgCode());
        }
        String level = reginParams.getCompany().getLevel();
        String userId = reginParams.getUserModel().getUserId();
        SortVo sortMap = commonService.sortFieldConversion(sort);
        return this.baseMapper.pageList(page, sortMap, dto, level, userId, client);
    }


    public String startByVariable() {
        String instanceId = "";
        // 启动流程
        try {
            ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
            dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
            dto.setBusinessKey("submit");
            AjaxResult ajaxResult = Workflow.taskClient.startByVariable(dto);
            instanceId = ((Map<?, ?>) ajaxResult.get("data")).get("id").toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return instanceId;
    }


    /**
     * 工作流启动并执行
     *
     * @param submitType      是否提交
     * @param jgEnableDisable 业务数据
     * @return 工作流返回相关数据
     */
    private List<WorkflowResultDto> workFlowInfo(String submitType, JgEnableDisable jgEnableDisable, String receiveOrgCode) {
        if (SUBMIT_TYPE_FLOW.equals(submitType)) {
            ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
            List<ActWorkflowStartDTO> list = new ArrayList<>();
            ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
            dto.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
            dto.setBusinessKey(jgEnableDisable.getApplyNo());
            dto.setCompleteFirstTask(Boolean.TRUE);
            dto.setNextExecuteUserCompanyCode(receiveOrgCode);
            list.add(dto);

            actWorkflowBatchDTO.setProcess(list);
            List<ProcessTaskDTO> processTaskDTOS = iCmWorkflowService.startBatch(actWorkflowBatchDTO);
            // 组装工作流返回的数据
            return commonService.buildWorkFlowInfo(processTaskDTOS);
        }
        return new ArrayList<>();
    }


    @Transactional(rollbackFor = Exception.class)
    public void flowExecute(JSONObject map, ReginParams reginParams) {
        Long id = map.getLong("sequenceNbr");
        String instanceId = map.getString("instanceId");
        String operate = map.getString("operate");
        String comment = map.getString("comment");
        String nextTaskId = map.getString("nextTaskId");
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForExecuteFlow(nextTaskId, instanceId);
            JgEnableDisable jgEnableDisable = this.baseMapper.selectById(id);

            // 执行工作流并返回组装好的工作流信息
            WorkflowResultDto workflowResultDto = getWorkflowResultDto(operate, comment, jgEnableDisable);

            jgEnableDisable.setPromoter(reginParams.getUserModel().getUserId());
            TaskV2Model taskV2Model = new TaskV2Model();
            if ("0".equals(operate)) {
                if (StringUtils.isEmpty(workflowResultDto.getNextExecutorRoleIds())) {
                    jgEnableDisable.setPromoter("");
                    jgEnableDisable.setAuditPassDate(new Date());
                    jgEnableDisable.setAuditStatus(String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getName()));
                    // 上个代办改为已办
                    HashMap<String, Object> taskMap = new HashMap<>();
                    taskMap.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
                    taskMap.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
                    taskMap.put("relationId", jgEnableDisable.getInstanceId());
                    taskMap.put("flowStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
                    taskMap.put("flowStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
                    TaskMessageDto taskMessageDto = new TaskMessageDto();
                    BeanUtils.copyProperties(jgEnableDisable, taskMessageDto);
                    taskMap.put("model", jgEnableDisable);
                    // 更新业务数据
                    updateInfoOther(jgEnableDisable);
                    //  保存json历史数据
                    commonService.saveOrUpdateHistory(this.getRegistrationClass(jgEnableDisable), map, null, jgEnableDisable.getSequenceNbr().toString());
                    TaskV2Model taskV2Model1 = commonService.updateTaskModel(taskMap);
                    // 完成后发送数据刷新消息
                    this.sendDataRefreshMsg(jgEnableDisable);
                    //  创建设备履历
                    this.createResume(jgEnableDisable, taskV2Model1.getRoutePath());
                } else {
                    jgEnableDisable.setNextExecutorIds(workflowResultDto.getNextExecutorRoleIds());
                    if (!ObjectUtils.isEmpty(jgEnableDisable.getExecuteSequence())) {
                        jgEnableDisable.setExecuteSequence(jgEnableDisable.getExecuteSequence() + "," + workflowResultDto.getNextExecutorRoleIds());
                    } else {
                        jgEnableDisable.setExecuteSequence(workflowResultDto.getNextExecutorRoleIds());
                    }
                    jgEnableDisable.setAuditStatus(String.valueOf(FlowStatusEnum.TO_BE_PROCESSED.getName()));
                    // 上个代办改为已办
                    HashMap<String, Object> taskMap = new HashMap<>();
                    taskMap.put("taskStatus", FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    taskMap.put("taskStatusLabel", FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskMap.put("flowStatus", FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    taskMap.put("flowStatusLabel", FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskMap.put("relationId", jgEnableDisable.getInstanceId());
                    taskV2Model = commonService.updateTaskModel(taskMap);
                    TaskModelDto taskModelDto = new TaskModelDto();
                    BeanUtils.copyProperties(taskV2Model, taskModelDto);
                    // 创建新的代办
                    TaskMessageDto taskMessageDto = new TaskMessageDto();
                    BeanUtils.copyProperties(jgEnableDisable, taskMessageDto);
                    taskModelDto.setModel(taskMessageDto);
                    taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
                    taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                    taskModelDto.setFlowStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    taskModelDto.setFlowStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskModelDto.setFlowCode(workflowResultDto.getNextTaskId());
                    taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
                    commonService.buildTaskModel(Collections.singletonList(taskModelDto));
                }
            } else {
                jgEnableDisable.setPromoter("");
                jgEnableDisable.setAuditStatus(String.valueOf(FlowStatusEnum.REJECTED.getName()));
                jgEnableDisable.setNextExecutorIds(workflowResultDto.getNextExecutorRoleIds());
                // 上个代办改为已办
                HashMap<String, Object> taskMap = new HashMap<>();
                taskMap.put("taskStatus", FlowStatusEnum.REJECTED.getCode());
                taskMap.put("taskStatusLabel", FlowStatusEnum.REJECTED.getName());
                taskMap.put("relationId", jgEnableDisable.getInstanceId());
                taskMap.put("flowStatus", FlowStatusEnum.REJECTED.getCode());
                taskMap.put("flowStatusLabel", FlowStatusEnum.REJECTED.getName());
                taskV2Model = commonService.updateTaskModel(taskMap);
                TaskModelDto taskModelDto = new TaskModelDto();
                BeanUtils.copyProperties(taskV2Model, taskModelDto);
                // 创建新的代办
                TaskMessageDto taskMessageDto = new TaskMessageDto();
                BeanUtils.copyProperties(jgEnableDisable, taskMessageDto);
                taskModelDto.setModel(taskMessageDto);
                taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
                taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                taskModelDto.setFlowStatus(FlowStatusEnum.REJECTED.getCode());
                taskModelDto.setFlowStatusLabel(FlowStatusEnum.REJECTED.getName());
                taskModelDto.setFlowCode(workflowResultDto.getNextTaskId());
                taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
                taskModelDto.setPageType("edit");
                commonService.buildTaskModel(Collections.singletonList(taskModelDto));
            }
            jgEnableDisable.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            jgEnableDisable.setNextTaskId(workflowResultDto.getNextTaskId());
            this.baseMapper.updateById(jgEnableDisable);

            // redis流程实时数据更新
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jgEnableDisable));
            this.delRepeatUseEquipData(jgEnableDisable);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    private void createResume(JgEnableDisable jgEnableDisable, String routePath) {
        if (!jgEnableDisable.getEquListCode().equals(EquipmentClassifityEnum.YLGD.getCode())) { // 非压力管道按照设备记录履历
            LambdaQueryWrapper<JgEnableDisableEq> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JgEnableDisableEq::getEnableDisableApplyId, jgEnableDisable.getSequenceNbr());
            List<JgEnableDisableEq> enableDisableEqs = jgEnableDisableEqService.list(queryWrapper);
            jgResumeInfoService.saveBatchResume(enableDisableEqs.stream().map(eq -> JgResumeInfoDto.builder().applyNo(jgEnableDisable.getApplyNo())
                    .businessType(getRegistrationClass(jgEnableDisable))
                    .businessId(String.valueOf(jgEnableDisable.getSequenceNbr()))
                    .equId(eq.getEquId())
                    .approvalUnit(jgEnableDisable.getReceiveOrgName())
                    .approvalUnitCode(jgEnableDisable.getReceiveCompanyCode())
                    .status("正常")
                    .createUserId(jgEnableDisable.getCreateUserId())
                    .createUserName(jgEnableDisable.getCreateUserName())
                    .changeContent(getRegistrationClass(jgEnableDisable) + "业务办理")
                    .routePath(routePath)
                    .build()).collect(Collectors.toList())
            );
        } else { // 压力管道按照装置记录履历
            jgResumeInfoService.saveBatchResume(Collections.singletonList(JgResumeInfoDto.builder().applyNo(jgEnableDisable.getApplyNo())
                    .businessType(getRegistrationClass(jgEnableDisable))
                    .businessId(String.valueOf(jgEnableDisable.getSequenceNbr()))
                    .equId(jgEnableDisable.getProjectContraptionId())
                    .approvalUnit(jgEnableDisable.getReceiveOrgName())
                    .approvalUnitCode(jgEnableDisable.getReceiveCompanyCode())
                    .status("正常")
                    .createUserId(jgEnableDisable.getCreateUserId())
                    .createUserName(jgEnableDisable.getCreateUserName())
                    .changeContent(getRegistrationClass(jgEnableDisable) + "业务办理")
                    .routePath(routePath)
                    .build())
            );
        }
    }

    private void sendDataRefreshMsg(JgEnableDisable jgEnableDisable) {
        LambdaQueryWrapper<JgEnableDisableEq> lambdaEq = new QueryWrapper<JgEnableDisableEq>().lambda();
        lambdaEq.eq(JgEnableDisableEq::getEnableDisableApplyId, jgEnableDisable.getSequenceNbr());
        lambdaEq.select(JgEnableDisableEq::getEquId);
        List<String> records = jgEnableDisableEqMapper.selectList(lambdaEq).stream().map(JgEnableDisableEq::getEquId).collect(Collectors.toList());
        eventPublisher.publish(new DataRefreshEvent(this, records, DataRefreshEvent.DataType.equipment.name(), DataRefreshEvent.Operation.UPDATE));
    }

    private void updateInfoOther(JgEnableDisable jgEnableDisable) {
        // 1.更新设备的使用信息：启用->停用，停用->启用
        LambdaQueryWrapper<JgEnableDisableEq> lambdaEq = new QueryWrapper<JgEnableDisableEq>().lambda();
        lambdaEq.eq(JgEnableDisableEq::getEnableDisableApplyId, jgEnableDisable.getSequenceNbr());
        List<JgEnableDisableEq> jgEnableDisableEqs = jgEnableDisableEqMapper.selectList(lambdaEq);
        jgEnableDisableEqs.forEach(jgEnableDisableEq -> {
            IdxBizJgUseInfo idxBizJgUseInfo = new IdxBizJgUseInfo();
            if (ApplicationFormTypeEnum.SBQY.getBusinessCode().equals(jgEnableDisable.getApplyType())) {
                // 1启用
                idxBizJgUseInfo.setEquState(String.valueOf(EquipmentEnum.ZAIYONG.getCode()));
            } else {
                // 0停用
                idxBizJgUseInfo.setEquState(String.valueOf(EquipmentEnum.TINGYONG.getCode()));
            }
            LambdaQueryWrapper<IdxBizJgUseInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(IdxBizJgUseInfo::getRecord, jgEnableDisableEq.getEquId());
            idxBizJgUseInfoMapper.update(idxBizJgUseInfo, wrapper);
            // 2.更新设备的es数据的状态：启用->停用，停用->启用
            updateEquipEsData(jgEnableDisableEq, idxBizJgUseInfo);
        });
        String useRegistrationCodeStr = jgEnableDisable.getUseRegistrationCode();
        List<String> useRegistrationCodeList = Optional.ofNullable(useRegistrationCodeStr)
                .map(str -> Arrays.stream(str.split(","))
                        .map(String::trim)
                        .filter(StrUtil::isNotBlank)
                        .collect(Collectors.toList()))
                .orElse(Collections.emptyList());

        if (CollUtil.isNotEmpty(useRegistrationCodeList)) {
            useRegistrationManageService.lambdaUpdate()
                    .set(JgUseRegistrationManage::getCertificateStatus, CertificateStatusEnum.YIDENGJI.getName())
                    .in(JgUseRegistrationManage::getUseRegistrationCode, useRegistrationCodeList)
                    .update();
        }
    }

    private void updateEquipEsData(JgEnableDisableEq jgScrapCancelEq, IdxBizJgUseInfo idxBizJgUseInfo) {
        Map<String, Map<String, Object>> resultMap = new HashMap<>();
        Map<String, Object> map1 = new HashMap<>();
        map1.put("EQU_STATE", idxBizJgUseInfo.getEquState());
        resultMap.put(jgScrapCancelEq.getEquId(), map1);
        try {
            tzsServiceFeignClient.commonUpdateEsDataByIds(resultMap);
        } catch (Exception e) {
            log.error("更新es失败", e.getCause());
        }
    }


    /**
     * 执行工作流并返回组装好的工作流信息
     *
     * @param op              是否通过
     * @param opinion         备注信息
     * @param jgEnableDisable 业务信息
     * @return 返回组装好的工作流信息
     */
    private WorkflowResultDto getWorkflowResultDto(String op, String opinion, JgEnableDisable jgEnableDisable) {
        ProcessTaskDTO processTaskDTO = new ProcessTaskDTO();
        WorkflowResultDto workflowResultDto = new WorkflowResultDto();
        // 只调用执行API，返回下个节点信息，用于填充业务字段
        // 组装信息
        TaskResultDTO workDto = new TaskResultDTO();
        workDto.setResultCode("approvalStatus");
        workDto.setTaskId(jgEnableDisable.getNextTaskId());
        HashMap<String, Object> commMap = new HashMap<>();
        commMap.put("approvalStatus", op);
        workDto.setVariable(commMap);
        workDto.setComment(opinion);
        workDto.setNextExecuteUserCompanyCode("1".equals(op) ? jgEnableDisable.getUseUnitCreditCode() : jgEnableDisable.getReceiveCompanyCode());
        processTaskDTO = iCmWorkflowService.completeOrReject(jgEnableDisable.getNextTaskId(), workDto, op);
        // 提取节点等信息
        workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
        return workflowResultDto;
    }


    @Transactional(rollbackFor = Exception.class)
    public void withdraw(String instanceId, String nextTaskId) {
        String lockKey = CommonServiceImpl.buildJgExecuteLockKey(instanceId);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
            // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
            if (!isLocked) {
                throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 流程执行时，状态及权限校验
            commonService.checkForRevocationFlow(nextTaskId, instanceId);

            JgEnableDisable jgEnableDisable = this.baseMapper.selectOne(new QueryWrapper<JgEnableDisable>().lambda().eq(JgEnableDisable::getInstanceId, instanceId));
            ProcessTaskDTO processTaskDTO = iCmWorkflowService.rollBack(instanceId);
            // 提取节点等信息
            WorkflowResultDto workflowResultDto = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO)).get(0);
            jgEnableDisable.setPromoter("");
            jgEnableDisable.setExecuteSequence(workflowResultDto.getNextExecutorRoleIds());
            jgEnableDisable.setAuditStatus(String.valueOf(FlowStatusEnum.ROLLBACK.getName()));
            jgEnableDisable.setNextTaskId(workflowResultDto.getNextTaskId());
            jgEnableDisable.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
            updateById(jgEnableDisable);
            // 删除待办
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(jgEnableDisable));
            jsonObject.put("nextExecuteUser", jgEnableDisable.getNextExecutorIds());
            jsonObject.put("taskType", BusinessTypeEnum.JG_MAINTENANCE_NOTIFICATION.getCode());
            jsonObject.put("flowStatusLabel", FlowStatusEnum.ROLLBACK.getName());
            jsonObject.put("flowStatus", FlowStatusEnum.ROLLBACK.getCode());
            commonService.rollbackTask(jgEnableDisable.getInstanceId(), jsonObject);

            // redis流程实时数据更新
            commonService.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jgEnableDisable));
            this.delRepeatUseEquipData(jgEnableDisable);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    public InstanceRuntimeData buildInstanceRuntimeData(JgEnableDisable jgEnableDisable) {
        return InstanceRuntimeData.builder()
                .nextExecuteUserIds(jgEnableDisable.getNextExecuteUserIds())
                .promoter(jgEnableDisable.getPromoter())
                .nextTaskId(jgEnableDisable.getNextTaskId())
                .build();
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteMessage(Long sequenceNbr) {
        JgEnableDisable jgEnableDisable = this.baseMapper.selectById(sequenceNbr);
        // 删除代办 + 中止流程
        commonService.deleteTaskModel(String.valueOf(sequenceNbr), jgEnableDisable.getInstanceId());
        // 删除单子
        this.baseMapper.deleteById(sequenceNbr);
        // 删除单子对应eq
        jgEnableDisableEqService.getBaseMapper().delete(new QueryWrapper<JgEnableDisableEq>().lambda()
                .eq(JgEnableDisableEq::getEnableDisableApplyId, sequenceNbr));
        // 删除单子对应历史表数据
        jgRegistrationHistoryMapper.delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getCurrentDocumentId, jgEnableDisable.getSequenceNbr()));
    }

    public Map<String, Object> getDetail(Long sequenceNbr, CompanyBo company) {
        Map<String, Object> resultMap = new HashMap<>();
        JgEnableDisable enableDisable = this.getById(sequenceNbr);
        this.doCompensate(enableDisable);
        JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryMapper.selectOne(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getCurrentDocumentId, sequenceNbr)
                .eq(JgRegistrationHistory::getIsDelete, false));
        // 已完成或者已作废查询json
        if (enableDisable.getAuditStatus().equals(FlowStatusEnum.TO_BE_FINISHED.getName()) || enableDisable.getAuditStatus().equals(FlowStatusEnum.TO_BE_DISCARD.getName())) {
            if (jgRegistrationHistory != null) {
                JSONObject jsonObject = JSONObject.parseObject(jgRegistrationHistory.getChangeData());
                resultMap.putAll(jsonObject);
            }
        } else {
            // 基本信息使用json里面的，其他字段按照如下覆盖
            if (jgRegistrationHistory != null) {
                JSONObject jsonObject = JSONObject.parseObject(jgRegistrationHistory.getChangeData());
                resultMap.putAll(jsonObject);
            }
            // 流程中实时显示设备信息
            LambdaQueryWrapper<JgEnableDisableEq> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JgEnableDisableEq::getEnableDisableApplyId, enableDisable.getSequenceNbr());
            queryWrapper.select(BaseEntity::getSequenceNbr, JgEnableDisableEq::getEquId);
            List<JgEnableDisableEq> enableDisableEqs = jgEnableDisableEqService.list(queryWrapper).stream().filter(e -> org.apache.commons.lang3.StringUtils.isNotEmpty(e.getEquId())).collect(Collectors.toList());
            if (!enableDisableEqs.isEmpty()) {
                List<Map<String, Object>> equipments;
                if (!enableDisable.getEquListCode().equals(EquipmentClassifityEnum.YLGD.getCode())) {
                    equipments = new ArrayList<>();
                    Iterable<ESEquipmentCategoryDto> equipmentCategoryDtos = esEquipmentCategory.findAllById(enableDisableEqs.stream().map(JgEnableDisableEq::getEquId).collect(Collectors.toList()));
                    equipmentCategoryDtos.forEach(dto -> {
                        Map<String, Object> item = new HashMap<>();
                        BeanUtils.copyProperties(dto, item);
                        BeanUtil.beanToMap(dto, item, true, false);
                        item.replaceAll((k, v) -> v == null ? "" : v);
                        item.put("record", dto.getSEQUENCE_NBR());
                        item.put("equipAddress", concatWithSplit(trimNull2Empty(dto.getUSE_PLACE()), trimNull2Empty(dto.getADDRESS())));
                        item.put("EQU_STATE_NAME", !ValidationUtil.isEmpty(dto.getEQU_STATE()) ? EquipmentEnum.getName.get(dto.getEQU_STATE()) : null);
                        item.put("NEXT_INSPECT_DATE", this.castDate2TimeStr(dto.getNEXT_INSPECT_DATE()));
                        equipments.add(item);
                    });
                } else {
                    buildNewProjectBaseInfo(enableDisable, resultMap);
                    equipments = this.getBaseMapper().selectPipeLineByRecords(enableDisableEqs.stream().map(JgEnableDisableEq::getEquId).collect(Collectors.toList()));
                    // 检验报告数据格式化 转json
                    equipments.stream().filter(e -> e.get("inspectReport") != null).forEach(item -> {
                        item.put("inspectReport", JSON.parse(item.get("inspectReport").toString()));
                    });
                }
                resultMap.put("equipments", equipments);
            }
        }
        resultMap.put("receiveOrgCode", enableDisable.getReceiveCompanyCode() + '_' + enableDisable.getReceiveOrgName());
        resultMap.put("receiveCompanyCode", enableDisable.getReceiveCompanyCode());
        resultMap.put("sequenceNbr", enableDisable.getSequenceNbr());
        resultMap.put("applyNo", enableDisable.getApplyNo());
        resultMap.put("applyType", enableDisable.getApplyType());
        resultMap.put("remark", enableDisable.getRemark());
        resultMap.put("auditStatus", enableDisable.getAuditStatus());
        resultMap.put("useUnitCreditCode", enableDisable.getUseUnitCreditCode());
        commonService.convertStringToJsonobject(resultMap, new String[]{"otherAccessories"});
        new FillingEditPermForCurrentUser(new JSONObject(resultMap), company, BusinessTypeEnum.JG_EQUIPMENT_START_STOP).getData();
        return resultMap;
    }

    private void buildNewProjectBaseInfo(JgEnableDisable enableDisable, Map<String, Object> resultMap) {
        IdxBizJgProjectContraptionDto idxBizJgProjectContraptionDto = findOneProjectContraption(enableDisable.getProjectContraptionId());
        resultMap.put("projectContraption", idxBizJgProjectContraptionDto.getProjectContraption());
        resultMap.put("projectContraptionNo", idxBizJgProjectContraptionDto.getProjectContraptionNo());
        resultMap.put("productPhoto", idxBizJgProjectContraptionDto.getProductPhoto());
        resultMap.put("proOtherAccessories", idxBizJgProjectContraptionDto.getProOtherAccessories());
        resultMap.put("productQualificationCertificate", idxBizJgProjectContraptionDto.getProductQualificationCertificate());
    }

    private String concatWithSplit(String... strs) {
        return Arrays.stream(strs).filter(org.apache.commons.lang3.StringUtils::isNotEmpty).collect(Collectors.joining("/"));
    }

    private String trimNull2Empty(String str) {
        return JsonDiffUtil.nullToEmpty(str);
    }

    private Date castDate2TimeStr(Long timestamp) {
        if (timestamp != null) {
            try {
                return DateUtil.date(timestamp);
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }

    @Override
    public boolean beforeCheck(JgEnableDisable jgEnableDisable) {
        return jgEnableDisable.getInstanceId() != null && !jgEnableDisable.getAuditStatus().equals(FlowStatusEnum.TO_BE_FINISHED.getName()) && !jgEnableDisable.getAuditStatus().equals(FlowStatusEnum.TO_BE_DISCARD.getName());
    }

    @Override
    public void compensate(JgEnableDisable jgEnableDisable) {
        commonService.saveExecuteFlowData2Redis(jgEnableDisable.getInstanceId(), this.buildInstanceRuntimeData(jgEnableDisable));
    }

    public void handleEnableDisableWrongData(String applyNo) {
        JgEnableDisable jgEnableDisable = this.baseMapper.selectOne(new LambdaQueryWrapper<JgEnableDisable>()
                .eq(JgEnableDisable::getApplyNo, applyNo)
                .eq(JgEnableDisable::getIsDelete, 0));
        WorkflowResultDto workflowResultDto = new WorkflowResultDto();
        workflowResultDto.setNextTaskCode("已完成");
        workflowResultDto.setNextTaskId(jgEnableDisable.getNextTaskId());
        workflowResultDto.setNextExecutorUserIds(jgEnableDisable.getNextExecuteUserIds());
        if (StringUtils.isEmpty(workflowResultDto.getNextExecutorRoleIds())) {
            jgEnableDisable.setPromoter("");
            jgEnableDisable.setAuditPassDate(new Date());
            jgEnableDisable.setAuditStatus(String.valueOf(FlowStatusEnum.TO_BE_FINISHED.getName()));
            // 上个代办改为已办
            HashMap<String, Object> taskMap = new HashMap<>();
            taskMap.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
            taskMap.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
            taskMap.put("relationId", jgEnableDisable.getInstanceId());
            taskMap.put("flowStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
            taskMap.put("flowStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
            TaskMessageDto taskMessageDto = new TaskMessageDto();
            BeanUtils.copyProperties(jgEnableDisable, taskMessageDto);
            taskMap.put("model", jgEnableDisable);
            // 更新业务数据
            updateInfoOther(jgEnableDisable);
            TaskV2Model taskV2Model1 = commonService.updateTaskModel(taskMap);
            // 完成后发送数据刷新消息
            this.sendDataRefreshMsg(jgEnableDisable);
            //  创建设备履历
            this.createResume(jgEnableDisable, taskV2Model1.getRoutePath());
        }
        jgEnableDisable.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
        jgEnableDisable.setNextTaskId(workflowResultDto.getNextTaskId());
        this.baseMapper.updateById(jgEnableDisable);
        // redis流程实时数据更新
        commonService.saveExecuteFlowData2Redis(jgEnableDisable.getInstanceId(), this.buildInstanceRuntimeData(jgEnableDisable));
        this.delRepeatUseEquipData(jgEnableDisable);
    }

    public IPage<IdxBizJgProjectContraption> getJgProjectContraptionPage(String useUnitCreditCode, Page<IdxBizJgProjectContraption> page, String sequenceNbr) {
        // 兼容个人业务
        if (useUnitCreditCode.contains("_")) {
            useUnitCreditCode = useUnitCreditCode.split("_")[1];
        }
        // 查询流程中的装置
        List<JgEnableDisable> flowIngPros = this.list(new LambdaQueryWrapper<JgEnableDisable>().notIn(JgEnableDisable::getAuditStatus, NOT_FLOWING_STATE).select(BaseEntity::getSequenceNbr, JgEnableDisable::getProjectContraptionId));
        Set<String> proIds = flowIngPros.stream().map(JgEnableDisable::getProjectContraptionId).collect(toSet());
        proIds.remove(null);
        proIds.remove("");
        // 编辑时要有自己
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(sequenceNbr)) {
            proIds.remove(sequenceNbr);
        }
        return this.getBaseMapper().queryJgProjectContraptionPage(page, useUnitCreditCode, proIds);
    }

    public IdxBizJgProjectContraptionDto findOneProjectContraption(Long sequenceNbr) {
        return findOneProjectContraption(String.valueOf(sequenceNbr));
    }

    private IdxBizJgProjectContraptionDto findOneProjectContraption(String sequenceNbr) {
        IdxBizJgProjectContraption bizJgProjectContraption = jgProjectContraptionMapper.selectById(sequenceNbr);
        IdxBizJgProjectContraptionDto dto = new IdxBizJgProjectContraptionDto();
        BeanUtil.copyProperties(bizJgProjectContraption, dto);
        dto.setProductPhoto(JSON.parseArray(bizJgProjectContraption.getProductPhoto()));
        dto.setProOtherAccessories(JSON.parseArray(bizJgProjectContraption.getOtherAccessories()));
        dto.setProductQualificationCertificate(JSON.parseArray(bizJgProjectContraption.getProductQualificationCertificate()));
        return dto;
    }

    public IPage<Map<String, Object>> findPipeLinePage(Page<Map<String, Object>> page, String projectContraptionId, String applyType, Map<String, Object> filters) {
        IPage<Map<String, Object>> re = this.getBaseMapper().selectPipeLinePage(page, projectContraptionId, applyType, filters);
        re.getRecords().forEach(item -> item.put("inspectReport", Optional.ofNullable(item.get("inspectReport")).map(r -> JSON.parse(r.toString())).orElse(null)));
        return re;
    }
}