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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
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.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.yeejoin.amos.boot.biz.common.annotation.EnableEsRollback;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.controller.BaseController;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.module.common.api.dao.ESEquipmentCategory;
import com.yeejoin.amos.boot.module.common.api.dao.EsBaseEnterpriseInfoDao;
import com.yeejoin.amos.boot.module.common.api.dao.EsEquipmentDao;
import com.yeejoin.amos.boot.module.common.api.dao.EsUserInfoDao;
import com.yeejoin.amos.boot.module.common.api.dto.ESEquipmentCategoryDto;
import com.yeejoin.amos.boot.module.common.api.enums.CylinderTypeEnum;
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.*;
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.enums.WorkFlowStatusEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.*;
import com.yeejoin.amos.boot.module.jg.api.service.IJgChangeRegistrationNameService;
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.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.common.api.service.ICompensateFlowDataOfRedis;
import com.yeejoin.amos.boot.module.ymt.api.common.StringUtil;
import com.yeejoin.amos.boot.module.ymt.api.entity.TzBaseEnterpriseInfo;
import com.yeejoin.amos.boot.module.ymt.api.entity.TzsBaseIndividuality;
import com.yeejoin.amos.boot.module.ymt.api.entity.TzsUserInfo;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
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.TzBaseEnterpriseInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzsBaseIndividualityMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzsUserInfoMapper;
import com.yeejoin.amos.boot.module.ymt.flc.api.entity.RegUnitInfo;
import com.yeejoin.amos.boot.module.ymt.flc.api.feign.AccessFeignService;
import com.yeejoin.amos.boot.module.ymt.flc.api.mapper.RegUnitInfoMapper;
import com.yeejoin.amos.component.feign.config.InnerInvokException;
import com.yeejoin.amos.component.feign.model.FeignClientResult;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.systemctl.model.TaskV2Model;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowBatchDTO;
import com.yeejoin.amos.feign.workflow.model.ActWorkflowStartDTO;
import com.yeejoin.amos.feign.workflow.model.ProcessTaskDTO;
import com.yeejoin.amos.feign.workflow.model.TaskResultDTO;
import io.seata.spring.annotation.GlobalTransactional;
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.http.HttpStatus;
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.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 更名变更登记服务实现类
 *
 * @author system_generator
 * @date 2023-12-25
 */
@Service
public class JgChangeRegistrationNameServiceImpl extends BaseService<JgChangeRegistrationNameDto, JgChangeRegistrationName, JgChangeRegistrationNameMapper> implements IJgChangeRegistrationNameService, ICompensateFlowDataOfRedis<JgChangeRegistrationName> {

    @Autowired
    private JgChangeRegistrationNameEqServiceImpl jgChangeRegistrationNameEqService;

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;

    @Autowired
    private JgChangeRegistrationNameEqMapper jgChangeRegistrationNameEqMapper;

    @Autowired
    private RegUnitInfoMapper regUnitInfoMapper;

    @Autowired
    private TzBaseEnterpriseInfoMapper tzBaseEnterpriseInfoMapper;

    @Autowired
    AccessFeignService accessFeignService;

    @Autowired
    CommonServiceImpl commonService;

    @Autowired
    ICmWorkflowService cmWorkflowService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private JgResumeInfoServiceImpl jgResumeInfoService;

    @Autowired
    private JgResumeInfoEqServiceImpl jgResumeInfoEqService;
    @Autowired
    private EsBaseEnterpriseInfoDao enterpriseInfoDao;
    @Autowired
    private EsEquipmentDao esEquipmentDao;
    @Autowired
    private EsUserInfoDao esUserInfoDao;
    @Autowired
    private ESEquipmentCategory esEquipmentCategory;

    public final static String CHANGE_NAME = "更名变更";
    public final static String CHANGE_NAME_KEY = "changeName";
    private final List<String> NOT_FLOWING_STATE = Arrays.asList("使用单位待提交", "一级受理已驳回", "使用单位已撤回", "已作废", "已完成");

    private static String template = "发起【更名变更登记】业务申请，【申请单号：%s】";
    @Autowired
    private JgRegistrationHistoryMapper jgRegistrationHistoryMapper;
    @Autowired
    private JgRegistrationHistoryServiceImpl jgRegistrationHistoryService;

    @Autowired
    private JgUseRegistrationManageServiceImpl jgUseRegistrationManageService;

    @Autowired
    private TzsUserInfoMapper useInfoMapper;

    @Autowired
    private TzsBaseIndividualityMapper individualityMapper;

    @Autowired
    private IdxBizJgUseInfoMapper jgUseInfoMapper;

    @Autowired
    private JgCertificateChangeRecordServiceImpl jgCertificateChangeRecordService;

    @Autowired
    private JgCertificateChangeRecordEqMapper jgCertificateChangeRecordEqMapper;

    @Autowired
    private EventPublisher eventPublisher;

