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

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.toolkit.Sequence;
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.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.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.CompanyTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.*;
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.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.ICmWorkflowService;
import com.yeejoin.amos.boot.module.jg.biz.service.ICompensateFlowDataOfRedis;
import com.yeejoin.amos.boot.module.jg.biz.service.IIdxBizJgRegisterInfoService;
import com.yeejoin.amos.boot.module.jg.biz.feign.WorkFlowFeignService;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgInspectionDetectionInfo;
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.EquipmentClassifityEnum;
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.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.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;

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

    @Autowired
    WorkFlowFeignService workFlowFeginService;

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    JgEnableDisableEqServiceImpl jgEnableDisableEqService;

    @Autowired
    JgEnableDisableEqMapper jgEnableDisableEqMapper;

    @Autowired
    JgMaintainNoticeMapper jgMaintainNoticeMapper;

    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;

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

    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;

    @Autowired
    private JgRegistrationHistoryMapper jgRegistrationHistoryMapper;

    @Autowired
    private Sequence sequence;

    @Autowired
    private IdxBizJgInspectionDetectionInfoServiceImpl jgInspectionDetectionInfoService;

    @Autowired
    private JgUseRegistrationManageMapper jgUseRegistrationManageMapper;

    /**
     * 设备状态:启用
     */
    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) {
        try {
            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.setSequenceNbr(sequence.nextId());
            }
            jgEnableDisable.setCreateDate(new Date());
            String submit = String.valueOf(map.get("submit"));
            String pageType = String.valueOf(map.get("formType"));
            // 设备列表
            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());
            }
            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 (APPLY_TYPE_QY.equals(map.getString("applyType"))) {
                        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.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]);
                // 设备种类
                String equListCode = String.valueOf(map.getString("equListCode"));
                jgEnableDisable.setEquListCode(equListCode);
                jgEnableDisable.setEquListName(EquipmentClassifityEnum.getNameByCode(equListCode));
                // 使用登记证相关
                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(",")));
                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 {
                // 编辑
                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("SEQUENCE_NBR")));
                    jgEnableDisableEq.setEnableDisableApplyId(jgEnableDisable.getSequenceNbr().toString());
                    jgEnableDisableEqService.saveOrUpdate(jgEnableDisableEq);
                }
            }
            if (!SUBMIT_TYPE_FLOW.equals(submit)) {
                // 暂存任务
                buildTaskDraft(jgEnableDisable);
            } else {
                buildTask(Arrays.asList(jgEnableDisable), businessCode, workflowResultList, Boolean.TRUE);
            }
            // 保存历史表
            commonService.saveOrUpdateHistory(this.getRegistrationClass(jgEnableDisable), map, null, jgEnableDisable.getSequenceNbr().toString());
            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 repeatUsedEquipCheck(List<Map<String, Object>> equipList, String companyCode) {
        equipList.forEach(equipMap -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                .equipRepeatUsedCheck(String.valueOf(equipMap.get("SEQUENCE_NBR")), 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 (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】",
                        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());
        // 使用登记证相关
        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(",")));
        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("SEQUENCE_NBR")));
            jgEnableDisableEq.setEnableDisableApplyId(jgEnableDisable.getSequenceNbr().toString());
            jgEnableDisableEqService.save(jgEnableDisableEq);
        }
    }


    /**
     * 插入代办
     */
    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) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        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());
        }
        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 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<>();
    }


    @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));
            this.delRepeatUseEquipData(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());
        List<JgEnableDisableEq> jgEnableDisableEqs = jgEnableDisableEqMapper.selectList(lambdaEq);
        jgEnableDisableEqs.forEach(jgEnableDisableEq -> {
            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, jgEnableDisableEq.getEquId());
            idxBizJgUseInfoMapper.update(idxBizJgUseInfo, wrapper);
            // 2.更新设备的es数据的状态：启用->停用，停用->启用
            updateEquipEsData(jgEnableDisableEq, 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));
            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) {
        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));
        if (jgRegistrationHistory != null) {
            JSONObject jsonObject = JSONObject.parseObject(jgRegistrationHistory.getChangeData());
            resultMap.putAll(jsonObject);
        }
        resultMap.put("receiveOrgCode", enableDisable.getReceiveCompanyCode() + '_' + enableDisable.getReceiveOrgName());
        resultMap.put("sequenceNbr", enableDisable.getSequenceNbr());
        resultMap.put("applyNo", enableDisable.getApplyNo());
        commonService.convertStringToJsonobject(resultMap, new String[]{"otherAccessories"});
        return resultMap;
    }

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

}