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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.ImmutableMap;
import com.yeejoin.amos.boot.biz.common.annotation.FieldMapping;
import com.yeejoin.amos.boot.biz.common.annotation.ResultFieldMapping;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.enums.TcmUnitTypeEnum;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
import com.yeejoin.amos.boot.module.common.api.enums.ReginStepEnum;
import com.yeejoin.amos.boot.module.common.biz.refresh.DataRefreshEvent;
import com.yeejoin.amos.boot.module.jg.api.common.StringUtil;
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.*;
import com.yeejoin.amos.boot.module.jg.api.mapper.*;
import com.yeejoin.amos.boot.module.jg.api.service.IJgChangeRegistrationTransferEqService;
import com.yeejoin.amos.boot.module.jg.api.service.IJgChangeRegistrationTransferService;
import com.yeejoin.amos.boot.module.jg.api.vo.SortVo;
import com.yeejoin.amos.boot.module.jg.biz.config.LocalBadRequest;
import com.yeejoin.amos.boot.module.jg.biz.context.EquipUsedCheckStrategyContext;
import com.yeejoin.amos.boot.module.jg.biz.context.FlowingEquipRedisContext;
import com.yeejoin.amos.boot.module.jg.biz.edit.permission.FillingEditPermForCurrentUser;
import com.yeejoin.amos.boot.module.jg.biz.event.publisher.EventPublisher;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.*;
import com.yeejoin.amos.boot.module.ymt.api.entity.*;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
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.IdxBizJgRegisterInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.IdxBizJgSupervisionInfoMapper;
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.apache.commons.collections.CollectionUtils;
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.ObjectUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.Bean;
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 javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.yeejoin.amos.boot.module.jg.biz.service.impl.JgUseRegistrationServiceImpl.getAuditPassedDate;

/**
 * 移装变更登记登记服务实现类
 *
 * @author system_generator
 * @date 2023-12-20
 */
@Service
public class JgChangeRegistrationTransferServiceImpl extends BaseService<JgChangeRegistrationTransferDto, JgChangeRegistrationTransfer, JgChangeRegistrationTransferMapper> implements IJgChangeRegistrationTransferService, ICompensateFlowDataOfRedis<JgChangeRegistrationTransfer> {
    private static final String PROCESS_DEFINITION_KEY = "changeRegistrationTransfer";
    private static final String TABLE_PAGE_ID = "changeRegistrationTransfer";
    private final List<String> NOT_FLOWING_STATE = Arrays.asList("使用单位待提交", "一级受理已驳回", "使用单位已撤回", "已作废", "已完成");

    @Autowired
    RedisUtils redisUtils;
    @Autowired
    ICommonService iCommonService;
    @Autowired
    TzsServiceFeignClient tzsServiceFeignClient;
    @Autowired
    ICmWorkflowService icmWorkflowService;
    @Autowired
    CommonServiceImpl commonService;
    @Autowired
    private IJgChangeRegistrationTransferEqService jgChangeRegistrationTransferEqService;
    @Autowired
    private JgRegistrationHistoryServiceImpl jgRegistrationHistoryService;
    @Autowired
    private IIdxBizJgUseInfoService useInfoService;
    @Autowired
    private IdxBizJgUseInfoServiceImpl idxBizJgUseInfoService;
    @Autowired
    private IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoService;
    @Autowired
    private IdxBizJgFactoryInfoServiceImpl idxBizJgFactoryInfoService;
    @Autowired
    private JgChangeRegistrationReformEqMapper jgChangeRegistrationReformEqMapper;
    @Autowired
    private JgChangeRegistrationTransferEqMapper jgChangeRegistrationTransferEqMapper;
    @Autowired
    private JgUseRegistrationEqMapper jgUseRegistrationEqMapper;
    @Autowired
    private JgChangeRegistrationUnitEqMapper jgChangeRegistrationUnitEqMapper;
    @Autowired
    private JgChangeRegistrationNameEqMapper jgChangeRegistrationNameEqMapper;

    @Autowired
    private IdxBizJgRegisterInfoMapper idxBizJgRegisterInfoMapper;
    @Autowired
    private IdxBizJgSupervisionInfoMapper idxBizJgSupervisionInfoMapper;
    @Autowired
    private CommonServiceImpl commonServiceImpl;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private JgRegistrationHistoryMapper jgRegistrationHistoryMapper;
    @Autowired
    private JgUseRegistrationManageServiceImpl registrationManageService;
    @Autowired
    private SnowflakeIdUtil sequence;
    @Autowired
    private JgCertificateChangeRecordServiceImpl certificateChangeRecordService;
    @Autowired
    private JgCertificateChangeRecordEqServiceImpl certificateChangeRecordEqService;
    @Autowired
    private JgUseRegistrationManageServiceImpl useRegistrationManageService;
    @Autowired
    private IIdxBizJgOtherInfoService otherInfoService;
    @Autowired
    private EventPublisher eventPublisher;
    @Autowired
    private JgVehicleInformationMapper jgVehicleInformationMapper;

    @Autowired
    JgResumeInfoServiceImpl jgResumeInfoService;

    @Autowired
    private CommonMapper commonMapper;