    public static final int DB_BATCH_SIZE = 500;
    public static final int ES_BATCH_SIZE = 200;

    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 600000)
    public List<JgChangeRegistrationName> save2(String submitType, JSONObject requestParam) {
        Map<String, JSONObject> jgRegistrationInfoMap = (Map<String, JSONObject>) JSONObject.parseObject(JSONObject.toJSONString(requestParam), Map.class);
        return Collections.singletonList(this.save(submitType, jgRegistrationInfoMap));
    }

    public void saveJgChangeRegistrationNameEq(Long registrationId, Object object, ReginParams reginParams) {
        JSONArray objects = JSONObject.parseArray(object.toString());
        ArrayList<JgChangeRegistrationNameEq> jgChangeRegistrationNameEqs = new ArrayList<>();
        if (!ObjectUtils.isEmpty(objects)) {
            List<JgUseRegistrationManageDto> jgUseRegistrationManageDtos = objects.toJavaList(JgUseRegistrationManageDto.class);
            List<Long> collect = jgUseRegistrationManageDtos.stream().map(JgUseRegistrationManageDto::getSequenceNbr).collect(Collectors.toList());
            List<JSONObject> jsonObjects = jgUseRegistrationManageService.queryEquByCertificateSeqList(collect);
            jgUseRegistrationManageDtos.forEach(item -> {
                JgChangeRegistrationNameEq jgChangeRegistrationNameEq = new JgChangeRegistrationNameEq();
                jgChangeRegistrationNameEq.setNameChangeRegistrationId(registrationId.toString());
                jgChangeRegistrationNameEq.setCreateDate(new Date());
                jgChangeRegistrationNameEq.setCreateUserId(reginParams.getUserModel().getUserId());
                jgChangeRegistrationNameEq.setCreateUserName(reginParams.getUserModel().getRealName());
                jgChangeRegistrationNameEq.setCertificateSeq(item.getSequenceNbr().toString());
                List<JSONObject> equipInfo = jsonObjects.stream().filter(a -> a.get("USE_ORG_CODE").equals(item.getUseRegistrationCode())).collect(Collectors.toList());
                jgChangeRegistrationNameEq.setEquipInfo(JSONObject.toJSONString(equipInfo));
                jgChangeRegistrationNameEq.setIsInvalid("0");
                jgChangeRegistrationNameEqs.add(jgChangeRegistrationNameEq);
            });
        }
        if (!ObjectUtils.isEmpty(jgChangeRegistrationNameEqs)) {
            LambdaQueryWrapper<JgChangeRegistrationNameEq> lambda = new QueryWrapper<JgChangeRegistrationNameEq>().lambda();
            lambda.eq(JgChangeRegistrationNameEq::getNameChangeRegistrationId, registrationId);
            jgChangeRegistrationNameEqService.remove(lambda);
            jgChangeRegistrationNameEqService.saveBatch(jgChangeRegistrationNameEqs);
        }
    }

    public void updateHistory(Map<String, JSONObject> map, String currentDocumentId) {
        JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
        LambdaQueryWrapper<JgRegistrationHistory> lambda = new QueryWrapper<JgRegistrationHistory>().lambda();
        lambda.eq(JgRegistrationHistory::getCurrentDocumentId, currentDocumentId);
        lambda.eq(JgRegistrationHistory::getRegistrationClass, CHANGE_NAME);
        lambda.eq(JgRegistrationHistory::getIsDelete, false);
        Integer integer = jgRegistrationHistoryService.getBaseMapper().selectCount(lambda);
        if (integer > 0) {
            jgRegistrationHistory.setChangeData(JSON.toJSONString(map));
            jgRegistrationHistoryService.update(jgRegistrationHistory, lambda);
        } else {
            jgRegistrationHistory.setChangeData(JSON.toJSONString(map));
            jgRegistrationHistory.setStatus("new");
            jgRegistrationHistory.setRegistrationClass(CHANGE_NAME);
            jgRegistrationHistory.setCurrentDocumentId(currentDocumentId);
            jgRegistrationHistoryService.save(jgRegistrationHistory);
        }

    }

    public void updateEsData(List<String> ids, JgChangeRegistrationName jgChangeRegistrationName) {
        // 更新es
        Iterable<ESEquipmentCategoryDto> equips = esEquipmentCategory.findAllById(ids);
        Date date = new Date();
        equips.forEach(item -> {
            item.setUSE_UNIT_NAME(jgChangeRegistrationName.getNewUseUnitName());
            item.setREC_DATE(date.getTime());
        });
        esEquipmentCategory.saveAllWithFallback(equips);
//        Iterable<ESEquipmentInfo> newEsDtos = esEquipmentDao.findAllById(ids);
//        newEsDtos.forEach(dto -> {
//            dto.setUSE_UNIT_NAME(jgChangeRegistrationName.getNewUseUnitName());
//            dto.setREC_DATE(date.getTime());
//        });
//        esEquipmentDao.saveAll(newEsDtos);
    }

    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 600000)
    public JgChangeRegistrationName save(String submitType, Map<String, JSONObject> jgRegistrationInfoMap) {
        try {
            ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
            String[] taskName = new String[]{"流程结束"};
            JSONObject jgRegistrationInfo = jgRegistrationInfoMap.get("jgRegistrationInfo");
            JgChangeRegistrationNameDto model = JSON.parseObject(jgRegistrationInfo.toJSONString(), JgChangeRegistrationNameDto.class);
            // 获取告知单号
            ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.GMBG.getCode(), 1);
            if (!ObjectUtils.isEmpty(listResponseModel) && listResponseModel.getStatus() != HttpStatus.OK.value()) {
                log.error(" 获取告知单号失败");
                throw new RuntimeException();
            }
            List<String> applyNoList = listResponseModel.getResult();
            if (CollectionUtils.isEmpty(applyNoList)) {
                return null;
            }
            if ("1".equals(submitType)) {
                JSONArray objects = JSONObject.parseArray(jgRegistrationInfo.get("dataList").toString());
                List<Map<String, Object>> equipList = new ArrayList<>();
                for (Object object : objects) {
                    JSONObject jsonObject = JSON.parseObject(object.toString());
                    Map<String, Object> map = new HashMap<>();
                    map.put("SEQUENCE_NBR", jsonObject.get("sequenceNbr"));
                    equipList.add(map);
                }
                this.repeatUsedEquipCheck(equipList,
                        CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                                reginParams.getCompany().getCompanyCode().split("_")[1] :
                                reginParams.getCompany().getCompanyCode());
            }
            List<ProcessTaskDTO> processTasks = new ArrayList<>();
            // 判断当前是否为提交
            String instanceId = "";
            String nextTaskId = "";
            List<String> roleListNext = new ArrayList<>();
            List<String> roleListAll = new ArrayList<>();
            String applyNo = applyNoList.get(0);
            String nextUserIds = "";
            if ("1".equals(submitType)) {
                // 发起流程
                ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                List<ActWorkflowStartDTO> list = new ArrayList<>();
                ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                dto.setProcessDefinitionKey("unitRename");
                dto.setBusinessKey(applyNo);
                dto.setCompleteFirstTask(true);
                // 启动并执行下一步人单位传接收单位的code
                dto.setNextExecuteUserCompanyCode(this.getReceiveCompanyCode(model));
                list.add(dto);
                actWorkflowBatchDTO.setProcess(list);
                processTasks = cmWorkflowService.startBatch(actWorkflowBatchDTO);
                this.buildRoleList(processTasks, roleListNext, roleListAll);
                instanceId = processTasks.get(0).getProcessInstance().getId();
                nextTaskId = processTasks.get(0).getNextTask().get(0).getId();
                taskName[0] = processTasks.get(0).getNextTask().get(0).getName();
                List<WorkflowResultDto> workflowResultDtos = commonService.buildWorkFlowInfo(processTasks);
                nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
            }
            JgChangeRegistrationName dto = new JgChangeRegistrationName();
            // 字段转换
            convertField(model);
            BeanUtils.copyProperties(model, dto);
            dto.setApplyNo(applyNo);
            dto.setApplyDate(new Date());
            dto.setCreateDate(new Date());
            dto.setNextExecutorIds(String.join(",", roleListNext));
            dto.setInstanceStatus(String.join(",", roleListAll));
            dto.setPromoter(reginParams.getUserModel().getUserId());
            if (!StringUtils.isEmpty(instanceId)) {
                dto.setInstanceId(instanceId);
                dto.setNextTaskId(nextTaskId);
                dto.setNextExecuteUserIds(nextUserIds);
                dto.setAuditStatus(String.valueOf(WorkFlowStatusEnum.UNIT_RENAME_RECEIVE.getPass()));
            } else {
                dto.setAuditStatus(String.valueOf(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getPass()));
            }
            dto.setUseUnitCreditCode(CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                    reginParams.getCompany().getCompanyCode().split("_")[1] :
                    reginParams.getCompany().getCompanyCode());
            dto.setCreateUserId(RequestContext.getExeUserId());
            dto.setCreateUserName(reginParams.getUserModel().getRealName());
            this.save(dto);
            // 新增业务关联设备表
            if (!ObjectUtils.isEmpty(jgRegistrationInfo) && !ObjectUtils.isEmpty(jgRegistrationInfo.get("dataList"))) {
                saveJgChangeRegistrationNameEq(dto.getSequenceNbr(), jgRegistrationInfo.get("dataList"), reginParams);
            }
            // 保存历史数据
            updateHistory(jgRegistrationInfoMap, dto.getSequenceNbr().toString());
            // 创建代办
            this.createTaskModel(dto, taskName[0], submitType, nextUserIds);
            if (StringUtil.isNotEmpty(dto.getInstanceId())) {
                commonService.saveExecuteFlowData2Redis(dto.getInstanceId(), this.buildInstanceRuntimeData(dto));
            }
            return dto;
        } 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(CHANGE_NAME_KEY)
                .registrationRepeatUsedCheck(String.valueOf(equipMap.get("SEQUENCE_NBR")), companyCode));
    }

    /**
     * 删除 redis校验重复引用设备的数据
     */
    private void delRepeatUseEquipData(JgChangeRegistrationName notice) {
        if (NOT_FLOWING_STATE.contains(notice.getAuditStatus())) {
            final String creditCode = notice.getUseUnitCreditCode().contains("_")
                    ? notice.getUseUnitCreditCode().substring(notice.getUseUnitCreditCode().indexOf("_") + 1)
                    : notice.getUseUnitCreditCode();
            jgChangeRegistrationNameEqMapper.selectList(
                    new LambdaQueryWrapper<JgChangeRegistrationNameEq>()
                            .eq(JgChangeRegistrationNameEq::getNameChangeRegistrationId, notice.getSequenceNbr())
            ).forEach(noticeEq ->
                    EquipUsedCheckStrategyContext.getUsedStrategy(CHANGE_NAME_KEY)
                            .delDataForCheckEquipRepeatUsed(Collections.singletonList(noticeEq.getCertificateSeq()), creditCode)
            );
        }
    }

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

    private String getReceiveCompanyCode(JgChangeRegistrationNameDto model) {
        String receiveOrgId = model.getReceiveOrgCode();
        if (!ObjectUtils.isEmpty(receiveOrgId)) {
            String[] receiveOrgIdList = receiveOrgId.split("_");
            if (receiveOrgIdList.length > 1) {
                return receiveOrgIdList[0];
            }
        }
        return null;
    }

    private void buildRoleList(List<ProcessTaskDTO> processTasks, List<String> roleListNext, List<String> roleListAll) {
        processTasks.forEach(p -> {
            p.getNextCandidateGroups().values().forEach(e -> {
                roleListNext.addAll(e);
                roleListAll.addAll(e);
            });
            roleListAll.addAll(p.getCandidateGroups());
        });
    }

    private void createTaskModel(JgChangeRegistrationName dto, String taskName, String submitType, String nextUserIds) {
        ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        // 提交创建待办逻辑
        if ("1".equals(submitType)) {
            //提交时先删除之前的暂存待办数据
            commonService.deleteTasksByRelationId(dto.getSequenceNbr() + "");
            // 创建待办
            TaskModelDto taskModelDto = new TaskModelDto();
            taskModelDto.setFlowCreateDate(dto.getApplyDate());
            taskModelDto.setTaskName(taskName);
            taskModelDto.setTaskCode(dto.getApplyNo());
            taskModelDto.setTaskContent(this.buildTaskContent(dto));
            taskModelDto.setTaskDesc("");
            taskModelDto.setTaskType(BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getCode());
            taskModelDto.setTaskTypeLabel(BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getName());
            taskModelDto.setRelationId(dto.getInstanceId());
            taskModelDto.setExecuteUserIds(nextUserIds);
            FlowStatusEnum flowStatusEnum = this.getTaskStatus(submitType);
            taskModelDto.setTaskStatus(flowStatusEnum.getCode());
            taskModelDto.setTaskStatusLabel(flowStatusEnum.getName());
            taskModelDto.setFlowStatus(this.getTaskStatusByName(dto.getAuditStatus()));
            taskModelDto.setFlowStatusLabel(dto.getAuditStatus());
            taskModelDto.setStartUserId(dto.getCreateUserId());
            taskModelDto.setFlowCode(dto.getNextTaskId());
            taskModelDto.setStartUser(reginParams.getUserModel().getRealName());
            taskModelDto.setStartUserCompanyName(dto.getUseUnitName());
            taskModelDto.setNextExecuteUser(dto.getNextExecutorIds());
            taskModelDto.setStartDate(dto.getCreateDate());
            TaskMessageDto taskMessageDto = new TaskMessageDto();
            BeanUtil.copyProperties(dto, taskMessageDto);
            taskModelDto.setModel(taskMessageDto);
            commonService.buildTaskModel(Collections.singletonList(taskModelDto));
        }
        // 暂存创建待办逻辑
        if ("0".equals(submitType)) {
            // 暂存 创建待办逻辑
            TaskModelDto taskModelDto = new TaskModelDto();
            //行数据
            //附件太大赋空
            dto.setChangeCertificate(null);
            taskModelDto.setModel(dto);
            //摘要 按原有规则组装
            taskModelDto.setTaskContent(buildTaskContent(dto));
            //申请单号
            taskModelDto.setTaskCode(dto.getApplyNo());
            //业务类型枚举code值
            taskModelDto.setTaskType(BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getCode());
            //业务主键
            taskModelDto.setRelationId(dto.getSequenceNbr() + "");
            commonService.buildTaskModel(Collections.singletonList(taskModelDto));
        }
    }

    private Integer getTaskCodeByName(String auditStatus) {
        return commonService.getDictionaryCodeByName(auditStatus);
    }

    /**
     * 摘要构建
     *
     * @param dto 业务
     * @return 摘要
     */
    private String buildTaskContent(JgChangeRegistrationName dto) {
        return String.format(template, dto.getApplyNo());
    }


    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public JgChangeRegistrationNameDto updateInfo(String submitType, JgChangeRegistrationNameDto jgChangeRegistrationNameDto, String op) {
        if (Objects.isNull(jgChangeRegistrationNameDto) || StringUtils.isEmpty(submitType)) {
            throw new IllegalArgumentException("参数不能为空");
        }
        // 字段转换
        this.convertField(jgChangeRegistrationNameDto);
        List<String> roleListNext = new ArrayList<>();
        List<String> roleListAll = new ArrayList<>();
        JgChangeRegistrationName jgChangeRegistrationName = this.getById(jgChangeRegistrationNameDto.getSequenceNbr());
        BeanUtil.copyProperties(jgChangeRegistrationNameDto, jgChangeRegistrationName);

        if ("1".equals(submitType)) {
            LambdaQueryWrapper<JgChangeRegistrationNameEq> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(JgChangeRegistrationNameEq::getNameChangeRegistrationId, jgChangeRegistrationNameDto.getSequenceNbr());
            List<JgChangeRegistrationNameEq> noticeEqList = jgChangeRegistrationNameEqMapper.selectList(queryWrapper);
            List<Map<String, Object>> equipList = new ArrayList<>();
            for (JgChangeRegistrationNameEq eq : noticeEqList) {
                Map<String, Object> map = new HashMap<>();
                map.put("SEQUENCE_NBR", eq.getCertificateSeq());
                equipList.add(map);
            }
            ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
            this.repeatUsedEquipCheck(equipList,
                    CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                            reginParams.getCompany().getCompanyCode().split("_")[1] :
                            reginParams.getCompany().getCompanyCode());
        }
        if ("1".equals(submitType)) {
            //发起流程
            if (!StringUtils.hasText(jgChangeRegistrationName.getInstanceId())) {
                List<ProcessTaskDTO> processTasks = new ArrayList<>();
                ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                List<ActWorkflowStartDTO> list = new ArrayList<>();
                ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                dto.setProcessDefinitionKey("unitRename");
                dto.setBusinessKey(jgChangeRegistrationName.getApplyNo());
                dto.setCompleteFirstTask(true);
                // 启动并执行下一步人单位传接收单位的code
                dto.setNextExecuteUserCompanyCode(jgChangeRegistrationName.getReceiveCompanyCode());
                list.add(dto);
                actWorkflowBatchDTO.setProcess(list);
                processTasks = cmWorkflowService.startBatch(actWorkflowBatchDTO);
                String instanceId = processTasks.get(0).getProcessInstance().getId();
                String nextTaskId = processTasks.get(0).getNextTask().get(0).getId();
                String taskName = processTasks.get(0).getNextTask().get(0).getName();
                this.buildRoleList(processTasks, roleListNext, roleListAll);
                List<WorkflowResultDto> workflowResultDtos = commonService.buildWorkFlowInfo(processTasks);
                String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
                jgChangeRegistrationName.setInstanceStatus(String.join(",", roleListAll));
                jgChangeRegistrationName.setInstanceId(instanceId);
                jgChangeRegistrationName.setNextExecutorIds(String.join(",", roleListNext));
                jgChangeRegistrationName.setNextTaskId(nextTaskId);
                jgChangeRegistrationName.setNextExecuteUserIds(nextUserIds);
                jgChangeRegistrationName.setAuditStatus(WorkFlowStatusEnum.UNIT_RENAME_RECEIVE.getPass());
                jgChangeRegistrationName.setApplyDate(new Date());
                // 创建待办
                createTaskModel(jgChangeRegistrationName, taskName, "1", nextUserIds);
            } else {
                // 执行一步
                ProcessTaskDTO processTaskDTO = submit(op, jgChangeRegistrationName);
                String nextTaskId = processTaskDTO.getNextTask().get(0).getId();
                String taskName = processTaskDTO.getNextTask().get(0).getName();
                this.buildRoleList(Collections.singletonList(processTaskDTO), roleListNext, roleListAll);
                List<WorkflowResultDto> workflowResultDtos = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
                String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
                // 查询下节点任务
                if (!ObjectUtils.isEmpty(jgChangeRegistrationName.getInstanceStatus())) {
                    jgChangeRegistrationName.setInstanceStatus(jgChangeRegistrationName.getInstanceStatus() + "," + String.join("", roleListNext));
                } else {
                    jgChangeRegistrationName.setInstanceStatus(String.join(",", roleListAll));
                }
                jgChangeRegistrationName.setPromoter(RequestContext.getExeUserId());
                jgChangeRegistrationName.setNextExecutorIds(String.join(",", roleListNext));
                jgChangeRegistrationName.setAuditStatus(WorkFlowStatusEnum.UNIT_RENAME_RECEIVE.getPass());
                jgChangeRegistrationName.setNextTaskId(nextTaskId);
                // 更新下一步可执行人
                jgChangeRegistrationName.setNextExecuteUserIds(nextUserIds);
                executeOneStep(jgChangeRegistrationName, taskName, nextUserIds, op);
            }
            this.updateById(jgChangeRegistrationName);
            commonService.saveExecuteFlowData2Redis(jgChangeRegistrationName.getInstanceId(), this.buildInstanceRuntimeData(jgChangeRegistrationName));
        } else {
            // 暂存逻辑
            createTaskModel(jgChangeRegistrationName, null, "0", null);
            this.updateById(jgChangeRegistrationName);
        }
        return jgChangeRegistrationNameDto;
    }

    private void executeOneStep(JgChangeRegistrationName jgChangeRegistrationName, String taskName, String nextUserIds, String operate) {
        // 先更新之前的待办
        TaskV2Model taskV2Model = updateTaskModel(jgChangeRegistrationName, operate);
        taskV2Model.setTaskDesc("");
        taskV2Model.setTaskContent(this.buildTaskContent(jgChangeRegistrationName));
        taskV2Model.setTaskName(taskName);
        taskV2Model.setTaskDesc("");
        taskV2Model.setTaskCode(jgChangeRegistrationName.getApplyNo());
        taskV2Model.setExecuteUserIds(nextUserIds);
        taskV2Model.setRelationId(jgChangeRegistrationName.getInstanceId());
        FlowStatusEnum flowStatusEnum = this.getTaskStatus(operate);
        taskV2Model.setTaskStatus(flowStatusEnum.getCode());
        taskV2Model.setTaskStatusLabel(flowStatusEnum.getName());
        taskV2Model.setFlowStatus(this.getTaskStatusByName(jgChangeRegistrationName.getAuditStatus()));
        taskV2Model.setFlowStatusLabel(jgChangeRegistrationName.getAuditStatus());
        taskV2Model.setTaskType(BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getCode());
        taskV2Model.setStartUser(jgChangeRegistrationName.getCreateUserName());
        taskV2Model.setTaskTypeLabel(BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getName());
        taskV2Model.setStartDate(jgChangeRegistrationName.getCreateDate());
        taskV2Model.setStartUserId(jgChangeRegistrationName.getCreateUserId());
        taskV2Model.setStartUserCompanyName(jgChangeRegistrationName.getUseUnitName());
        taskV2Model.setExecuteUserIds(nextUserIds);
        taskV2Model.setFlowCode(jgChangeRegistrationName.getNextTaskId());
        TaskModelDto modelDto = new TaskModelDto();
        BeanUtil.copyProperties(taskV2Model, modelDto);
        modelDto.setNextExecuteUser(jgChangeRegistrationName.getNextExecutorIds());
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtil.copyProperties(jgChangeRegistrationName, taskMessageDto);
        modelDto.setModel(taskMessageDto);
        modelDto.setPageType(this.getPageTypeForReject(operate, jgChangeRegistrationName.getAuditStatus()));
        // 再插入新代办、数据待定
        commonService.buildTaskModel(Collections.singletonList(modelDto));
    }

    private String getPageTypeForReject(String operate, String auditStatus) {
        // 驳回
        if ("1".equals(operate)) {
            // 且驳回到的节点为使用单位提交 则可编辑
            if (WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getPass().equals(auditStatus) ||
                    WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getReject().equals(auditStatus) ||
                    WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getRollBack().equals(auditStatus)
            ) {
                // urlInfo.json 文件的 pageType
                return "edit";
            }
            return "look";
        }
        return "look";
    }


    public ProcessTaskDTO submit(String operate, JgChangeRegistrationName jgChangeRegistrationName) {
        //组装信息
        TaskResultDTO dto = new TaskResultDTO();
        dto.setResultCode("approvalStatus");
        dto.setTaskId(jgChangeRegistrationName.getNextTaskId());
        dto.setComment("提交流程");
        dto.setNextExecuteUserCompanyCode(this.getNextUserOrgCode(operate, jgChangeRegistrationName));
        HashMap<String, Object> map = new HashMap<>();
        map.put("approvalStatus", operate);
        dto.setVariable(map);
        return cmWorkflowService.completeOrReject(jgChangeRegistrationName.getNextTaskId(), dto, operate);
    }

    private void convertField(JgChangeRegistrationNameDto model) {
        // 处理文件1
        if (!ValidationUtil.isEmpty(model.getChangeCertificateList())) {
            model.setChangeCertificate(JSON.toJSONString(model.getChangeCertificateList()));
        }
        String receiveOrgId = model.getReceiveOrgCode();
        if (!ObjectUtils.isEmpty(receiveOrgId)) {
            String[] receiveOrgIdList = receiveOrgId.split("_");
            if (receiveOrgIdList.length > 1) {
                model.setReceiveOrgCode(receiveOrgIdList[0]);
                model.setReceiveCompanyCode(receiveOrgIdList[0]);
                model.setReceiveOrgName(receiveOrgIdList[1]);
            }
        }
    }


    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(List<Long> ids) {
        for (Long seq : ids) {
            JgChangeRegistrationName jgChangeRegistrationName = this.baseMapper.selectById(seq);
            // 删除代办 + 中止流程
            commonService.deleteTaskModel(String.valueOf(seq), jgChangeRegistrationName.getInstanceId());
            // 删除单子
            this.baseMapper.deleteById(seq);
            // 删除单子对应eq
            jgChangeRegistrationNameEqMapper.delete(new LambdaQueryWrapper<JgChangeRegistrationNameEq>()
                    .eq(JgChangeRegistrationNameEq::getNameChangeRegistrationId, seq));
            // 删除单子对应历史表数据
            jgRegistrationHistoryMapper.delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                    .eq(JgRegistrationHistory::getCurrentDocumentId, jgChangeRegistrationName.getApplyNo()));
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void revocation(String instanceId, String taskId) {
        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(taskId, instanceId);
            // 执行流程
            String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
            JgChangeRegistrationName jgChangeRegistrationName = new JgChangeRegistrationName();
            LambdaQueryWrapper<JgChangeRegistrationName> lambda = new QueryWrapper<JgChangeRegistrationName>().lambda();
            lambda.eq(JgChangeRegistrationName::getInstanceId, instanceId);
            jgChangeRegistrationName = this.getOne(lambda);
            List<String> roleListNext = new ArrayList<>();
            List<String> roleListAll = new ArrayList<>();
            ProcessTaskDTO processTaskDTO = cmWorkflowService.rollBack(instanceId);
            String nextTaskId = processTaskDTO.getNextTask().get(0).getId();
            this.buildRoleList(Collections.singletonList(processTaskDTO), roleListNext, roleListAll);
            // 待调整
            taskCode = processTaskDTO.getNextTask().get(0).getKey();
            if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(taskCode)) {
                jgChangeRegistrationName.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getRollBack());
            }
            jgChangeRegistrationName.setPromoter(RequestContext.getExeUserId());
            jgChangeRegistrationName.setNextExecutorIds(String.join(",", roleListNext));
            jgChangeRegistrationName.setNextTaskId(nextTaskId);
            List<WorkflowResultDto> workflowResultDtos = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
            // 更新下一步可执行人
            String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
            jgChangeRegistrationName.setNextExecuteUserIds(nextUserIds);
            this.updateById(jgChangeRegistrationName);
            // 删除待办
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(jgChangeRegistrationName));
            jsonObject.put("nextExecuteUser", jgChangeRegistrationName.getNextExecutorIds());
            jsonObject.put("taskType", BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getCode());
            jsonObject.put("flowStatus", this.getTaskCodeByName(jgChangeRegistrationName.getAuditStatus()));
            jsonObject.put("flowStatusLabel", jgChangeRegistrationName.getAuditStatus());
            jsonObject.put("changeCertificate", null);
            // 判断撤回后当前的节点，如果当前节点为提交节点则页面可编辑
            jsonObject.put("pageType", this.getPageTypeByCurrentNode(jgChangeRegistrationName.getAuditStatus()));
            commonService.rollbackTask(instanceId, jsonObject);

            // 保存redis最新流程数据
            commonService.saveExecuteFlowData2Redis(jgChangeRegistrationName.getInstanceId(), this.buildInstanceRuntimeData(jgChangeRegistrationName));
            this.delRepeatUseEquipData(jgChangeRegistrationName);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }

    }

    private String getPageTypeByCurrentNode(String auditStatus) {
        if (WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getPass().equals(auditStatus) ||
                WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getReject().equals(auditStatus) ||
                WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getRollBack().equals(auditStatus)
        ) {
            // urlInfo.json 文件的 pageType
            return "edit";
        } else {
            // urlInfo.json 文件的 pageType
            return "look";
        }
    }

    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 6000000)
    @EnableEsRollback
    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);

            JgChangeRegistrationName jgChangeRegistrationName = this.getBaseMapper().selectById(id);
            String taskId = jgChangeRegistrationName.getNextTaskId();
            // 组装信息
            TaskResultDTO dto = new TaskResultDTO();
            dto.setResultCode("approvalStatus");
            dto.setTaskId(taskId);
            dto.setComment(comment);
            dto.setNextExecuteUserCompanyCode(this.getNextUserOrgCode(operate, jgChangeRegistrationName));
            HashMap<String, Object> map = new HashMap<>();
            map.put("approvalStatus", operate);
            if (!ObjectUtils.isEmpty(jgChangeRegistrationName.getInstanceStatus()) &&
                    (jgChangeRegistrationName.getAuditStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getReject()) ||
                            jgChangeRegistrationName.getAuditStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_SUBMIT.getRollBack()))) {
                map.put("approvalStatus", "提交");
            }
            dto.setVariable(map);
            //执行流程
            ProcessTaskDTO processTaskDTO = cmWorkflowService.completeOrReject(taskId, dto, operate);
            // 更新下一步执行人、创建待办
            updateExecuteIds(instanceId, jgChangeRegistrationName, operate, processTaskDTO);
            this.delRepeatUseEquipData(jgChangeRegistrationName);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }


    private String getNextUserOrgCode(String operate, JgChangeRegistrationName jgChangeRegistrationName) {
        if ("0".equals(operate)) {
            // 执行通过节点，单位code为接收机构单位信息
            return jgChangeRegistrationName.getReceiveCompanyCode();
        }
        if (jgChangeRegistrationName.getAuditStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_RECEIVE.getPass())
                || jgChangeRegistrationName.getAuditStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_RECEIVE.getReject())
                || jgChangeRegistrationName.getAuditStatus().equals(WorkFlowStatusEnum.UNIT_RENAME_RECEIVE.getRollBack())) {
            // 驳回且当前节点为一键节点时，单位code为发起人单位信息
            return jgChangeRegistrationName.getUseUnitCreditCode();
        }
        // 2、3级驳回时，单位code为接收单位code
        return jgChangeRegistrationName.getReceiveCompanyCode();
    }

    public void updateExecuteIds(String instanceId, JgChangeRegistrationName jgChangeRegistrationName, String operate, ProcessTaskDTO processTaskDTO) {
        List<String> roleListNext = new ArrayList<>();
        List<String> roleListAll = new ArrayList<>();
        List<String> recordList;
        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
        String taskName = "";
        String nextTaskId = "";
        if (processTaskDTO != null && processTaskDTO.getNextTask() != null && !processTaskDTO.getNextTask().isEmpty()) {
            taskCode = processTaskDTO.getNextTask().get(0).getKey();
            taskName = processTaskDTO.getNextTask().get(0).getName();
            nextTaskId = processTaskDTO.getNextTask().get(0).getId();
        }
        if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(taskCode)) {
            this.buildRoleList(Collections.singletonList(processTaskDTO), roleListNext, roleListAll);
            List<WorkflowResultDto> workflowResultDtos = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
            String nextUserIds = workflowResultDtos.get(0).getNextExecutorUserIds();
            jgChangeRegistrationName.setNextExecutorIds(String.join(",", roleListNext));
            jgChangeRegistrationName.setPromoter(RequestContext.getExeUserId());
            jgChangeRegistrationName.setInstanceId(instanceId);
            jgChangeRegistrationName.setNextTaskId(nextTaskId);
            // 更新下一步可执行人
            jgChangeRegistrationName.setNextExecuteUserIds(nextUserIds);
            if (!ObjectUtils.isEmpty(jgChangeRegistrationName.getInstanceStatus())) {
                jgChangeRegistrationName.setInstanceStatus(jgChangeRegistrationName.getInstanceStatus() + "," + String.join(",", roleListNext));
            } else {
                jgChangeRegistrationName.setInstanceStatus(String.join(",", roleListNext));
            }
            if ("0".equals(operate)) {
                // 通过操作
                jgChangeRegistrationName.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
            } else {
                // 驳回操作
                jgChangeRegistrationName.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getReject());
                jgChangeRegistrationName.setPromoter(null);
            }
            // 更新上一步待办、创建待办
            executeOneStep(jgChangeRegistrationName, taskName, nextUserIds, operate);
        } else {
            jgChangeRegistrationName.setAuditStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
            jgChangeRegistrationName.setAuditPassDate(new Date());
            // 完成时 下一步骤可执行人清空
            jgChangeRegistrationName.setNextExecuteUserIds("");
            jgChangeRegistrationName.setNextTaskId(nextTaskId);
            // 更新代办
            TaskV2Model taskV2Model = updateTaskModel(jgChangeRegistrationName, operate);
            // 修改业务信息
            recordList = updateInfoOther(taskV2Model, jgChangeRegistrationName);
            Lists.partition(recordList, ES_BATCH_SIZE)
                    .forEach(batch -> updateEsData(batch, jgChangeRegistrationName));
            this.updateEnterpriseInfo(jgChangeRegistrationName);
            this.sendDataRefreshMsg(jgChangeRegistrationName, recordList);
        }
        // 保存redis最新流程数据
        commonService.saveExecuteFlowData2Redis(jgChangeRegistrationName.getInstanceId(), this.buildInstanceRuntimeData(jgChangeRegistrationName));
        this.getBaseMapper().updateById(jgChangeRegistrationName);
    }

    private void sendDataRefreshMsg(JgChangeRegistrationName jgChangeRegistrationName, List<String> records) {
        eventPublisher.publish(new DataRefreshEvent(this, Collections.singletonList(jgChangeRegistrationName.getUseUnitCreditCode()), DataRefreshEvent.DataType.enterprise.name(), DataRefreshEvent.Operation.UPDATE));
        eventPublisher.publish(new DataRefreshEvent(this, records, DataRefreshEvent.DataType.equipment.name(), DataRefreshEvent.Operation.UPDATE));
    }

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

    private TaskV2Model updateTaskModel(JgChangeRegistrationName jgChangeRegistrationName, String operate) {
        Map<String, Object> params = new HashMap<>();
        FlowStatusEnum flowStatusEnum = this.getTaskStatus(operate);
        params.put("relationId", jgChangeRegistrationName.getInstanceId());
        params.put("taskStatus", flowStatusEnum.getCode());
        params.put("taskStatusLabel", flowStatusEnum.getName());
        params.put("flowStatus", this.getTaskStatusByName(jgChangeRegistrationName.getAuditStatus()));
        params.put("flowStatusLabel", jgChangeRegistrationName.getAuditStatus());
        params.put("model", jgChangeRegistrationName);
        return commonService.updateTaskModelNew(params);
    }


    private FlowStatusEnum getTaskStatus(String operate) {
        if ("0".equals(operate)) {
            return FlowStatusEnum.TO_BE_FINISHED;
        } else {
            return FlowStatusEnum.REJECTED;
        }
    }


    private Integer getTaskStatusByName(String auditStatus) {
        return commonService.getDictionaryCodeByName(auditStatus);
    }

    public List<String> updateInfoOther(TaskV2Model taskV2Model, JgChangeRegistrationName jgChangeRegistrationName) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        LambdaUpdateWrapper<RegUnitInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(RegUnitInfo::getUnitCode, jgChangeRegistrationName.getUseUnitCreditCode());
        RegUnitInfo regUnitInfo = new RegUnitInfo();
        regUnitInfo.setName(jgChangeRegistrationName.getNewUseUnitName());
        regUnitInfoMapper.update(regUnitInfo, updateWrapper);

        // 修改本次更名登记选择的使用登记证下的设备信息
        List<JgChangeRegistrationNameEq> list = jgChangeRegistrationNameEqService.lambdaQuery()
                .eq(JgChangeRegistrationNameEq::getNameChangeRegistrationId, jgChangeRegistrationName.getSequenceNbr())
                .list();
        Map<String,String> recordProjectContraptionIdMap = new HashMap<>();
        Set<String> cylinderEquipIds = new HashSet<>();
        List<String> allEquipIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            Set<String> equipIds = new HashSet<>();
            Set<String> certificateSeqList = new HashSet<>();
            list.forEach(item -> {
                Optional.ofNullable(item.getEquipInfo())
                        .map(JSONObject::parseArray)
                        .orElseGet(JSONArray::new)
                        .forEach(info -> {
                            JSONObject json = JSONObject.parseObject(info.toString());
                            if (json.containsKey("SEQUENCE_NBR")) {
                                // record 装置id map
                                recordProjectContraptionIdMap.put(json.getString("SEQUENCE_NBR"), json.getString("PROJECT_CONTRAPTION_ID"));
                                String categoryCode = json.getString("EQU_CATEGORY_CODE");
                                String seqNbr = json.getString("SEQUENCE_NBR");
                                if (!ObjectUtils.isEmpty(categoryCode) && !ObjectUtils.isEmpty(seqNbr)) {
                                    (CylinderTypeEnum.CYLINDER.getCode().equals(categoryCode) ? cylinderEquipIds : equipIds).add(seqNbr);
                                }
                            }
                        });
                if (item.getCertificateSeq() != null) {
                    certificateSeqList.add(item.getCertificateSeq());
                }
            });

            if (CollectionUtil.isNotEmpty(equipIds)) {
                allEquipIds.addAll(equipIds);
            }
            if (CollectionUtil.isNotEmpty(cylinderEquipIds)) {
                allEquipIds.addAll(cylinderEquipIds);
            }

            // 批量更新使用信息
            if (CollectionUtil.isNotEmpty(allEquipIds)) {
                final String useUnitName = jgChangeRegistrationName.getNewUseUnitName();
                final String creditCode = jgChangeRegistrationName.getUseUnitCreditCode();
                final List<String> recordList = new ArrayList<>(allEquipIds);
                Lists.partition(recordList, DB_BATCH_SIZE)
                        .forEach(batch -> jgUseInfoMapper.updateUseUnitNameByRecords(useUnitName, creditCode, batch));
            }
            if (!CollectionUtils.isEmpty(certificateSeqList)) {
                final String newUseUnitName = jgChangeRegistrationName.getNewUseUnitName();
                final String receiveCompanyCode = jgChangeRegistrationName.getReceiveCompanyCode();
                final String receiveOrgName = jgChangeRegistrationName.getReceiveOrgName();
                final String changeReason = BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getName();
                List<String> seqList = new ArrayList<>(certificateSeqList);
                Lists.partition(seqList, DB_BATCH_SIZE).forEach(v -> jgUseRegistrationManageService.batchUpdateManageBySeq(newUseUnitName, changeReason,
                        receiveCompanyCode, receiveOrgName, v));
            }
        }
        // 业务流水生成
        JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryService.lambdaQuery()
                .select(JgRegistrationHistory::getCurrentDocumentId, JgRegistrationHistory::getChangeData)
                .eq(JgRegistrationHistory::getCurrentDocumentId, jgChangeRegistrationName.getSequenceNbr())
                .eq(JgRegistrationHistory::getIsDelete, false)
                .one();
        JSONObject jsonObject = JSONObject.parseObject(jgRegistrationHistory.getChangeData());
        JSONObject dataList = JSONObject.parseObject(jsonObject.get("jgRegistrationInfo").toString());
        Date now = new Date();
        String realName = Privilege.agencyUserClient
                .queryByUserId(jgChangeRegistrationName.getCreateUserId())
                .getResult()
                .getRealName();

        Map<String, JgChangeRegistrationNameEq> certMap = list.stream()
                .collect(Collectors.toMap(JgChangeRegistrationNameEq::getCertificateSeq, Function.identity()));

        JSONArray certificateList = JSONObject.parseArray(dataList.get("dataList").toString());
        List<JgCertificateChangeRecord> changeRecords = certificateList.stream()
                .map(obj -> (JSONObject) obj)
                .map(object -> {
                    JgCertificateChangeRecord record = new JgCertificateChangeRecord();
                    record.setApplyNo(jgChangeRegistrationName.getApplyNo());
                    record.setReceiveOrgName(jgChangeRegistrationName.getReceiveOrgName());
                    record.setAuditPassDate(now);
                    record.setRegDate(jgChangeRegistrationName.getApplyDate());
                    record.setChangeContent(String.format("%s的%s办理了【%s】,单号【%s】,原%s变更为%s,办理日期%s",
                            jgChangeRegistrationName.getUseUnitName(),
                            realName,
                            CHANGE_NAME,
                            jgChangeRegistrationName.getApplyNo(),
                            jgChangeRegistrationName.getUseUnitName(),
                            jgChangeRegistrationName.getNewUseUnitName(),
                            sdf.format(jgChangeRegistrationName.getAuditPassDate())
                    ));
                    record.setRecUserId(jgChangeRegistrationName.getRecUserId());
                    record.setUseRegistrationCode(object.getString("useRegistrationCode"));
                    record.setCertificateNo(object.getString("certificateNo"));
                    record.setUseUnitCreditCode(jgChangeRegistrationName.getUseUnitCreditCode());
                    record.setUseUnitName(jgChangeRegistrationName.getUseUnitName());
                    record.setEquCategory(object.getString("equCategoryCode"));
                    record.setReceiveCompanyCode(jgChangeRegistrationName.getReceiveOrgCode());
                    record.setRoutePath(taskV2Model.getRoutePath());
                    return record;
                })
                .collect(Collectors.toList());

        Lists.partition(changeRecords, DB_BATCH_SIZE).forEach(batch -> jgCertificateChangeRecordService.saveBatch(batch));

        List<JgCertificateChangeRecordEq> eqRecords = certificateList.stream()
                .map(obj -> (JSONObject) obj)
                .flatMap(object -> {
                    JgChangeRegistrationNameEq eqItem = certMap.get(object.getString("sequenceNbr"));
                    if (eqItem == null || StringUtils.isEmpty(eqItem.getEquipInfo())) {
                        return Stream.empty();
                    }
                    JSONArray equList = JSONObject.parseArray(eqItem.getEquipInfo());
                    return equList.stream().map(info -> {
                        JSONObject equInfo = (JSONObject) info;
                        JgCertificateChangeRecordEq eqRecord = new JgCertificateChangeRecordEq();
                        eqRecord.setEquId(equInfo.getString("SEQUENCE_NBR"));
                        eqRecord.setProductCode(equInfo.getString("FACTORY_NUM"));
                        JgCertificateChangeRecord record = changeRecords.stream()
                                .filter(r -> Objects.equals(r.getCertificateNo(), object.getString("certificateNo")))
                                .findFirst()
                                .orElse(null);
                        eqRecord.setChangeRecordId(record != null ? String.valueOf(record.getSequenceNbr()) : null);
                        return eqRecord;
                    });
                })
                .collect(Collectors.toList());
        Lists.partition(eqRecords, DB_BATCH_SIZE).forEach(batch -> jgCertificateChangeRecordEqMapper.insertBatchSomeColumn(batch));
        this.createResumeBatch(recordProjectContraptionIdMap, cylinderEquipIds, jgChangeRegistrationName, taskV2Model.getRoutePath());
        return allEquipIds;
    }

    private void updateEnterpriseInfo(JgChangeRegistrationName jgChangeRegistrationName) {
        // 当企业下所有使用登记证单位信息都改为最新的时候再去修改系统中单位信息
        Optional.ofNullable(tzBaseEnterpriseInfoMapper.selectOne(
                        Wrappers.<TzBaseEnterpriseInfo>lambdaQuery()
                                .eq(TzBaseEnterpriseInfo::getUseUnitCode, jgChangeRegistrationName.getUseUnitCreditCode())
                ))
                .ifPresent(enterprise -> {
                    String newName = jgChangeRegistrationName.getNewUseUnitName();
                    enterprise.setUseUnit(newName);
                    tzBaseEnterpriseInfoMapper.updateById(enterprise);

//                    EsBaseEnterpriseInfo esBaseEnterpriseInfo = new EsBaseEnterpriseInfo();
//                    BeanUtil.copyProperties(enterprise, esBaseEnterpriseInfo);
//                    enterpriseInfoDao.save(esBaseEnterpriseInfo);
                    String platformName = CompanyTypeEnum.INDIVIDUAL.getName().equals(enterprise.getUnitType())
                            ? jgChangeRegistrationName.getUseUnitCreditCode() + "_" + newName
                            : newName;
                    // 人员更新冗余的单位信息
                    List<TzsUserInfo> userOfOneUnit = useInfoMapper.selectList(new LambdaQueryWrapper<TzsUserInfo>().eq(TzsUserInfo::getUnitCode, enterprise.getUseCode()).eq(BaseEntity::getIsDelete, false).select(BaseEntity::getSequenceNbr));
//                    Iterable<EsUserInfo> userInfosEs = esUserInfoDao.findAllById(userOfOneUnit.stream().map(u -> String.valueOf(u.getSequenceNbr())).collect(Collectors.toList()));
//                    userInfosEs.forEach(esUserInfo -> {
//                        esUserInfo.setUnitType(esBaseEnterpriseInfo.getUnitType());
//                        esUserInfo.setSuperviseOrgName(esBaseEnterpriseInfo.getSuperviseOrgName());
//                        esUserInfo.setSuperviseOrgCode(esBaseEnterpriseInfo.getSuperviseOrgCode());
//                        esUserInfo.setOfficeRegion(esBaseEnterpriseInfo.getOfficeRegion());
//                        esUserInfo.setUnitName(platformName);
//                    });

                    if (CompanyTypeEnum.INDIVIDUAL.getName().equals(enterprise.getUnitType())){
                        useInfoMapper.updateBatchUnitName(userOfOneUnit, platformName);
                        // 更新tz_base_individuality信息
                        TzsBaseIndividuality individuality = new TzsBaseIndividuality();
                        individuality.setRealName(jgChangeRegistrationName.getNewUseUnitName());
                        individualityMapper.update(individuality, new LambdaUpdateWrapper<TzsBaseIndividuality>().eq(TzsBaseIndividuality::getEnterpriseId, enterprise.getSequenceNbr()));

                        FeignClientResult<AgencyUserModel> agencyUserModel = Privilege.agencyUserClient.queryByUserId(jgChangeRegistrationName.getCreateUserId());
                        AgencyUserModel userModel = agencyUserModel.getResult();

                        if (!ObjectUtils.isEmpty(userModel)) {
                            userModel.setRealName(jgChangeRegistrationName.getNewUseUnitName());
                            Privilege.agencyUserClient.update(userModel, userModel.getUserId());
                        }
                    }
//                    if (userInfosEs.iterator().hasNext()) {
//                        esUserInfoDao.saveAll(userInfosEs);
//                    }
                    try {
                        Privilege.companyClient.updateCompanyName(enterprise.getUseCode(), platformName);
                    } catch (InnerInvokException e) {
                        throw new RuntimeException(e);
                    }
                });
    }

    private void createResumeBatch(Map<String, String> recordProjectContraptionIdMap, Set<String> cylinderEquipIds, JgChangeRegistrationName jgChangeRegistrationName, String routePath) {
        Set<String> projectContraptionIds = new HashSet<>();
        Set<String> notPipelineRecords = new HashSet<>();
        recordProjectContraptionIdMap.forEach((k,v)->{
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(v)){
                // v 不为空则标识是管道，按照装置创建履历, v为管道记录装置id,
                projectContraptionIds.add(v);
            } else {
                //  v 为空则标识非管道类，按照设备记录履历， key为record
                notPipelineRecords.add(k);
            }
        });
        if (!cylinderEquipIds.isEmpty()) {
            JgResumeInfo resumeInfo = JgResumeInfo.builder()
                    .businessType(BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getName())
                    .applyNo(jgChangeRegistrationName.getApplyNo())
                    .businessId(String.valueOf(jgChangeRegistrationName.getSequenceNbr()))
                    .status("正常")
                    .approvalUnitCode(jgChangeRegistrationName.getReceiveCompanyCode())
                    .approvalUnit(jgChangeRegistrationName.getReceiveOrgName())
                    .changeContent(BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getName() + "业务办理")
                    .routePath(routePath)
                    .build();
            jgResumeInfoService.save(resumeInfo);
            jgResumeInfoEqService.saveBatchResumeEq(cylinderEquipIds.stream()
                    .map(e -> JgResumeInfoEq.builder()
                            .resumeId(String.valueOf(resumeInfo.getSequenceNbr()))
                            .equId(e)
                            .build())
                    .collect(Collectors.toList()));
        }
        List<JgResumeInfo> resumeInfos  =  Stream.concat(projectContraptionIds.stream(), notPipelineRecords.stream()).map(e-> JgResumeInfo.builder()
                .businessType(BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getName())
                .applyNo(jgChangeRegistrationName.getApplyNo())
                .businessId(jgChangeRegistrationName.getSequenceNbr() + "")
                .equId(e)
                .status("正常")
                .approvalUnitCode(jgChangeRegistrationName.getReceiveCompanyCode())
                .approvalUnit(jgChangeRegistrationName.getReceiveOrgName())
                .changeContent(BusinessTypeEnum.JG_NAME_CHANGE_REGISTRATION.getName() + "业务办理")
                .routePath(routePath)
                .build()).collect(Collectors.toList());
        jgResumeInfoService.saveBatchResume(resumeInfos);
    }

    public Map<String, Object> getTableData(JgUseRegistrationManageDto dto) {
        HashMap<String, Object> data = new HashMap<>();
        List<JgUseRegistrationManageDto> jgUseRegistrationManageDtos = jgUseRegistrationManageService.queryByUseUnitCreditCode(dto);
        data.put("dataList", jgUseRegistrationManageDtos);
        return data;
    }

    public Map<String, Object> queryBySequenceNbr(Long sequenceNbr) {
        ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        Map<String, Object> resultMap = accessFeignService.getData(reginParams.getCompany().getCompanyCode()).getResult();
        String unitName = String.valueOf(resultMap.getOrDefault("unitName", ""));
        JgChangeRegistrationName jgChangeRegistrationName = new JgChangeRegistrationName();
        Map<String, Object> dtoMap = new HashMap<>();
        Map<String, Object> map = new HashMap<>();
        if (!Objects.isNull(sequenceNbr)) {
            jgChangeRegistrationName = this.baseMapper.selectById(sequenceNbr);
            this.doCompensate(jgChangeRegistrationName);
            jgChangeRegistrationName.setReceiveOrgCode(jgChangeRegistrationName.getReceiveCompanyCode() + "_" + jgChangeRegistrationName.getReceiveOrgName());
            // 页面可编辑（当前登录人是发起人）且符合这个 监管机构 false
            if (BaseController.COMPANY_TYPE_COMPANY.equals(reginParams.getCompany().getLevel())) {
                dtoMap.put("isInProvince", this.justIsInProvince(reginParams.getCompany().getCompanyCode()));
            } else {
                dtoMap.put("isInProvince", false);
            }
        } else {
            jgChangeRegistrationName.setUseUnitCreditCode(CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                    reginParams.getCompany().getCompanyCode().split("_")[1] :
                    reginParams.getCompany().getCompanyCode());
            jgChangeRegistrationName.setNewUseUnitName(unitName);
            jgChangeRegistrationName.setUseUnitName(reginParams.getCompany().getCompanyName());
            // 初始时：返回当前登录人的公司信息，用来判断是否新名称是否可编辑
            dtoMap.put("isInProvince", this.justIsInProvince(reginParams.getCompany().getCompanyCode()));
        }
        BeanUtil.copyProperties(jgChangeRegistrationName, dtoMap);
        dtoMap.put("changeCertificate", JSON.parseArray(jgChangeRegistrationName.getChangeCertificate()));
        dtoMap.put("otherAccessories", JSON.parseArray(jgChangeRegistrationName.getOtherAccessories()));
        // 查询历史数据中选择的使用登记证信息
        JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryService.lambdaQuery()
                .eq(JgRegistrationHistory::getCurrentDocumentId, sequenceNbr)
                .eq(JgRegistrationHistory::getIsDelete, false)
                .one();
        if (!ObjectUtils.isEmpty(jgRegistrationHistory)) {
            JSONObject jsonObject = JSONObject.parseObject(jgRegistrationHistory.getChangeData());
            JSONObject dataList = JSONObject.parseObject(jsonObject.get("jgRegistrationInfo").toString());
            dtoMap.put("dataList", dataList.get("dataList"));
        }
        map.put("jgRegistrationInfo", dtoMap);
        return map;
    }

    private Boolean justIsInProvince(String companyCode) {
        TzBaseEnterpriseInfo baseEnterpriseInfo = tzBaseEnterpriseInfoMapper.selectOne(new LambdaQueryWrapper<TzBaseEnterpriseInfo>().eq(TzBaseEnterpriseInfo::getUseCode, companyCode));
        if (baseEnterpriseInfo == null) {
            log.warn(companyCode + "无企业信息");
            return false;
        }
        String dataSource = baseEnterpriseInfo.getDataSources();
        String registerType = baseEnterpriseInfo.getRegisterType();
        String[] disabledDataSource = {"企业注册", "陕西省内企业"};
        String[] disabledRegisterType = {"企业单位"};
        // 省内的企业且类型为企业时
        return Arrays.asList(disabledDataSource).contains(dataSource) && Arrays.asList(disabledRegisterType).contains(registerType);
    }


    public Page<Map<String, Object>> getList(JgChangeRegistrationNameDto dto, String sort, Page<Map<String, Object>> page, List<String> roleIds, String superviseOrgCode, String client) {
        if (org.apache.commons.lang3.StringUtils.isNotBlank(dto.getReceiveOrgCode())) {
            String[] receiveOrgIdList = dto.getReceiveOrgCode().split("_");
            if (receiveOrgIdList.length > 1) {
                dto.setReceiveOrgCode(receiveOrgIdList[0]);
                dto.setReceiveCompanyCode(receiveOrgIdList[0]);
            }
        }
        SortVo sortMap = commonService.sortFieldConversion(sort);
        return this.baseMapper.getListPage(page, sortMap, dto, roleIds, superviseOrgCode, RequestContext.getExeUserId(), client);
    }

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

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

    @GlobalTransactional(rollbackFor = Exception.class, timeoutMills = 6000000)
    public void handleChangeRegistrationNameWrongData(String applyNo) {
        JgChangeRegistrationName jgChangeRegistrationName = this.baseMapper.selectOne(new LambdaQueryWrapper<JgChangeRegistrationName>()
                .in(JgChangeRegistrationName::getApplyNo, applyNo)
                .eq(JgChangeRegistrationName::getIsDelete, 0));
        WorkflowResultDto workflowResultDto = new WorkflowResultDto();
        workflowResultDto.setNextExecutorRoleIds(jgChangeRegistrationName.getNextExecutorIds());
        workflowResultDto.setNextTaskCode("已完成");
        workflowResultDto.setNextTaskId(jgChangeRegistrationName.getNextTaskId());
        workflowResultDto.setNextExecutorUserIds(jgChangeRegistrationName.getNextExecuteUserIds());

        jgChangeRegistrationName.setAuditStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
        jgChangeRegistrationName.setAuditPassDate(new Date());
        // 完成时 下一步骤可执行人清空
        jgChangeRegistrationName.setNextExecuteUserIds("");
        // 更新代办
        TaskV2Model taskV2Model = updateTaskModel(jgChangeRegistrationName, "0");
        // 修改业务信息
        List<String> recordList = updateInfoOther(taskV2Model, jgChangeRegistrationName);
        commonService.saveExecuteFlowData2Redis(jgChangeRegistrationName.getInstanceId(), this.buildInstanceRuntimeData(jgChangeRegistrationName));
        this.getBaseMapper().updateById(jgChangeRegistrationName);
        Lists.partition(recordList, ES_BATCH_SIZE)
                .forEach(batch -> updateEsData(batch, jgChangeRegistrationName));
        this.updateEnterpriseInfo(jgChangeRegistrationName);
    }
}
