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

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.jg.api.dto.*;
import com.yeejoin.amos.boot.module.jg.api.entity.*;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.WorkFlowStatusEnum;
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.JgMaintainNoticeMapper;
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.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.ICmWorkflowService;
import com.yeejoin.amos.boot.module.jg.biz.service.IIdxBizJgRegisterInfoService;
import com.yeejoin.amos.boot.module.jg.flc.api.fegin.WorkFlowFeignService;
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.EquimentEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.IdxBizJgUseInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.RegistrationInfoMapper;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
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.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.rdbms.service.BaseService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import java.util.*;
import java.util.concurrent.TimeUnit;

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

    @Autowired
    WorkFlowFeignService workFlowFeginService;

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    JgEnableDisableEqServiceImpl jgEnableDisableEqService;

    @Autowired
    JgEnableDisableEqMapper jgEnableDisableEqMapper;

    @Autowired
     JgMaintainNoticeMapper jgMaintainNoticeMapper;

    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;

    @Autowired
    IIdxBizJgRegisterInfoService idxBizJgRegisterInfoService;


    private final String PROCESS_DEFINITION_KEY = "deactivateEnable";

    private static final String SUBMIT_TYPE_FLOW = "1";

    @Autowired
    private CommonServiceImpl commonService;

    @Autowired
    ICmWorkflowService iCmWorkflowService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private IdxBizJgUseInfoMapper idxBizJgUseInfoMapper;

    /**
     * 设备状态:启用
     */
    public static final String APPLY_TYPE_QY = "SB_QY";

    /**
     * 设备状态:启用
     */
    public static final String APPLY_TYPE_TY = "SB_TY";

    @Transactional(rollbackFor = Exception.class)
    public List<JgEnableDisable> saveOrUpdate(JSONObject map, ReginParams reginParams) {
        JgEnableDisable jgEnableDisable = new JgEnableDisable();
        if (!"null".equals(String.valueOf(map.get("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.setCreateDate(new Date());
        String submit = String.valueOf(map.get("submit"));
        String pageType = String.valueOf(map.get("formType"));
        String record = String.valueOf(map.get("record"));
        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())));
        jgEnableDisable.setEquList("null".equals(record) ? "null" : String.valueOf(map.get("equListDesc")));
        jgEnableDisable.setSupervisoryCode("null".equals(record) ? "null" : String.valueOf(map.get("supervisoryCode")));

        jgEnableDisable.setEquCategory(ObjectUtils.isEmpty(map.get("equCategoryDesc")) ? null : map.get("equCategoryDesc").toString());
        jgEnableDisable.setProductName(ObjectUtils.isEmpty(map.get("productName")) ? null : map.get("productName").toString());
        jgEnableDisable.setAddress(ObjectUtils.isEmpty(map.get("fullAddress")) ? null : map.get("fullAddress").toString());

        if (SUBMIT_TYPE_FLOW.equals(submit)) {
            if (map.containsKey("instanceId") && !ObjectUtils.isEmpty(map.get("instanceId"))){
                // 只调用执行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 {
                // 启动工作流并返回信息
                workflowResultList = workFlowInfo(submit, record,receiveOrgCode[0]);
                //业务数据组装等
                businessData(submit, reginParams, jgEnableDisable, map, 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(reginParams.getCompany().getCompanyCode());
            jgEnableDisable.setUseUnitName(reginParams.getCompany().getCompanyName());
            jgEnableDisable.setReceiveCompanyCode(receiveOrgCode[0]);
            jgEnableDisable.setReceiveOrgName(receiveOrgCode[1]);
            jgEnableDisable.setRemark(map.get("remark") == null ? "" : map.get("remark").toString());
            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 {
            // 编辑
            jgEnableDisable.setSequenceNbr(Long.valueOf(String.valueOf(map.get("sequenceNbr"))));
            this.baseMapper.updateById(jgEnableDisable);
            LambdaQueryWrapper<JgEnableDisableEq> lambda = new QueryWrapper<JgEnableDisableEq>().lambda();
            lambda.eq(JgEnableDisableEq::getEnableDisableApplyId, String.valueOf(map.get("sequenceNbr")));
            jgEnableDisableEqService.getBaseMapper().delete(lambda);
        }
        if(!SUBMIT_TYPE_FLOW.equals(submit)){
            // 暂存任务
            buildTaskDraft(jgEnableDisable);
        } else {
            buildTask(Arrays.asList(jgEnableDisable), businessCode, workflowResultList, Boolean.TRUE);
        }
        if(!"null".equals(record)){
            // 关联设备表
            JgEnableDisableEq jgEnableDisableEq = new JgEnableDisableEq();
            jgEnableDisableEq.setEquId(record);
            jgEnableDisableEq.setEnableDisableApplyId(jgEnableDisable.getSequenceNbr().toString());
            jgEnableDisableEqService.saveOrUpdate(jgEnableDisableEq);
        }
        // 保存历史表
        commonService.saveOrUpdateHistory(this.getRegistrationClass(jgEnableDisable), map, record, jgEnableDisable.getSequenceNbr().toString());
        return Collections.singletonList(jgEnableDisable);
    }

    private String getRegistrationClass(JgEnableDisable jgEnableDisable){
        // SB_QY启用，SB_TY停用
        if(APPLY_TYPE_QY.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】的业务办理，【申请单号：%s】",
                ObjectUtils.isEmpty(jgEnableDisable.getEquList()) ? "" : jgEnableDisable.getEquList(),
                ObjectUtils.isEmpty(jgEnableDisable.getSupervisoryCode()) ? "" : jgEnableDisable.getSupervisoryCode(),
                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<WorkflowResultDto> workflowResultList) {
        // 接收机构
        String[] splitMaintenanceUnitCode = String.valueOf(map.getString("receiveOrgCode")).split("_");
        jgEnableDisable.setApplyDate(new Date());
        jgEnableDisable.setReceiveCompanyCode(splitMaintenanceUnitCode[0]);
        jgEnableDisable.setReceiveOrgName(splitMaintenanceUnitCode[1]);
        jgEnableDisable.setUseUnitCreditCode(reginParams.getCompany().getCompanyCode());
        jgEnableDisable.setUseUnitName(reginParams.getCompany().getCompanyName());
        jgEnableDisable.setRemark(String.valueOf(map.get("remark")));
        jgEnableDisable.setApplyType(map.getString("applyType"));
        jgEnableDisable.setCreateUserCompanyName(reginParams.getCompany().getCompanyName());
        jgEnableDisable.setPromoter(reginParams.getUserModel().getUserId());
        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.setSupervisoryCode(String.valueOf(map.get("supervisoryCode")));
        jgEnableDisable.setCreateUserName(reginParams.getUserModel().getRealName());
        jgEnableDisable.setCreateUserId(reginParams.getUserModel().getUserId());
    }


    /**
     * 插入代办
     */
    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】的业务办理，【申请单号：%s】", item.getEquList(), item.getSupervisoryCode(), item.getApplyNo()));
            taskModelDtoList.add(taskModelDto);
            if (bool) {
                // 删除暂存时生成的待办
                commonService.deleteTaskModel(item.getSequenceNbr()+"");
            }
        });
        if(bool){
            commonService.buildTaskModel(taskModelDtoList);
        }
    }



    public Page<Map<String, Object>> pageList(Page<Map<String, Object>> page,String sort, JgEnableDisableDto dto) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        if ("company".equals(reginParams.getCompany().getLevel())) {
            dto.setUseUnitCreditCode(reginParams.getCompany().getCompanyCode());
        } else {
            dto.setReceiveCompanyCode(reginParams.getCompany().getCompanyCode());
        }
        String level =  reginParams.getCompany().getLevel();
        String userId =  reginParams.getUserModel().getUserId();
        SortVo sortMap = commonService.sortFieldConversion(sort);
        return this.baseMapper.pageList(page,sortMap, dto, level,userId);
    }


    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 record 设备record
     * @return 工作流返回相关数据
     */
    private List<WorkflowResultDto> workFlowInfo(String submitType, String record,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(record);
            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<>();
    }


    @Autowired
    RegistrationInfoMapper tzsJgRegistrationInfoMapper;

    @Transactional(rollbackFor = Exception.class)
    public void flowExecute(Long id, String instanceId, String operate, String comment, 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.checkForExecuteFlow(nextTaskId, instanceId);

            ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
            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);
                    commonService.updateTaskModel(taskMap);
                } 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));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

    private void updateInfoOther(JgEnableDisable jgEnableDisable) {
        // 1.更新设备的使用信息：启用->停用，停用->启用
        LambdaQueryWrapper<JgEnableDisableEq> lambdaEq = new QueryWrapper<JgEnableDisableEq>().lambda();
        lambdaEq.eq(JgEnableDisableEq::getEnableDisableApplyId, jgEnableDisable.getSequenceNbr());
        JgEnableDisableEq jgScrapCancelEq = jgEnableDisableEqMapper.selectOne(lambdaEq);
        IdxBizJgUseInfo idxBizJgUseInfo = new IdxBizJgUseInfo();
        if(APPLY_TYPE_QY.equals(jgEnableDisable.getApplyType())){
            // 1启用
            idxBizJgUseInfo.setEquState(String.valueOf(EquimentEnum.ZAIYONG.getCode()));
        } else {
            // 0停用
            idxBizJgUseInfo.setEquState(String.valueOf(EquimentEnum.TINGYONG.getCode()));
        }
        LambdaQueryWrapper<IdxBizJgUseInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(IdxBizJgUseInfo::getRecord, jgScrapCancelEq.getEquId());
        idxBizJgUseInfoMapper.update(idxBizJgUseInfo, wrapper);
        // 2.更新设备的es数据的状态：启用->停用，停用->启用
        updateEquipEsData(jgScrapCancelEq, idxBizJgUseInfo);
    }

    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));
        } 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();
    }

    public void updateExecuteIds(String instanceId, Long sequenceNbr, String operate) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        String role = "";
        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
        ArrayList<String> roleList = new ArrayList<>();
        JgEnableDisable jgEnableDisable = this.getBaseMapper().selectById(sequenceNbr);
        try {
            // 查询下节点任务

            JSONObject taskNoAuth = workFlowFeginService.getTaskNoAuth(instanceId);
            if (!ObjectUtils.isEmpty(taskNoAuth.get("data"))) {
                JSONObject nextTask = JSON.parseObject(JSON.toJSONString(taskNoAuth.get("data")));
                String nextTaskId = nextTask.getString("id");
                FeignClientResult<JSONObject> nodeInfo = workFlowFeginService.getNodeInfo(nextTaskId);
                JSONObject result = nodeInfo.getResult();
                Map<String, Object> taskInfo = (Map<String, Object>) result.get("taskInfo");
                taskCode = String.valueOf(taskInfo.get("taskDefinitionKey"));
                AjaxResult taskGroupName = Workflow.taskClient.getTaskGroupName(nextTaskId);
                JSONArray data = JSON.parseArray(JSON.toJSONString(taskGroupName.get("data")));
                for (Object datum : data) {
                    if (((Map) datum).containsKey("groupId")) {
                        roleList.add(((Map) datum).get("groupId").toString());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(taskCode)) {
            role = String.join(",", roleList);
            jgEnableDisable.setNextExecutorIds(role);
            jgEnableDisable.setPromoter(reginParams.getUserModel().getUserId());
            jgEnableDisable.setInstanceId(instanceId);
            jgEnableDisable.setApplyDate(new Date());
            if (!ObjectUtils.isEmpty(jgEnableDisable.getExecuteSequence())) {
                jgEnableDisable.setExecuteSequence(jgEnableDisable.getExecuteSequence() + "," + role);
            } else {
                jgEnableDisable.setExecuteSequence(role);
            }
            if ("0".equals(operate)) {
                // 通过操作
                jgEnableDisable.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
            } else {
                // 驳回操作
                jgEnableDisable.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getReject());
                jgEnableDisable.setPromoter(null);
            }

        } else {
            jgEnableDisable.setAuditStatus(taskCode);
            jgEnableDisable.setAuditPassDate(new Date());
        }
        this.getBaseMapper().updateById(jgEnableDisable);
    }

    public void deleteMessage(Long sequenceNbr) {
        this.baseMapper.deleteById(sequenceNbr);
        LambdaQueryWrapper<JgEnableDisableEq> lambda = new QueryWrapper<JgEnableDisableEq>().lambda();
        lambda.eq(JgEnableDisableEq::getEnableDisableApplyId, sequenceNbr);
        jgEnableDisableEqService.getBaseMapper().delete(lambda);
        // 删除暂存时生成的待办
        commonService.deleteTaskModel(sequenceNbr + "");
    }

    public Map<String, Object> getDetail(Long sequenceNbr) {
        Map<String, Object> resultMap = new HashMap<>();
        JgEnableDisable enableDisable = this.getById(sequenceNbr);
        Map<String, Object> beanMap = BeanUtil.beanToMap(enableDisable, false, true);
        if(enableDisable.getAuditStatus().equals(FlowStatusEnum.TO_BE_FINISHED.getName())){
            // 完成状态查询历史表
            JSONObject jsonObject = commonService.queryHistoryData(sequenceNbr);
            // 兼容老数据
            if(jsonObject == null){
                // 新数据逻辑
                fillRuntimeEquipInfoData(sequenceNbr, resultMap);
            } else {
                // 老数据逻辑
                CommonServiceImpl.formatTime2StrDateForEquip(jsonObject);
                resultMap.putAll(jsonObject);
            }
            resultMap.putAll(beanMap);
        } else {
            // 其他状态显示实时数据
            fillRuntimeEquipInfoData(sequenceNbr, resultMap);
            resultMap.putAll(beanMap);
        }
        resultMap.put("receiveOrgCode", enableDisable.getReceiveCompanyCode() + '_' + enableDisable.getReceiveOrgName());
        commonService.convertStringToJsonobject(resultMap, new String[]{"otherAccessories"});
        return resultMap;
    }

    private void fillRuntimeEquipInfoData(Long sequenceNbr, Map<String, Object> resultMap) {
        JgEnableDisableEq jgEnableDisableEq = jgEnableDisableEqMapper.selectOne(new LambdaQueryWrapper<JgEnableDisableEq>().eq(JgEnableDisableEq::getEnableDisableApplyId, sequenceNbr));
        if (!ObjectUtils.isEmpty(jgEnableDisableEq)) {
            Map<String, Object> map = idxBizJgRegisterInfoService.getDetailFieldCamelCaseByRecord(jgEnableDisableEq.getEquId());
            resultMap.putAll(map);
        }
    }

}