    /**
     * 新增移装变更登记
     *
     * @param submitType
     * @param map
     * @return
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    @FieldMapping({
            @FieldMapping.FieldMap(paramIndex = 1, sourceField = "changeRegistrationTransfer.estateUnitSeq",
                    targetField = "changeRegistrationTransfer.transferUseInfo",
                    serviceClass = CommonServiceImpl.class,
                    queryMethod = "queryTcmUnitCreditCodeAndNameBySeq",
                    secondParamValue = "CQ"
            )
    })
    public List<JgChangeRegistrationTransferDto> createTransfer(String submitType, JSONObject map, ReginParams reginParams) {
        try {
            Map<String, Object> tableData = (Map<String, Object>) map.get(TABLE_PAGE_ID);
            if (ValidationUtil.isEmpty(tableData)) {
                throw new BadRequest("参数校验失败.");
            }
            List<Map<String, Object>> registrationList = (List<Map<String, Object>>) tableData.get("registrationList");
            if (CollectionUtils.isEmpty(registrationList)) {
                throw new BadRequest("使用登记证不能为空!");
            }

            //根据使用登记证查询设备
            List<Long> registrationIdList = registrationList.stream()
                    .map(objectMap -> objectMap.get("sequenceNbr"))
                    .filter(Objects::nonNull)
                    .map(Object::toString)
                    .filter(this::canConvertToLong)
                    .map(Long::parseLong)
                    .collect(Collectors.toList());

            List<String> registrationNoList = registrationList.stream()
                    .map(objectMap -> objectMap.get("useRegistrationCode"))
                    .filter(Objects::nonNull)
                    .map(Object::toString)
                    .collect(Collectors.toList());

            if (CollectionUtils.isEmpty(registrationIdList)) {
                throw new BadRequest("使用登记证不能为空");
            }

            if ("1".equals(submitType)) {
                this.repeatUsedEquipCheck(registrationIdList,
                        CompanyTypeEnum.INDIVIDUAL.getName().equals(reginParams.getCompany().getCompanyType()) ?
                                reginParams.getCompany().getCompanyCode().split("_")[1] :
                                reginParams.getCompany().getCompanyCode());
            }

            //查询证下的设备
            List<JSONObject> deviceList = registrationManageService.queryEquByCertificateSeqList(registrationIdList);
            // 获取单位变更设备列表
            if (CollectionUtils.isEmpty(deviceList)) {
                throw new BadRequest("使用登记证下无设备");
            }

            String fullAddress = "";
            String province = (String) tableData.get("transferProvince");
            String city = (String) tableData.get("transferCity");
            String county = (String) tableData.get("transferCounty");
            String street = (String) tableData.get("transferStreet");
            String address = (String) tableData.get("transferAddress");
            //区内移装，需判断是否为同一地市，如果不是同一地市，返回异常 -> 610000#610200#610204#610204002
            if ("0".equals(tableData.get("transferType"))) {
                deviceList.forEach(device -> {
                    Object usePlaceCodeObj = device.get("USE_PLACE_CODE");
                    if (usePlaceCodeObj == null) {
                        throw new BadRequest("没有查询到地市信息");
                    }
                    String deviceCity = Arrays.stream(((String) usePlaceCodeObj).split("#"))
                            .skip(1)
                            .findFirst()
                            .orElseThrow(() -> new BadRequest("没有查询到地市信息"));

                    if (city == null || deviceCity == null) {
                        throw new BadRequest("请选择地市后暂存！");
                    }

                    String[] parts = city.split("_");
                    if (parts.length == 0 || !parts[0].equals(deviceCity)) {
                        throw new BadRequest("区内移装只能选择与设备地址中相同地市进行移装！");
                    }
                });
            } else {
                deviceList.forEach(device -> {
                    Object usePlaceCodeObj = device.get("USE_PLACE_CODE");
                    if (usePlaceCodeObj == null) {
                        throw new BadRequest("没有查询到地市信息");
                    }
                    String deviceCity = Arrays.stream(((String) usePlaceCodeObj).split("#"))
                            .skip(1)
                            .findFirst()
                            .orElseThrow(() -> new BadRequest("没有查询到地市信息"));

                    if (city.split("_")[0].equals(deviceCity)) {
                        throw new BadRequest("区外移装只能选择与设备地址中不同地市进行移装！");
                    }
                });
            }

            CompanyBo company = reginParams.getCompany();
            String sequenceNbr = MapUtil.getStr(tableData,"sequenceNbr");
            String receiveOrgCode = (String) tableData.get("receiveOrgCode");
            String receiveOrgName = "";

            //移装变更数据
            JgChangeRegistrationTransfer oldTransfer = new JgChangeRegistrationTransfer();

            if (!ValidationUtil.isEmpty(receiveOrgCode)) {
                String[] receiveOrgCodeList = receiveOrgCode.split("_");
                if (receiveOrgCodeList.length > 1) {
                    receiveOrgCode = receiveOrgCodeList[0];
                    receiveOrgName = receiveOrgCodeList[1];
                }
            }

            //有sequenceNbr代表修改数据
            if (!ValidationUtil.isEmpty(sequenceNbr)) {
                //查询移装变更记录
                oldTransfer = this.getById(sequenceNbr);
                // 删除以前设备关联关系
                LambdaQueryWrapper<JgChangeRegistrationTransferEq> lambda = new QueryWrapper<JgChangeRegistrationTransferEq>().lambda();
                lambda.eq(JgChangeRegistrationTransferEq::getEquipTransferId, sequenceNbr);
                jgChangeRegistrationTransferEqService.getBaseMapper().delete(lambda);
                jgRegistrationHistoryService.getBaseMapper().delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                        .eq(JgRegistrationHistory::getCurrentDocumentId, oldTransfer.getApplyNo()));
            } else {
                //查询申请单号
                ResponseModel<List<String>> result = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.getCode.get(String.valueOf(tableData.get("businessCode"))), 1);
                if (!result.getResult().isEmpty()) {
                    //申请编号
                    oldTransfer.setApplyNo(result.getResult().get(0));
                } else {
                    throw new BadRequest("申请单编号生成失败,请稍后重试!");
                }
            }

            //登记类别
            oldTransfer.setRegType("移装登记");
            //注册登记日期
            oldTransfer.setRegDate(new Date());
            //使用机构
            oldTransfer.setUseUnitCreditCode(CompanyTypeEnum.INDIVIDUAL.getName().equals(company.getCompanyType()) ?
                    company.getCompanyCode().split("_")[1] : company.getCompanyCode());
            oldTransfer.setUseUnitName(company.getCompanyName());
            //录入单位统一信用代码
            oldTransfer.setInputUnitNo(company.getCompanyCode());
            // 创建人ID
            oldTransfer.setCreateUserId(reginParams.getUserModel().getUserId());

            //登记机构代码
            //登记机构公司代码
            if (!ValidationUtil.isEmpty(receiveOrgCode)) {
                oldTransfer.setReceiveOrgCode(receiveOrgCode);
                oldTransfer.setReceiveCompanyCode(receiveOrgCode);
            } else {
                oldTransfer.setReceiveOrgCode("610000");
                oldTransfer.setReceiveCompanyCode("610000");
            }
            //登记机构
            if (!ValidationUtil.isEmpty(receiveOrgName)) {
                oldTransfer.setReceiveOrgName(receiveOrgName);
            }
            //办理状态
            oldTransfer.setAuditStatus(WorkFlowStatusEnum.TRANSFER_SUBMIT.getPass());
            oldTransfer.setStatus(WorkFlowStatusEnum.TRANSFER_SUBMIT.getPass());
            // 统计使用
            CompanyBo companyBo = commonServiceImpl.getOneCompany(oldTransfer.getReceiveCompanyCode());
            oldTransfer.setReceiveCompanyOrgCode(companyBo.getOrgCode());
            oldTransfer.setUseRegistrationCode(String.join("，", registrationNoList));

            // 分割省市区街道字段
            if (!ObjectUtils.isEmpty(province)) {
                String[] provinceList = province.split("_");
                if (provinceList.length > 1) {
                    fullAddress += provinceList[1];
                }
            }
            if (!ObjectUtils.isEmpty(city)) {
                String[] cityList = city.split("_");
                if (cityList.length > 1) {
                    fullAddress += cityList[1];
                }
            }
            if (!ObjectUtils.isEmpty(county)) {
                String[] countyList = county.split("_");
                if (countyList.length > 1) {
                    fullAddress += countyList[1];
                }
            }
            if (!ObjectUtils.isEmpty(street)) {
                String[] streetList = street.split("_");
                if (streetList.length > 1) {
                    fullAddress += streetList[1];
                }
            }
            if (!ObjectUtils.isEmpty(address)) {
                fullAddress += address;
            }
            //设备移装详细地址
            oldTransfer.setFullAddress(fullAddress);
            oldTransfer.setTransferType((String) tableData.get("transferType"));
            oldTransfer.setEquipListName(Optional.of(deviceList)
                    .flatMap(list -> list.stream()
                            .findFirst()
                            .map(json -> json.getString("EQU_LIST")))
                    .orElse(""));
            if (!ObjectUtils.isEmpty(tableData.get("otherAccessories"))) {
                oldTransfer.setOtherAccessories(JSONObject.toJSONString(tableData.get("otherAccessories")));
            }
            oldTransfer.setCreateDate(new Date());
            //保存【移装变更登记】基本信息
            if (!ValidationUtil.isEmpty(oldTransfer)) {
                this.saveOrUpdate(oldTransfer);
            }

            // 产权单位
            // 使用用户输入的产权单位信息未查询到数据，则保存新的产权单位信息
            if (!ValidationUtil.isEmpty(tableData.get("estateUnitSeq"))) {
                String estateUnitSeq = String.valueOf(tableData.get("estateUnitSeq"));
                Map<String, String> propertyUnitInfo = commonService.queryTcmUnitInfoBySeq(estateUnitSeq, TcmUnitTypeEnum.CQ.getCode());
                tableData.put("estateUnitCode", propertyUnitInfo.get("unitCode"));
                tableData.put("estateUnitName", propertyUnitInfo.get("unitName"));
            }

            JgChangeRegistrationTransfer finalOldTransfer = oldTransfer;
            List<JgChangeRegistrationTransferEq> oldTransferEqList = new ArrayList<>(Collections.emptyList());
            deviceList.forEach(device -> {
                JgChangeRegistrationTransferEq equip = new JgChangeRegistrationTransferEq();
                equip.setEquipTransferId(String.valueOf(finalOldTransfer.getSequenceNbr()));
                equip.setEquId((String) device.get("SEQUENCE_NBR"));
                equip.setEquList((String) device.get("EQU_LIST_CODE"));
                equip.setEquCategory((String) device.get("EQU_CATEGORY_CODE"));
                equip.setEquDefine((String) device.get("EQU_DEFINE_CODE"));
                equip.setDeviceInfo(JSONObject.toJSONString(device));
                equip.setUseRegistrationCode((String) device.get("USE_ORG_CODE"));
                oldTransferEqList.add(equip);
            });
            jgChangeRegistrationTransferEqService.saveBatch(oldTransferEqList);
            JgRegistrationHistory oldHistory = new JgRegistrationHistory();
            oldHistory.setUseRegistrationCode(finalOldTransfer.getUseRegistrationCode());
            oldHistory.setRegistrationClass("移装变更登记");
            oldHistory.setChangeData(JSONObject.toJSONString(tableData));
            oldHistory.setCurrentDocumentId(finalOldTransfer.getApplyNo());
            oldHistory.setStatus("new");
            jgRegistrationHistoryService.saveOrUpdateHistoryData(oldHistory);

            //发起流程
            if ("1".equals(submitType)) {
                String instanceId = "";

                if (!ValidationUtil.isEmpty(oldTransfer.getSequenceNbr()) && !ValidationUtil.isEmpty(oldTransfer.getInstanceId())) {
                    this.flowExecute(oldTransfer.getSequenceNbr(), oldTransfer.getInstanceId(), "0", "", String.valueOf(map.get("nextTaskId")));
                } else {
                    // 如果是新启动的流程开启自动访问
                    String equipListName = jgVehicleInformationMapper.getEquCategoryNameByCode(Objects.toString(tableData.get("equListCode")));
                    oldTransfer.setAuditStatus(WorkFlowStatusEnum.TRANSFER_RECEIVE.getPass());
                    oldTransfer.setStatus(WorkFlowStatusEnum.TRANSFER_RECEIVE.getPass());
                    oldTransfer.setEquipListName(equipListName);
                    oldTransfer.setCreateUserId(reginParams.getUserModel().getUserId());
                    oldTransfer.setCreateUserName(reginParams.getUserModel().getRealName());
                    oldTransfer.setCreateUserCompanyName(reginParams.getCompany().getCompanyName());
                    //启动流程
                    WorkflowResultDto workflowResult = this.startWorkFlow(oldTransfer.getReceiveCompanyCode());

                    this.updateExecuteIds(instanceId, oldTransfer, "startWorkflow", workflowResult);
                    //删除旧的代办
                    commonService.deleteTasksByRelationId(oldTransfer.getSequenceNbr().toString());
                    //生成代办
                    this.createToDoTask(Collections.singletonList(workflowResult), oldTransfer, submitType);
                }
            } else {
                List<TaskModelDto> modelDtoList = new ArrayList<>();
                TaskModelDto dto = new TaskModelDto();
                dto.setModel(oldTransfer);
                dto.setTaskContent(this.getSummaryInfo(oldTransfer));
                dto.setTaskCode(oldTransfer.getApplyNo());
                dto.setTaskType(BusinessTypeEnum.JG_CHANGE_REGISTRATION.getCode());
                dto.setRelationId(oldTransfer.getSequenceNbr() + "");
                modelDtoList.add(dto);
                commonService.buildTaskModel(modelDtoList);
            }

            JgChangeRegistrationTransferDto resultDto = new JgChangeRegistrationTransferDto();
            Bean.copyExistPropertis(oldTransfer, resultDto);
            //组装返回信息，添加设备信息的展示
            resultDto.setEquCategory((String) tableData.get("equCategoryDesc"));
            resultDto.setProductName((String) tableData.get("productName"));
            resultDto.setAllAddress(oldTransfer.getFullAddress());
            resultDto.setEquCode((String) tableData.get("equCode"));
            resultDto.setInnerCode((String) tableData.get("useInnerCode"));
            return Collections.singletonList(resultDto);
        } 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();
        }
    }

    /**
     * 修改移装变更登记
     *
     * @param map
     * @return
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public List<JgChangeRegistrationTransferDto> updateTransfer(String submitType, JSONObject map, ReginParams reginParams) {
        return this.createTransfer(submitType, map, reginParams);
    }

    public boolean canConvertToLong(String str) {
        try {
            Long.parseLong(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 执行流程
     *
     * @param id
     * @param instanceId
     * @param operate
     * @param comment
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    @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);

            WorkflowResultDto workflowResult;
            JgChangeRegistrationTransfer transfer = this.getById(id);

            String taskId = transfer.getNextTaskId();
            //组装信息
            TaskResultDTO dto = new TaskResultDTO();
            dto.setResultCode("approvalStatus");
            dto.setTaskId(taskId);
            dto.setComment(comment);
            HashMap<String, Object> map = new HashMap<>();
            map.put("approvalStatus", operate);
            dto.setVariable(map);
            //下一节点执行人单位（下节点接收机构code）
            dto.setNextExecuteUserCompanyCode(this.getNextUserOrgCode(operate, transfer));
            if (!ObjectUtils.isEmpty(transfer) && (transfer.getStatus().equals(WorkFlowStatusEnum.TRANSFER_SUBMIT.getRollBack()) || transfer.getStatus().equals(WorkFlowStatusEnum.TRANSFER_SUBMIT.getReject()))) {
                map.put("approvalStatus", "提交");
            }
            //执行流程
            ProcessTaskDTO complete = icmWorkflowService.completeOrReject(taskId, dto, operate);
            workflowResult = commonService.buildWorkFlowInfo(Collections.singletonList(complete)).get(0);
            // 更新下一步执行人
            this.updateExecuteIds(instanceId, transfer, operate, workflowResult);
            delRepeatUseEquipData(transfer);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 流程撤回
     *
     * @param instanceId
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void revocation(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("当前流程已经被执行！请重新打开页面查看并执行！");
            }
            // 撤回校验
            commonServiceImpl.checkForRevocationFlow(nextTaskId, instanceId);

            ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);

            JgChangeRegistrationTransfer jgTransfer;
            LambdaQueryWrapper<JgChangeRegistrationTransfer> lambda = new QueryWrapper<JgChangeRegistrationTransfer>().lambda();
            lambda.eq(JgChangeRegistrationTransfer::getInstanceId, instanceId);
            jgTransfer = this.getOne(lambda);
            ProcessTaskDTO processTask = icmWorkflowService.rollBack(instanceId);
            WorkflowResultDto workflowResult = commonService.buildWorkFlowInfo(Collections.singletonList(processTask)).get(0);
            String taskCode = "";
            String role = "";
            if (!ValidationUtil.isEmpty(workflowResult)) {
                taskCode = Optional.ofNullable(workflowResult.getNextTaskCode()).orElse("");
                role = Optional.ofNullable(workflowResult.getNextExecutorRoleIds()).orElse("");
                jgTransfer.setNextTaskId(workflowResult.getNextTaskId());
                // 更新下一步可执行人
                jgTransfer.setNextExecuteUserIds(workflowResult.getNextExecutorUserIds());
            }
            if (!ObjectUtils.isEmpty(taskCode)) {
                jgTransfer.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getRollBack());
                jgTransfer.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getRollBack());
            }
            jgTransfer.setPromoter(reginParams.getUserModel().getUserId());
            jgTransfer.setNextExecutorIds(role);
            this.updateById(jgTransfer);
            //待办 撤回
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(jgTransfer));
            jsonObject.put("flowStatus", commonService.getDictionaryCodeByName(jgTransfer.getAuditStatus()));
            jsonObject.put("flowStatusLabel", jgTransfer.getAuditStatus());
            jsonObject.put("nextTaskId", jgTransfer.getNextTaskId());
            jsonObject.put("nextExecuteUser", jgTransfer.getNextExecutorIds());
            jsonObject.put("taskType", BusinessTypeEnum.JG_CHANGE_REGISTRATION.getCode());
            // 判断撤回后当前的节点，如果当前节点为提交节点则页面可编辑
            jsonObject.put("pageType", this.getPageTypeByCurrentNode(jgTransfer.getAuditStatus()));
            commonService.rollbackTask(instanceId, jsonObject);

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

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

    /**
     * 批量删除
     *
     * @param sequenceNbrs
     * @return
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    public boolean deleteBatchBySequenceNbrs(Long[] sequenceNbrs) {
        if (Objects.isNull(sequenceNbrs) || sequenceNbrs.length == 0) {
            return false;
        }
        try {
            for (Long sequenceNbr : sequenceNbrs) {
                JgChangeRegistrationTransfer registrationTransfer = this.baseMapper.selectById(sequenceNbr);
                // 删除代办 + 中止流程
                commonService.deleteTaskModel(String.valueOf(sequenceNbr), registrationTransfer.getInstanceId());
                // 删除单子
                this.baseMapper.deleteById(sequenceNbr);
                // 删除单子对应eq
                jgChangeRegistrationTransferEqMapper.delete(new LambdaQueryWrapper<JgChangeRegistrationTransferEq>()
                        .eq(JgChangeRegistrationTransferEq::getEquipTransferId, sequenceNbr));
                // 删除单子对应历史表数据
                jgRegistrationHistoryMapper.delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                        .eq(JgRegistrationHistory::getCurrentDocumentId, registrationTransfer.getApplyNo()));
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 根据移装变更记录sequenceNbr查询详情
     *
     * @param sequenceNbr 变更记录sequenceNbr
     * @param company
     * @return
     */
    @Override
    @ResultFieldMapping({
            @ResultFieldMapping.ResultFieldMap(sourceField = "changeRegistrationTransfer.transferUseInfo",
                    targetField = "changeRegistrationTransfer.estateUnitSeq",
                    serviceClass = CommonServiceImpl.class,
                    queryMethod = "queryTcmUnitSeqByCreditCode",
                    secondParamValue = "CQ"
            )
    })
    public Map<String, Map<String, Object>> getTransferDetail(String sequenceNbr, CompanyBo company) {
        Map<String, Map<String, Object>> pageDataMap = new HashMap<>();
        Map<String, Object> resultDataMap = new HashMap<>();
        //移装变更详情
        JgChangeRegistrationTransfer transfer = this.getById(sequenceNbr);
        this.doCompensate(transfer);
        //查询设备详情
        JgRegistrationHistory historyData = jgRegistrationHistoryMapper.selectOne(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getCurrentDocumentId, transfer.getApplyNo())
                .eq(JgRegistrationHistory::getIsDelete, false));
        if (ValidationUtil.equals(FlowStatusEnum.TO_BE_FINISHED.getName(), transfer.getStatus())) {
            // 执行完成时查询历史表
            if (!ValidationUtil.isEmpty(historyData)) {
                Map<String, Object> newPosition = JSON.parseObject(historyData.getChangeData(), Map.class);
                resultDataMap.putAll(newPosition);
                if (!ValidationUtil.isEmpty(transfer)) {
                    Map<String, Object> transferToMap = Bean.BeantoMap(transfer);
                    transferToMap.put("receiveCompanyCode", transfer.getReceiveCompanyCode() + "_" + transfer.getReceiveOrgName());
                    resultDataMap.putAll(transferToMap);
                }
            }
        } else {
            // 非执行完成状态显示最新设备信息
            Map<String, Object> changeData = JSON.parseObject(historyData.getChangeData(), Map.class);
            List<String> ids = ((List<?>) changeData.get("registrationList")).stream()
                    .map(obj -> ((JSONObject) obj).getString("sequenceNbr"))
                    .collect(Collectors.toList());
            List<JgUseRegistrationManage> newRegistrationList = useRegistrationManageService.lambdaQuery()
                    .in(BaseEntity::getSequenceNbr, ids)
                    .list();
            if (!ValidationUtil.isEmpty(transfer)) {
                Map<String, Object> transferToMap = Bean.BeantoMap(transfer);
                resultDataMap.putAll(transferToMap);
            }
            // 省市区街道字段等业务字段
            resultDataMap.put("transferProvince", changeData.get("transferProvince"));
            resultDataMap.put("transferCity", changeData.get("transferCity"));
            resultDataMap.put("transferCounty", changeData.get("transferCounty"));
            resultDataMap.put("transferStreet", changeData.get("transferStreet"));
            resultDataMap.put("transferUsePlace", changeData.get("transferUsePlace"));
            resultDataMap.put("transferAddress", changeData.get("transferAddress"));
            resultDataMap.put("transferLongitudeLatitude", changeData.get("transferLongitudeLatitude"));
            resultDataMap.put("orgBranchCode", changeData.get("orgBranchCode"));
            resultDataMap.put("orgBranchName", changeData.get("orgBranchName"));
            resultDataMap.put("transferIsXixian", changeData.get("transferIsXixian"));
            resultDataMap.put("transferSafetyManager", changeData.get("transferSafetyManager"));
            resultDataMap.put("transferPhone", changeData.get("transferPhone"));
            resultDataMap.put("transferUseInfo", changeData.get("transferUseInfo"));
            //resultDataMap.put("useInnerCode", equipDetailMap.get("equCode"));
            resultDataMap.put("receiveCompanyCode", transfer.getReceiveCompanyCode() + "_" + transfer.getReceiveOrgName());
            resultDataMap.put("registrationList", newRegistrationList);
        }
        if (!ObjectUtils.isEmpty(resultDataMap.get("otherAccessories"))) {
            resultDataMap.put("otherAccessories", JSONObject.parse(resultDataMap.get("otherAccessories").toString()));
        }
        String transferSafetyManager = Optional.ofNullable(resultDataMap.get("transferSafetyManager")).orElse("").toString();
        if (StringUtil.isNotEmpty(transferSafetyManager)) {
            String[] transferSafetyManagerList = transferSafetyManager.split("_");
            if (transferSafetyManagerList.length > 1) {
                resultDataMap.put("transferSafetyManagerName", transferSafetyManagerList[1]);
            }
        }
        new FillingEditPermForCurrentUser(new JSONObject(resultDataMap), company, BusinessTypeEnum.JG_EQUIPMENT_HANDOVER).getData();
        if (!resultDataMap.isEmpty()) {
            pageDataMap.put(TABLE_PAGE_ID, resultDataMap);
        }
        return pageDataMap;
    }


    private void repeatUsedEquipCheck(List<Long> equipList, String companyCode) {
        equipList.forEach(equipMap -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                .registrationRepeatUsedCheck(String.valueOf(equipMap), companyCode));
    }

    /**
     * 删除 redis校验重复引用设备的数据
     */
    private void delRepeatUseEquipData(JgChangeRegistrationTransfer transfer) {
        if (NOT_FLOWING_STATE.contains(transfer.getAuditStatus())) {
            JgRegistrationHistory historyData = jgRegistrationHistoryMapper.selectOne(new LambdaQueryWrapper<JgRegistrationHistory>()
                    .eq(JgRegistrationHistory::getCurrentDocumentId, transfer.getApplyNo())
                    .eq(JgRegistrationHistory::getIsDelete, false));
            JSONObject historyJson = JSON.parseObject(historyData.getChangeData());
            List<Map<String, Object>> registrationList = (List<Map<String, Object>>) historyJson.get("registrationList");
            List<String> ids = registrationList.stream().map(v -> JSON.parseObject(v.toString()).getString("sequenceNbr")).collect(Collectors.toList());
            ids.forEach(id -> EquipUsedCheckStrategyContext.getUsedStrategy(PROCESS_DEFINITION_KEY)
                    .delDataForCheckEquipRepeatUsed(Collections.singletonList(id), transfer.getUseUnitCreditCode())
            );
        }
    }

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

    /**
     * 分页查询
     *
     * @param page
     * @param params
     * @param companyTypeCode
     * @param companyType
     * @return
     */
    @Override
    public Page<Map<String, Object>> queryListForPage(Page<Map<String, Object>> page, String sort, JgChangeRegistrationTransferDto params, String companyTypeCode, String companyType, String orgCode) {
        SortVo sortMap = commonService.sortFieldConversion(sort);
        Page<Map<String, Object>> listPage = this.baseMapper.getListPage(page, sortMap, params, companyTypeCode, RequestContext.getExeUserId(), orgCode);
        listPage.getRecords().forEach(x -> x.put("companyType", companyType));
        return listPage;
    }

    public void updateExecuteIds(String instanceId, JgChangeRegistrationTransfer jgChangeRegistrationTransfer, String operate, WorkflowResultDto workflowResult) {
        Boolean updateTodoAndCreate = Boolean.TRUE;
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);

        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
        if (!ObjectUtils.isEmpty(workflowResult.getNextTaskCode())) {
            taskCode = Optional.ofNullable(workflowResult.getNextTaskCode()).orElse("");
        }
        String role = Optional.ofNullable(workflowResult.getNextExecutorRoleIds()).orElse("");

        if (operate.equals("startWorkflow")) {
            role = Optional.ofNullable(workflowResult.getExecutorRoleIds()).orElse("") + "," + Optional.ofNullable(workflowResult.getNextExecutorRoleIds()).orElse("");
            operate = "0";
            instanceId = workflowResult.getInstanceId();
            updateTodoAndCreate = Boolean.FALSE;
        }

        if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(taskCode)) {
            jgChangeRegistrationTransfer.setInstanceId(instanceId);
            jgChangeRegistrationTransfer.setNextTaskId(workflowResult.getNextTaskId());
            jgChangeRegistrationTransfer.setNextExecutorIds(role);
            //更新下一步可执行人
            jgChangeRegistrationTransfer.setNextExecuteUserIds(workflowResult.getNextExecutorUserIds());

            if (!ObjectUtils.isEmpty(jgChangeRegistrationTransfer.getInstanceStatus())) {
                jgChangeRegistrationTransfer.setInstanceStatus(jgChangeRegistrationTransfer.getInstanceStatus() + "," + role);
            } else {
                jgChangeRegistrationTransfer.setInstanceStatus(role);
            }

            if ("0".equals(operate)) {
                // 通过操作
                jgChangeRegistrationTransfer.setPromoter(reginParams.getUserModel().getUserId());
                jgChangeRegistrationTransfer.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
                jgChangeRegistrationTransfer.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
            } else {
                // 驳回操作
                jgChangeRegistrationTransfer.setAuditStatus(WorkFlowStatusEnum.getMessage(taskCode).getReject());
                jgChangeRegistrationTransfer.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getReject());
                jgChangeRegistrationTransfer.setPromoter("");
            }

            if (updateTodoAndCreate) {
                // 上个代办改为已办
                HashMap<String, Object> map = new HashMap<>();
                if ("0".equals(operate)) {
                    map.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
                    map.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
                } else {
                    map.put("taskStatus", FlowStatusEnum.REJECTED.getCode());
                    map.put("taskStatusLabel", FlowStatusEnum.REJECTED.getName());
                }
                map.put("flowStatus", commonService.getDictionaryCodeByName(jgChangeRegistrationTransfer.getStatus()));
                map.put("flowStatusLabel", jgChangeRegistrationTransfer.getStatus());
                map.put("relationId", jgChangeRegistrationTransfer.getInstanceId());
                TaskV2Model taskV2Model = commonService.updateTaskModelNew(map);
                if (!ValidationUtil.isEmpty(taskV2Model)) {
                    TaskModelDto taskModelDto = new TaskModelDto();
                    BeanUtils.copyProperties(taskV2Model, taskModelDto);
                    // 创建新的代办
                    taskModelDto.setTaskName(workflowResult.getNextTaskName());
                    taskModelDto.setExecuteUserIds(workflowResult.getNextExecutorUserIds());
                    taskModelDto.setTaskStatus(FlowStatusEnum.TO_BE_PROCESSED.getCode());
                    taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskModelDto.setNextExecuteUser(workflowResult.getNextExecutorRoleIds());
                    taskModelDto.setTaskType(BusinessTypeEnum.JG_CHANGE_REGISTRATION.getCode());
                    taskModelDto.setTaskTypeLabel(BusinessTypeEnum.JG_CHANGE_REGISTRATION.getName());
                    taskModelDto.setRelationId(instanceId);
                    taskModelDto.setFlowCode(jgChangeRegistrationTransfer.getNextTaskId());
                    TaskMessageDto taskMessageDto = new TaskMessageDto();
                    BeanUtil.copyProperties(jgChangeRegistrationTransfer, taskMessageDto);
                    taskModelDto.setPageType(this.getPageTypeByCurrentNode(jgChangeRegistrationTransfer.getAuditStatus()));
                    taskModelDto.setModel(taskMessageDto);
                    commonService.buildTaskModel(Collections.singletonList(taskModelDto));
                }
            }
        } else {
            jgChangeRegistrationTransfer.setAuditPassDate(new Date());
            jgChangeRegistrationTransfer.setAuditStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
            jgChangeRegistrationTransfer.setStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
            jgChangeRegistrationTransfer.setNextTaskId(null);
            //更新下一步可执行人
            jgChangeRegistrationTransfer.setNextExecuteUserIds("");
            //流程执行完成后，更新设备使用信息
            JgRegistrationHistory historyData = jgRegistrationHistoryMapper.selectOne(new LambdaQueryWrapper<JgRegistrationHistory>()
                    .eq(JgRegistrationHistory::getCurrentDocumentId, jgChangeRegistrationTransfer.getApplyNo())
                    .eq(JgRegistrationHistory::getIsDelete, false));
            this.updateByFlowEnd(jgChangeRegistrationTransfer.getSequenceNbr().toString(), historyData);
            HashMap<String, Object> map = new HashMap<>();
            map.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
            map.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
            map.put("flowStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
            map.put("flowStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
            map.put("relationId", jgChangeRegistrationTransfer.getInstanceId());
            map.put("model", jgChangeRegistrationTransfer);
            TaskV2Model taskV2Model = commonService.updateTaskModel(map);
            // 新增使用登记证和设备变更记录
            this.saveChangeRecord(jgChangeRegistrationTransfer, taskV2Model);
            // 事务提交后发送数据刷新消息
            this.sendDataRefreshMsg(jgChangeRegistrationTransfer);
            //  创建设备履历
            this.createResume( jgChangeRegistrationTransfer, taskV2Model.getRoutePath());
        }
        // redis流程实时数据更新
        commonServiceImpl.saveExecuteFlowData2Redis(instanceId, this.buildInstanceRuntimeData(jgChangeRegistrationTransfer));
        this.getBaseMapper().updateById(jgChangeRegistrationTransfer);
    }

    private void createResume(JgChangeRegistrationTransfer jgChangeRegistrationTransfer, String routePath) {
        LambdaQueryWrapper<JgChangeRegistrationTransferEq> lambda = new QueryWrapper<JgChangeRegistrationTransferEq>().lambda();
        lambda.eq(JgChangeRegistrationTransferEq::getEquipTransferId, jgChangeRegistrationTransfer.getSequenceNbr());
        List<JgChangeRegistrationTransferEq> changeRegistrationTransferEqs = jgChangeRegistrationTransferEqService.getBaseMapper().selectList(lambda);
        jgResumeInfoService.saveBatchResume(changeRegistrationTransferEqs.stream().map(eq-> JgResumeInfoDto.builder().applyNo(jgChangeRegistrationTransfer.getApplyNo())
                .businessType(BusinessTypeEnum.JG_CHANGE_REGISTRATION.getName())
                .businessId(String.valueOf(jgChangeRegistrationTransfer.getSequenceNbr()))
                .equId(eq.getEquId())
                .approvalUnit(jgChangeRegistrationTransfer.getReceiveOrgName())
                .approvalUnitCode(jgChangeRegistrationTransfer.getReceiveCompanyCode())
                .status("正常")
                .changeContent(BusinessTypeEnum.JG_CHANGE_REGISTRATION.getName() + "业务办理")
                .routePath(routePath)
                .build()).collect(Collectors.toList())
        );
    }

    private void sendDataRefreshMsg(JgChangeRegistrationTransfer jgChangeRegistrationTransfer) {
        LambdaQueryWrapper<JgChangeRegistrationTransferEq> lambda = new QueryWrapper<JgChangeRegistrationTransferEq>().lambda();
        lambda.eq(JgChangeRegistrationTransferEq::getEquipTransferId, jgChangeRegistrationTransfer.getSequenceNbr());
        List<String> records = jgChangeRegistrationTransferEqService.getBaseMapper().selectList(lambda).stream().map(JgChangeRegistrationTransferEq::getEquId).collect(Collectors.toList());
        eventPublisher.publish(new DataRefreshEvent(this, records, DataRefreshEvent.DataType.equipment.name(), DataRefreshEvent.Operation.UPDATE));
    }

    private Map<String, String> create96333Code(JgRegistrationHistory historyData, String record) {
        Map<String, Object> changeData = JSON.parseObject(historyData.getChangeData(), Map.class);
        List<JSONObject> registrationList = (List<JSONObject>) changeData.get("registrationList");
        IdxBizJgOtherInfo otherInfo = otherInfoService.getOneData(record);
        String superviseCode = otherInfo.getSupervisoryCode();
        String equListCode = Optional.ofNullable(registrationList)
                .flatMap(list -> list.stream()
                        .findFirst()
                        .map(json -> json.getString("equListCode")))
                .orElse("");
        // 非电梯不生成96333码
        if (!EquipmentClassifityEnum.DT.getCode().equals(equListCode)) {
            return ImmutableMap.<String, String>builder()
                    .put("superviseCode", superviseCode)
                    .build();
        }
        String equCategoryCode = Optional.ofNullable(registrationList)
                .flatMap(list -> list.stream()
                        .findFirst()
                        .map(json -> json.getString("equCategoryCode")))
                .orElse("");

        String cityCode = Optional.ofNullable((String) changeData.get("transferCity"))
                .map(s -> s.split("_")[0])
                .orElse("");
        String countyCode = Optional.ofNullable((String) changeData.get("transferCounty"))
                .map(s -> s.split("_")[0])
                .orElse("");
        String isXiXian = "0".equals(changeData.get("transferIsXixian")) ? "null" : "1";
        // 移转不需要重新生成监管码，只需要新生成96333码，接口上送superviseCode则不再生成监管码
        ImmutableMap<String, Object> map = ImmutableMap.<String, Object>builder()
                .put("cityCode", cityCode)
                .put("countyCode", countyCode)
                .put("equCategory", equCategoryCode)
                .put("isXiXian", isXiXian)
                .put("superviseCode", superviseCode)
                .build();

        Map<String, Object> result = tzsServiceFeignClient.createCode(map).getResult();

        ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
        builder.put("superviseCode", superviseCode);

        Optional.ofNullable(result)
                .map(r -> (String) r.get("code96333"))
                .ifPresent(code -> builder.put("code96333", code));

        return builder.build();
    }

    public void saveChangeRecord(JgChangeRegistrationTransfer transfer, TaskV2Model taskV2Model) {
        List<JgChangeRegistrationTransferEq> eqList = jgChangeRegistrationTransferEqService.lambdaQuery().eq(JgChangeRegistrationTransferEq::getEquipTransferId, transfer.getSequenceNbr()).list();
        JgRegistrationHistory historyData = jgRegistrationHistoryMapper.selectOne(new LambdaQueryWrapper<JgRegistrationHistory>()
                .eq(JgRegistrationHistory::getCurrentDocumentId, transfer.getApplyNo()));
        List<JgCertificateChangeRecord> changeRecordList = new ArrayList<>();
        List<JgCertificateChangeRecordEq> changeRecordEqList = new ArrayList<>();

        JSONObject historyJson = JSON.parseObject(historyData.getChangeData());
        List<Map<String, Object>> registrationList = (List<Map<String, Object>>) historyJson.get("registrationList");
        registrationList.forEach(registration -> {
            long nextId = sequence.nextId();
            JgCertificateChangeRecord changeRecord = new JgCertificateChangeRecord();
            String registrationCode = (String) registration.get("useRegistrationCode");
            String certificateNo = (String) registration.get("certificateNo");
            String equCategoryCode = (String) registration.get("equCategoryCode");
            changeRecord.setApplyNo(transfer.getApplyNo());
            changeRecord.setReceiveOrgName(transfer.getReceiveOrgName());
            changeRecord.setAuditPassDate(transfer.getAuditPassDate());
            changeRecord.setRegType("移装变更登记");
            changeRecord.setRegDate(transfer.getCreateDate());
            changeRecord.setChangeContent(this.buildRecordContent(transfer));
            changeRecord.setUseRegistrationCode(registrationCode);
            changeRecord.setReceiveCompanyCode(transfer.getReceiveCompanyCode());
            changeRecord.setCertificateNo(certificateNo);
            changeRecord.setUseUnitCreditCode(transfer.getUseUnitCreditCode());
            changeRecord.setUseUnitName(transfer.getUseUnitName());
            changeRecord.setEquCategory(equCategoryCode);
            changeRecord.setCreateDate(new Date());
            changeRecord.setSequenceNbr(nextId);
            changeRecord.setRoutePath(taskV2Model.getRoutePath());
            changeRecordList.add(changeRecord);
            for (JgChangeRegistrationTransferEq transferEq : eqList) {
                if (!StringUtils.isEmpty(transferEq.getUseRegistrationCode()) && !StringUtils.isEmpty(registrationCode) &&
                        transferEq.getUseRegistrationCode().equals(registrationCode)) {
                    JSONObject deviceJson = JSON.parseObject(transferEq.getDeviceInfo());
                    JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq();
                    changeRecordEq.setChangeRecordId(String.valueOf(nextId));
                    changeRecordEq.setEquId(deviceJson.getString("SEQUENCE_NBR"));
                    changeRecordEqList.add(changeRecordEq);
                }
            }
        });
        if (!changeRecordList.isEmpty()) {
            certificateChangeRecordService.saveBatch(changeRecordList);
        }
        if (!changeRecordEqList.isEmpty()) {
            certificateChangeRecordEqService.saveBatch(changeRecordEqList);
        }
    }

    private String buildRecordContent(JgChangeRegistrationTransfer obj) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        FeignClientResult<AgencyUserModel> agencyUserModelFeignClientResult = Privilege.agencyUserClient.queryByUserId(obj.getCreateUserId());
        return obj.getUseUnitName() + "的" + agencyUserModelFeignClientResult.getResult().getRealName() + "办理了【移装变更登记】，单号【"
                + obj.getApplyNo() + "】，移装后地址为" + obj.getFullAddress() + "，申请日期" + simpleDateFormat.format(new Date());
    }

    /**
     * 流程结束后需要更新的数据
     *
     * @param sequenceNbr 移装变更单Id
     */
    public void updateByFlowEnd(String sequenceNbr, JgRegistrationHistory historyData) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        JgChangeRegistrationTransfer transfer = this.getBaseMapper().selectById(sequenceNbr);
        LambdaQueryWrapper<JgChangeRegistrationTransferEq> lambda = new QueryWrapper<JgChangeRegistrationTransferEq>().lambda();
        lambda.eq(JgChangeRegistrationTransferEq::getEquipTransferId, sequenceNbr);
        List<JgChangeRegistrationTransferEq> transferEqList = jgChangeRegistrationTransferEqService.getBaseMapper().selectList(lambda);
        List<String> useRegistrationCodeList = new ArrayList<>(Collections.emptyList());

        if (!CollectionUtils.isEmpty(transferEqList)) {
            AtomicReference<String> useRegistrationCode = new AtomicReference<>("");
            AtomicBoolean isUpdateRegistrationCode = new AtomicBoolean(false);
            transferEqList.forEach(device -> {
                String supervisoryCode = "", code96333 = "";
                //区外移装
                if ("1".equals(transfer.getTransferType())) {
                    Map<String, String> supervisoryCodeMap = this.create96333Code(historyData, device.getEquId());
                    supervisoryCode = supervisoryCodeMap.get("superviseCode");
                    code96333 = supervisoryCodeMap.get("code96333");
                    useRegistrationCode.set(commonServiceImpl.generateRegistrationCode(device.getEquId(), transfer.getReceiveCompanyCode(), false));
                    useRegistrationCodeList.add(String.valueOf(useRegistrationCode));
                    isUpdateRegistrationCode.set(true);
                } else {
                    // 判断区内移装是否需要变更证号，若为韩城、杨凌或西咸则需变更，否则不变
                    JSONObject newPosition = JSON.parseObject(historyData.getChangeData());
                    String county = newPosition.getString("transferCounty").split("_")[0];

                    JSONObject deviceInfo = JSON.parseObject(device.getDeviceInfo());
                    String deviceCity = Arrays.stream(((String) deviceInfo.get("USE_PLACE_CODE")).split("#"))
                            .skip(2)
                            .findFirst()
                            .orElseThrow(() -> new BadRequest("没有查询到地市信息"));

                    // 判断是否为韩城、杨凌或西咸的区内移装到其他城市或从其他城市移装到韩城、杨凌或西咸
                    boolean shouldUpdateCode = Arrays.stream(ReginStepEnum.values())
                            .map(ReginStepEnum::getCode)
                            .anyMatch(code -> code.equals(county) || code.equals(deviceCity));
                    if (shouldUpdateCode) {
                        Map<String, String> supervisoryCodeMap = this.create96333Code(historyData, device.getEquId());
                        supervisoryCode = supervisoryCodeMap.get("superviseCode");
                        code96333 = supervisoryCodeMap.get("code96333");
                        useRegistrationCode.set(commonServiceImpl.generateRegistrationCode(device.getEquId(), transfer.getReceiveCompanyCode(), false));
                        useRegistrationCodeList.add(String.valueOf(useRegistrationCode));
                        isUpdateRegistrationCode.set(true);
                    }
                }
                //替换历史数据表和设备使用表
                this.replacementHistoryData(device.getEquId(), transfer, historyData, supervisoryCode, code96333);
                //更新使用注册登记证编号及ES中的信息
                this.updateRegisterInfoAndEsData(device.getEquId(), historyData, useRegistrationCode.get(), supervisoryCode, code96333, isUpdateRegistrationCode);
                //修改各类告知列表，置为废弃
                this.updateInvalidStatusByHistory(device.getEquId(), device.getEquipTransferId());
                //修改证管理表数据
                this.updateUseRegistrationManage(device, transfer, historyData, useRegistrationCode.get(), isUpdateRegistrationCode.get());
            });
        }

        //更新历史数据表
        historyData.setStatus("history");
        historyData.setUseRegistrationCode(String.join("，", useRegistrationCodeList));
        jgRegistrationHistoryService.saveOrUpdateHistoryData(historyData);

        transfer.setAuditPassDate(new Date());
        transfer.setRegPersonId(reginParams.getUserModel().getUserId());
        transfer.setRegPersonName(reginParams.getUserModel().getUserName());
        transfer.setUseRegistrationCode(String.join("，", useRegistrationCodeList));
        this.updateTransferByBaseInfo(transfer);
    }

    private void updateUseRegistrationManage(JgChangeRegistrationTransferEq device, JgChangeRegistrationTransfer transfer, JgRegistrationHistory historyData, String useRegistrationCode, boolean isUpdateRegistrationCode) {
        JSONObject historyJson = JSON.parseObject(historyData.getChangeData());
        JSONObject deviceInfo = JSON.parseObject(device.getDeviceInfo());
        List<JgUseRegistrationManage> registrationList = useRegistrationManageService.lambdaQuery()
                .in(BaseEntity::getSequenceNbr,
                        ((List<?>) historyJson.get("registrationList")).stream()
                                .map(obj -> ((JSONObject) obj).getString("sequenceNbr"))
                                .collect(Collectors.toList())
                )
                .eq(JgUseRegistrationManage::getUseRegistrationCode,deviceInfo.getString("USE_ORG_CODE"))
                .list();

        // 区外移装更新是否报废字段为1，区内移装不变
        if (isUpdateRegistrationCode) {
            useRegistrationManageService.lambdaUpdate()
                    .set(JgUseRegistrationManage::getIsScrap, 1)
                    // TODO 区外移装，业务已限制需要先注销证，这主要目的是将韩城、杨凌的特殊《区内逻辑》但是需要新生成的证的把之前证改成已注销
                    .set(JgUseRegistrationManage::getCertificateStatus, CertificateStatusEnum.YIZHUXIAO.getName())
                    .set(JgUseRegistrationManage::getIsDoBusiness, "3")// 限制区外移装后的老证不可办理业务，但是证管理可以查看
                    .in(JgUseRegistrationManage::getSequenceNbr,
                            registrationList.stream()
                                    .map(JgUseRegistrationManage::getSequenceNbr)
                                    .collect(Collectors.toList())
                    )
                    .update();
        }

        List<JgUseRegistrationManage> newRegistrationList = new ArrayList<>();
        // 新增-区外，或者区内是韩城和杨凌新生成证的新生成证（通过setSequenceNbr(null)），其他无需新生成证的进行证的更新
        List<JSONObject> updatedRegistrationList = registrationList.stream()
                .map(registrationManage -> {
                    Map<String, String> equType = new HashMap<>();
                    equType.put("equListCode", registrationManage.getEquCategoryCode());
                    equType.put("equCategoryCode", registrationManage.getEquDefineCode());
                    // 创建并设置新的 JgUseRegistrationManage 对象
                    JgUseRegistrationManage registrationManageNew = new JgUseRegistrationManage();
                    BeanUtils.copyProperties(registrationManage, registrationManageNew);
                    registrationManageNew.setReceiveOrgName(transfer.getReceiveOrgName());
                    registrationManageNew.setReceiveCompanyCode(transfer.getReceiveOrgCode());
                    registrationManageNew.setAuditPassDate(new Date());
                    registrationManageNew.setRegDate(new Date());
                    registrationManageNew.setEquUseAddress(transfer.getFullAddress());

                    // 更新使用登记码逻辑
                    if (isUpdateRegistrationCode &&
                            !StringUtils.isEmpty(registrationManageNew.getUseRegistrationCode()) &&
                            device.getUseRegistrationCode() != null &&
                            device.getUseRegistrationCode().equals(registrationManageNew.getUseRegistrationCode())) {
                        registrationManageNew.setUseRegistrationCode(useRegistrationCode);
                    }

                    registrationManageNew.setCertificateStatus("已登记");
                    registrationManageNew.setApplyNo(transfer.getApplyNo());
                    //新增-区外，或者区内是韩城和杨凌的进行
                    if (isUpdateRegistrationCode) {
                        registrationManageNew.setSequenceNbr(null);
                        registrationManageNew.setCertificateNo(commonServiceImpl.generateCertificateNo(equType, registrationManageNew.getAuditPassDate(), transfer.getReceiveCompanyCode()));
                    }
                    // 更新时，需更新原证的版本信息，扫码使用
                    if (registrationManageNew.getSequenceNbr() != null) {
                        registrationManageNew.setVersion(registrationManageNew.getVersion() + 1);
                        registrationManageNew.setChangeReason(BusinessTypeEnum.JG_CHANGE_REGISTRATION.getName());
                    } else {
                        registrationManageNew.setChangeReason("");
                        registrationManageNew.setVersion(1);
                    }
                    // 所属监管单位
                    String orgBranchCodeName = historyJson.getString("orgBranchCode");
                    String orgBranchName = historyJson.getString("orgBranchName");
                    String[] orgBranchArray = orgBranchCodeName.split("_");
                    if (orgBranchArray.length > 1) {
                        registrationManageNew.setSuperviseOrgCode(orgBranchArray[0]);
                        registrationManageNew.setSuperviseOrgName(StringUtil.isNotEmpty(orgBranchName) ? orgBranchName : orgBranchArray[1]);
                    }
                    registrationManageNew.setRegistrationType("0");
                    // 添加到新列表中
                    newRegistrationList.add(registrationManageNew);

                    // 创建并返回 JSON 对象
                    JSONObject jsonObject = (JSONObject) JSON.toJSON(registrationManageNew);
                    jsonObject.put("auditPassDate", new SimpleDateFormat("yyyy-MM-dd").format(registrationManage.getAuditPassDate()));
                    jsonObject.put("applyNo", registrationManageNew.getApplyNo());
                    jsonObject.put("certificateNo", registrationManageNew.getCertificateNo());
                    jsonObject.put("equUseAddress", registrationManageNew.getEquUseAddress());
                    jsonObject.put("certificateStatus", registrationManageNew.getCertificateStatus());
                    jsonObject.put("receiveCompanyCode", registrationManageNew.getReceiveCompanyCode());
                    jsonObject.put("receiveOrgName", registrationManageNew.getReceiveOrgName());
                    jsonObject.put("regType", registrationManageNew.getRegType());

                    return jsonObject;
                })
                .collect(Collectors.toList());

        // 批量保存新的注册管理对象
        useRegistrationManageService.saveOrUpdateBatch(newRegistrationList);
    }

    /**
     * 修改历史数据表和设备使用表
     *
     * @param record  设备Id
     * @param newData 设备移装的新数据
     */
    public void replacementHistoryData(String record, JgChangeRegistrationTransfer transfer,
                                       JgRegistrationHistory newData, String supervisoryCode, String code96333) {

        if (!ValidationUtil.isEmpty(record) && !ValidationUtil.isEmpty(transfer.getApplyNo())) {
            //查询设备旧数据
            IdxBizJgUseInfo useInfo = useInfoService.getOneData(record);
            IdxBizJgOtherInfo otherInfo = otherInfoService.getOneData(record);

            // 更新设备移装位置使用信息
            if (!ValidationUtil.isEmpty(newData)) {
                JSONObject newPosition = JSON.parseObject(newData.getChangeData());
                //省
                String province = newPosition.getString("transferProvince");
                //市
                String city = newPosition.getString("transferCity");
                //区县
                String county = newPosition.getString("transferCounty");
                //街道
                String street = newPosition.getString("transferStreet");
                //地址
                String address = newPosition.getString("transferAddress");
                //经纬度
                String longitudeLatitude = newPosition.getString("transferLongitudeLatitude");
                //使用场所
                String usePlace = newPosition.getString("transferUsePlace");
                //所属监管单位
                String supervisionUnit = newPosition.getString("orgBranchCode");
                //是否西咸
                String isXixian = newPosition.getString("transferIsXixian");
                //安全管理员
                String safetyManager = newPosition.getString("transferSafetyManager");
                //产权单位
                String transferUseInfo = newPosition.getString("transferUseInfo");
                //安全管理员电话
                String phone = newPosition.getString("transferPhone");

                // 分割省市区街道字段
                if (!ObjectUtils.isEmpty(province)) {
                    String[] provinceList = province.split("_");
                    if (provinceList.length > 1) {
                        useInfo.setProvince(provinceList[0]);
                        useInfo.setProvinceName(provinceList[1]);
                    }
                }
                if (!ObjectUtils.isEmpty(city)) {
                    String[] cityList = city.split("_");
                    if (cityList.length > 1) {
                        useInfo.setCity(cityList[0]);
                        useInfo.setCityName(cityList[1]);
                    }
                }
                if (!ObjectUtils.isEmpty(county)) {
                    String[] countyList = county.split("_");
                    if (countyList.length > 1) {
                        useInfo.setCounty(countyList[0]);
                        useInfo.setCountyName(countyList[1]);
                    }
                }
                if (!ObjectUtils.isEmpty(street)) {
                    String[] streetList = street.split("_");
                    if (streetList.length > 1) {
                        useInfo.setFactoryUseSiteStreet(streetList[0]);
                        useInfo.setStreetName(streetList[1]);
                    }
                }
                if (!ObjectUtils.isEmpty(address)) {
                    useInfo.setAddress(address);
                }
                if (!ObjectUtils.isEmpty(longitudeLatitude)) {
                    useInfo.setLongitudeLatitude(longitudeLatitude);
                }
                if (!ObjectUtils.isEmpty(usePlace)) {
                    useInfo.setUsePlace(usePlace);
                }
                if (!ObjectUtils.isEmpty(isXixian)) {
                    useInfo.setIsNotXiXian(isXixian);
                }
                if (!ObjectUtils.isEmpty(safetyManager)) {
                    String[] safetyManagerList = safetyManager.split("_");
                    if (safetyManagerList.length > 1) {
                        useInfo.setSafetyManagerId(safetyManagerList[0]);
                        useInfo.setSafetyManager(safetyManagerList[1]);
                    }
                }
                if (!ObjectUtils.isEmpty(phone)) {
                    useInfo.setPhone(phone);
                }
                if (!ObjectUtils.isEmpty(transferUseInfo)) {
                    String[] useInfoList = transferUseInfo.split("_");
                    if (useInfoList.length > 1) {
                        useInfo.setEstateUnitCreditCode(useInfoList[0]);
                        useInfo.setEstateUnitName(useInfoList[1]);
                    }
                }

                IdxBizJgSupervisionInfo idxBizJgSupervisionInfo = new IdxBizJgSupervisionInfo();
                if (!ObjectUtils.isEmpty(supervisionUnit)) {
                    String[] supervisionUnitList = supervisionUnit.split("_");
                    if (supervisionUnitList.length > 1) {
                        idxBizJgSupervisionInfo.setOrgBranchCode(supervisionUnitList[0]);
                        idxBizJgSupervisionInfo.setOrgBranchName(supervisionUnitList[1]);
                        LambdaQueryWrapper<IdxBizJgSupervisionInfo> eq = new QueryWrapper<IdxBizJgSupervisionInfo>().lambda().eq(IdxBizJgSupervisionInfo::getRecord, record);
                        idxBizJgSupervisionInfoMapper.update(idxBizJgSupervisionInfo, eq);
                    }
                }
                useInfo.setEquState("1");
                useInfoService.saveOrUpdateData(useInfo);
                if (!StringUtils.isEmpty(supervisoryCode)) {
                    otherInfo.setSupervisoryCode(supervisoryCode);
                }
                otherInfo.setCode96333(code96333);
                otherInfoService.saveOrUpdateData(otherInfo);
            }
        }
    }

    /**
     * 修改各类告知列表，置为废弃
     *
     * @param equId           设备id
     * @param equipTransferId 当前告知单Id
     */
    public void updateInvalidStatusByHistory(String equId, String equipTransferId) {
        //改造变更登记
        jgChangeRegistrationReformEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equId, equipTransferId);
        //移装变更登记
        jgChangeRegistrationTransferEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equId, equipTransferId);
        //使用登记
        jgUseRegistrationEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equId, equipTransferId);
        //单位变更登记
        jgChangeRegistrationUnitEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equId, equipTransferId);
        //更名变更登记
        jgChangeRegistrationNameEqMapper.updateEquipIsVaildByEquipIdAndCurrentDocumentId(equId, equipTransferId);
    }

    /**
     * 更新使用注册登记证编号及ES中的信息
     *
     * @param equId                    设备id
     * @param useRegistrationCode      使用注册登记证编号
     * @param isUpdateRegistrationCode 是否更新使用登记证编号
     */
    public void updateRegisterInfoAndEsData(String equId, JgRegistrationHistory newData, String useRegistrationCode,
                                            String supervisoryCode, String code96333, AtomicBoolean isUpdateRegistrationCode) {
        //更新使用注册登记证编号
        if (isUpdateRegistrationCode.get()) {
            idxBizJgRegisterInfoMapper.updateUseOrgCodeByEquip(equId, useRegistrationCode);
        }
        //获取移装新位置，更新ES
        String newUsePlace = "";
        String newUsePlaceCode = "";
        String newAddress = "";
        String newLongitudeLatitude = "";
        String useSiteCode = "";
        //es中的编号信息
        Map<String, Map<String, Object>> resultMap = new HashMap<>();
        Map<String, Object> map1 = new HashMap<>();
        if (!ValidationUtil.isEmpty(newData)) {
            JSONObject newPosition = JSON.parseObject(newData.getChangeData());
            String province = newPosition.getString("transferProvince");
            String city = newPosition.getString("transferCity");
            String county = newPosition.getString("transferCounty");
            String street = newPosition.getString("transferStreet");
            String address = newPosition.getString("transferAddress");
            String longitudeLatitude = newPosition.getString("longitudeLatitude");
            // 使用场所
            useSiteCode = newPosition.getString("transferUsePlace");
            // es的使用地点信息名称、code、详情地址
            String orgBranchCodeName = newPosition.getString("orgBranchCode");
            String orgBranchName = newPosition.getString("orgBranchName");
            String[] orgBranchArray = orgBranchCodeName.split("_");
            if (orgBranchArray.length > 1) {
                map1.put("ORG_BRANCH_CODE", orgBranchArray[0]);
                map1.put("ORG_BRANCH_NAME", StringUtil.isNotEmpty(orgBranchName) ? orgBranchName : orgBranchArray[1]);
            }
            // 分割省市区街道字段
            if (!ObjectUtils.isEmpty(province)) {
                String[] provinceList = province.split("_");
                if (provinceList.length > 1) {
                    newUsePlace += provinceList[1] + "/";
                    newUsePlaceCode += provinceList[0] + "#";
                }
            }
            if (!ObjectUtils.isEmpty(city)) {
                String[] cityList = city.split("_");
                if (cityList.length > 1) {
                    newUsePlace += cityList[1] + "/";
                    newUsePlaceCode += cityList[0] + "#";
                }
            }
            if (!ObjectUtils.isEmpty(county)) {
                String[] countyList = county.split("_");
                if (countyList.length > 1) {
                    newUsePlace += countyList[1] + "/";
                    newUsePlaceCode += countyList[0] + "#";
                }
            }
            if (!ObjectUtils.isEmpty(street)) {
                String[] countyList = street.split("_");
                if (countyList.length > 1) {
                    newUsePlace += countyList[1];
                    newUsePlaceCode += countyList[0];
                }
            }

            if (!ObjectUtils.isEmpty(address)) {
                newAddress = address;
            }
            if (!ObjectUtils.isEmpty(longitudeLatitude)) {
                newLongitudeLatitude = longitudeLatitude;
            }
        }
        map1.put("USE_PLACE", newUsePlace);
        map1.put("USE_PLACE_CODE", newUsePlaceCode);
        map1.put("ADDRESS", newAddress);
        // es的使用场所
        map1.put("USE_SITE_CODE", useSiteCode);
        map1.put("LONGITUDE_LATITUDE", newLongitudeLatitude);
        map1.put("EQU_STATE", "1");
        if (isUpdateRegistrationCode.get()) {
            map1.put("USE_ORG_CODE", useRegistrationCode);
            if (!StringUtils.isEmpty(supervisoryCode)) {
                map1.put("SUPERVISORY_CODE", supervisoryCode);
            }
            map1.put("CODE96333", code96333);
        }
        resultMap.put(equId, map1);
        tzsServiceFeignClient.commonUpdateEsDataByIds(resultMap);
    }

    //更新移装变更基本信息
    public void updateTransferByBaseInfo(JgChangeRegistrationTransfer model) {
        this.saveOrUpdate(model);
    }


    /**
     * 参数为监管码
     *
     * @param supervisoryCode
     * @return
     */
    public String getCode(String supervisoryCode) {
        if (!ObjectUtils.isEmpty(supervisoryCode) && supervisoryCode.length() > 5) {
            String name = EquipTypeEnum.getMessage(supervisoryCode.substring(1, 2));
            String type = supervisoryCode.substring(2, 4);
            String city = supervisoryCode.substring(0, 1);
            return commonServiceImpl.generateUniqueUseRegistrationCode(name, type, city);
        }
        return null;
    }

    /**
     * 导出使用登记证
     *
     * @param sequenceNbr
     */
    public void exportUseRegistrationCertificate(String sequenceNbr, HttpServletResponse response, String printType) {
        Map<String, Object> exportParamsMap = new HashMap<>();
        //查询移装变更详情
        JgChangeRegistrationTransfer transfer = this.getById(sequenceNbr);
        JgChangeRegistrationTransferEq transferEq = jgChangeRegistrationTransferEqService.getDetailByEquipTransferId(sequenceNbr);
        if (ValidationUtil.isEmpty(transfer) || ValidationUtil.isEmpty(transferEq)) {
            throw new BadRequest("使用登记证导出失败,请稍后重试!");
        }
        //是否废弃
        exportParamsMap.put("isInvalid", transferEq.getIsInvalid());
        JgRegistrationHistory transferHistory = jgRegistrationHistoryService.getDteailByRecord(transferEq.getEquId(), transfer.getApplyNo());
        //登记机关
        if (ValidationUtil.isEmpty(transfer.getReceiveOrgName())) {
            throw new BadRequest("使用登记证导出失败,登记机关为空!");
        }
        exportParamsMap.put("receiveOrgName", transfer.getReceiveOrgName());
        //使用登记证编号
        if (ValidationUtil.isEmpty(transfer.getUseRegistrationCode())) {
            throw new BadRequest("使用登记证导出失败,使用登记证编号为空!");
        }
        exportParamsMap.put("useRegistrationCode", transfer.getUseRegistrationCode());
        //使用单位名称
        if (ValidationUtil.isEmpty(transfer.getUseUnitName())) {
            throw new BadRequest("使用登记证导出失败,使用单位名称为空!");
        }
        exportParamsMap.put("useUnitName", transfer.getUseUnitName());
        //监管码
        if (ValidationUtil.isEmpty(transfer.getSupervisoryCode())) {
            throw new BadRequest("使用登记证导出失败,监管码为空!");
        }
        exportParamsMap.put("supervisoryCode", transfer.getSupervisoryCode());

        getAuditPassedDate(transfer.getAuditPassDate(), exportParamsMap);

        //设备使用地址
        if (!ValidationUtil.isEmpty(transferHistory)) {
            String fullAddress = "";
            JSONObject newPosition = JSON.parseObject(transferHistory.getChangeData());
            String province = newPosition.getString("transferProvince");
            String city = newPosition.getString("transferCity");
            String county = newPosition.getString("transferCounty");
            String street = newPosition.getString("transferStreet");
            String address = newPosition.getString("transferAddress");

            // 分割省市区街道字段
            if (!ObjectUtils.isEmpty(province)) {
                String[] provinceList = province.split("_");
                if (provinceList.length > 1) {
                    fullAddress += provinceList[1];
                }
            }
            if (!ObjectUtils.isEmpty(city)) {
                String[] cityList = city.split("_");
                if (cityList.length > 1) {
                    fullAddress += cityList[1];
                }
            }
            if (!ObjectUtils.isEmpty(county)) {
                String[] countyList = county.split("_");
                if (countyList.length > 1) {
                    fullAddress += countyList[1];
                }
            }
            if (!ObjectUtils.isEmpty(street)) {
                String[] streetList = street.split("_");
                if (streetList.length > 1) {
                    fullAddress += streetList[1];
                }
            }
            if (!ObjectUtils.isEmpty(address)) {
                fullAddress += address;
            }
            if (ValidationUtil.isEmpty(fullAddress)) {
                throw new BadRequest("使用登记证导出失败,设备使用地址为空!");
            }
            exportParamsMap.put("fullAddress", fullAddress);
        }

        //查询设备注册信息
        IdxBizJgRegisterInfo registerInfo = idxBizJgRegisterInfoService.getOne(new QueryWrapper<IdxBizJgRegisterInfo>().eq("RECORD", transferEq.getEquId()));
        if (!ValidationUtil.isEmpty(registerInfo)) {
            //设备种类、类别、品种
            String equList = registerInfo.getEquList();//设备种类
            String equCategory = registerInfo.getEquCategory();//设备类别
            String equDefine = registerInfo.getEquDefine();//设备品种
            List<EquipmentCategory> categoryList0 = iCommonService.getEquipmentCategoryList(equList, null);
            List<EquipmentCategory> categoryList1 = iCommonService.getEquipmentCategoryList(equCategory, null);
            List<EquipmentCategory> categoryList2 = iCommonService.getEquipmentCategoryList(equDefine, null);
            if (CollectionUtils.isNotEmpty(categoryList0)) {
                if (ValidationUtil.isEmpty(categoryList0.get(0).getName())) {
                    throw new BadRequest("使用登记证导出失败,设备种类为空!");
                }
                exportParamsMap.put("equList", categoryList0.get(0).getName());
            }
            if (CollectionUtils.isNotEmpty(categoryList1)) {
                if (ValidationUtil.isEmpty(categoryList1.get(0).getName())) {
                    throw new BadRequest("使用登记证导出失败,设备类别为空!");
                }
                exportParamsMap.put("equCategory", categoryList1.get(0).getName());
            }
            if (CollectionUtils.isNotEmpty(categoryList2)) {
                if (ValidationUtil.isEmpty(categoryList2.get(0).getName())) {
                    throw new BadRequest("使用登记证导出失败,设备品种为空!");
                }
                exportParamsMap.put("equDefine", categoryList2.get(0).getName());
            }
            //设备代码
            if (ValidationUtil.isEmpty(registerInfo.getEquCode())) {
                throw new BadRequest("使用登记证导出失败,设备代码为空!");
            }
            exportParamsMap.put("equCode", registerInfo.getEquCode());
        }

        //单位内部编码
        IdxBizJgUseInfo useInfo = idxBizJgUseInfoService.getOneData(transferEq.getEquId());
        if (!ValidationUtil.isEmpty(useInfo)) {
            if (ValidationUtil.isEmpty(useInfo.getUseInnerCode())) {
                throw new BadRequest("使用登记证导出失败,设备单位内部编码为空!");
            }
            exportParamsMap.put("useInnerCode", useInfo.getUseInnerCode());
        }
        IdxBizJgFactoryInfo factoryInfo = idxBizJgFactoryInfoService.getOneData(transferEq.getEquId());
        //产品编号(出厂编号)
        if (!ValidationUtil.isEmpty(factoryInfo)) {
            if (ValidationUtil.isEmpty(factoryInfo.getFactoryNum())) {
                throw new BadRequest("使用登记证导出失败,产品编号为空!");
            }
            exportParamsMap.put("factoryNum", factoryInfo.getFactoryNum());
        }
        exportParamsMap.put("applyNo", transfer.getApplyNo());
        if ("0".equals(printType)) {
            //调用生成使用登记证
            commonService.generateCertificateReport(exportParamsMap, response);
        } else {
            commonService.generatePdfPrint(exportParamsMap, response);
        }
    }


    /**
     * 启动工作流
     */
    private WorkflowResultDto startWorkFlow(String receiveOrgCreditCode) {
        ActWorkflowBatchDTO workflowBatchParams = new ActWorkflowBatchDTO();
        List<ActWorkflowStartDTO> workflowList = new ArrayList<>();
        ActWorkflowStartDTO workflow = new ActWorkflowStartDTO();
        workflow.setProcessDefinitionKey(PROCESS_DEFINITION_KEY);
        workflow.setBusinessKey("submit");
        workflow.setCompleteFirstTask(Boolean.TRUE);
        //下一节点执行人单位（下节点接收机构code）
        workflow.setNextExecuteUserCompanyCode(receiveOrgCreditCode);
        workflowList.add(workflow);
        workflowBatchParams.setProcess(workflowList);
        List<ProcessTaskDTO> processTasks = icmWorkflowService.startBatch(workflowBatchParams);
        // 组装工作流返回的数据
        return commonService.buildWorkFlowInfo(processTasks).get(0);
    }

    /**
     * 新增代办任务
     */
    private void createToDoTask(List<WorkflowResultDto> workflows, JgChangeRegistrationTransfer transfer, String submitType) {
        if (!ValidationUtil.isEmpty(workflows)) {
            List<TaskModelDto> toDoTasklist = new ArrayList<>();
            for (WorkflowResultDto workflow : workflows) {
                TaskModelDto toDoTask = new TaskModelDto();
                toDoTask.setTaskName(workflow.getTaskName());
                toDoTask.setFlowCreateDate(transfer.getCreateDate());
                toDoTask.setTaskCode(transfer.getApplyNo());
                toDoTask.setTaskContent(this.getSummaryInfo(transfer));
//                toDoTask.setTaskDesc();
                toDoTask.setTaskType(BusinessTypeEnum.JG_CHANGE_REGISTRATION.getCode());
                toDoTask.setTaskTypeLabel(BusinessTypeEnum.JG_CHANGE_REGISTRATION.getName());
                toDoTask.setRelationId(transfer.getInstanceId());
                toDoTask.setExecuteUserIds(workflow.getNextExecutorUserIds());
                FlowStatusEnum flowStatusEnum = this.getTaskStatus(submitType);
                toDoTask.setTaskStatus(flowStatusEnum.getCode());
                toDoTask.setTaskStatusLabel(flowStatusEnum.getName());
                toDoTask.setFlowStatus(commonService.getDictionaryCodeByName(transfer.getStatus()));
                toDoTask.setFlowStatusLabel(transfer.getStatus());
                toDoTask.setFlowCode(workflow.getNextTaskId());
                toDoTask.setStartUserId(transfer.getCreateUserId());
                toDoTask.setStartUser(transfer.getCreateUserName());
                toDoTask.setStartUserCompanyName(transfer.getCreateUserCompanyName());
                toDoTask.setStartDate(new Date());
                toDoTask.setNextExecuteUser(transfer.getNextExecutorIds());
                TaskMessageDto taskMessageDto = new TaskMessageDto();
                BeanUtil.copyProperties(transfer, taskMessageDto);
                toDoTask.setModel(taskMessageDto);
                toDoTasklist.add(toDoTask);
            }
            commonService.buildTaskModel(toDoTasklist);
        }
    }

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

    /**
     * @return String
     * @deprecated 动态获取
     */
    public String getSummaryInfo(JgChangeRegistrationTransfer transfer) {
        String result = "发起了【移装变更登记】业务申请，【申请单号：%s】";
        return String.format(result, Optional.ofNullable(transfer.getApplyNo()).orElse("无"));
    }

    public String getNextUserOrgCode(String operate, JgChangeRegistrationTransfer contract) {
        String code = null;
        if ("0".equals(operate)) {
            code = contract.getReceiveCompanyCode();
        } else {
            //驳回
            if (WorkFlowStatusEnum.TRANSFER_RECEIVE.getPass().equals(contract.getAuditStatus()) ||
                    WorkFlowStatusEnum.TRANSFER_RECEIVE.getReject().equals(contract.getAuditStatus()) ||
                    WorkFlowStatusEnum.TRANSFER_RECEIVE.getRollBack().equals(contract.getAuditStatus())) {
                code = contract.getUseUnitCreditCode();
            }
        }
        return code == null ? contract.getReceiveCompanyCode() : code;
    }

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

    public Map<String, Object> getDetailFieldCamelCase(String record) {
        Map<String, Object> result = new HashMap<>();
        result = idxBizJgRegisterInfoService.getDetailFieldCamelCaseByRecord(record);
        //移装变更-省份回显
        result.put("transferProvince", result.get("province"));
        //移装变更-市回显
        result.put("transferCity", result.get("city"));
        //移装变更-区回显
        result.put("transferCounty", result.get("county"));
        //移装变更-街道回显
        result.put("transferStreet", result.get("factoryUseSiteStreet") + "_" + result.get("streetName"));
        //移装变更-移装场所
        result.put("transferUsePlace", result.get("usePlace"));
        //移装变更-详细地址
        result.put("transferAddress", result.get("useAddress"));
        //移装变更-经纬度
        result.put("transferLongitudeLatitude", result.get("longitudeLatitude"));
        //移装变更-属地监管部门
        result.put("orgBranchCode", result.get("orgBranchCode") + "_" + result.get("orgBranchName"));
        //移装变更-所属经营单位
        result.put("transferIsXixian", result.get("isNotXiXian"));
        //移装变更-安全管理员
        result.put("transferSafetyManager", result.get("safetyManagerId") + "_" + result.get("safetyManager"));
        //移装变更-安全管理员姓名
        result.put("transferSafetyManagerName", result.get("safetyManager"));
        //移装变更-电话
        result.put("transferPhone", result.get("phone"));
        //移装变更-产权单位
        result.put("transferUseInfo", result.get("estateUnitCreditCode") + "_" + result.get("estateUnitName"));
        return result;
    }

    @Override
    public boolean beforeCheck(JgChangeRegistrationTransfer jgChangeRegistrationTransfer) {
        return jgChangeRegistrationTransfer.getInstanceId() != null && !jgChangeRegistrationTransfer.getStatus().equals(FlowStatusEnum.TO_BE_FINISHED.getName()) && !jgChangeRegistrationTransfer.getStatus().equals(FlowStatusEnum.TO_BE_DISCARD.getName());
    }

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