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

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Sequence;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.entity.DataDictionary;
import com.yeejoin.amos.boot.biz.common.service.impl.DataDictionaryServiceImpl;
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.dto.ESEquipmentCategoryDto;
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.JgVehicleInformationEqMapper;
import com.yeejoin.amos.boot.module.jg.api.mapper.JgVehicleInformationMapper;
import com.yeejoin.amos.boot.module.jg.api.service.IJgVehicleInformationService;
import com.yeejoin.amos.boot.module.jg.api.vo.JgVehicleInformationVo;
import com.yeejoin.amos.boot.module.jg.api.vo.SortVo;
import com.yeejoin.amos.boot.module.jg.biz.config.LocalBadRequest;
import com.yeejoin.amos.boot.module.jg.biz.context.EquipUsedCheckStrategyContext;
import com.yeejoin.amos.boot.module.jg.biz.context.FlowingEquipRedisContext;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.service.ICmWorkflowService;
import com.yeejoin.amos.boot.module.jg.biz.utils.FileExporter;
import com.yeejoin.amos.boot.module.jg.biz.utils.ImageUtils;
import com.yeejoin.amos.boot.module.jg.biz.feign.WorkFlowFeignService;
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.EquCodeTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquimentEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.*;
import com.yeejoin.amos.component.feign.utils.FeignUtil;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import com.yeejoin.amos.feign.systemctl.Systemctl;
import com.yeejoin.amos.feign.systemctl.model.DictionarieValueModel;
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 javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.yeejoin.amos.boot.module.jg.api.enums.VehicleApanageEnum.XIAN_YANG;
import static com.yeejoin.amos.boot.module.jg.api.enums.VehicleApanageEnum.XI_XIAN;
import static com.yeejoin.amos.boot.module.jg.biz.service.impl.JgUseRegistrationServiceImpl.getAuditPassedDate;

/**
 * 服务实现类
 *
 * @author system_generator
 * @date 2024-03-18
 */
@Service
public class JgVehicleInformationServiceImpl extends BaseService<JgVehicleInformationDto, JgVehicleInformation, JgVehicleInformationMapper> implements IJgVehicleInformationService {
    public static final String SUBMIT_DATA = "0";
    public static final String SUBMIT_TYPE_FLOW = "1";
    private static final String DEFINITION_KEY = "vehicleInformation";
    private static final String[] DEFAULT_KEYS = {
            "useRegistrationCode", "useUnitName", "fullAddress", "equList", "equipDefine",
            "equipCode", "equipCategory", "useInnerCode", "factoryNum", "giveOutYear",
            "giveOutMonth", "giveOutDay"
    };
    private final List<String> NOT_FLOWING_STATE = Arrays.asList("使用单位待提交", "一级受理已驳回", "使用单位已撤回", "已作废", "已完成");

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private CommonServiceImpl commonService;
    @Autowired
    private ICmWorkflowService workflowService;
    @Autowired
    private JgRegistrationHistoryServiceImpl jgRegistrationHistoryService;
    @Autowired
    private CmWorkflowServiceImpl cmWorkflowService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private Sequence sequence;
    @Autowired
    private JgVehicleInformationEqMapper jgVehicleInformationEqMapper;
    @Autowired
    private IdxBizJgUseInfoServiceImpl idxBizJgUseInfoService;
    @Autowired
    private IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoService;
    @Autowired
    private IdxBizJgRegisterInfoMapper idxBizJgRegisterInfoMapper;
    @Autowired
    private IdxBizJgUseInfoMapper useInfoMapper;
    @Autowired
    private IdxBizJgSupervisionInfoMapper idxBizJgSupervisionInfoMapper;
    @Autowired
    private DataDictionaryServiceImpl iDataDictionaryService;
    @Autowired
    private TzsServiceFeignClient tzsServiceFeignClient;
    @Autowired
    private JgVehicleInformationEqServiceImpl jgVehicleInformationEqService;
    @Autowired
    private IdxBizJgFactoryInfoMapper idxBizJgFactoryInfoMapper;
    @Autowired
    private IdxBizJgOtherInfoMapper otherInfoMapper;
    @Autowired
    private JgUseRegistrationServiceImpl jgUseRegistrationService;
    @Autowired
    private IdxBizJgInspectionDetectionInfoServiceImpl idxBizJgInspectionDetectionInfoService;
    @Autowired
    private ESEquipmentCategory esEquipmentCategory;
    @Autowired
    private JgResumeInfoServiceImpl jgResumeInfoService;
    @Autowired
    private TzBaseEnterpriseInfoMapper tzBaseEnterpriseInfoMapper;
    @Autowired
    private JgCertificateChangeRecordServiceImpl certificateChangeRecordService;
    @Autowired
    private JgCertificateChangeRecordEqServiceImpl certificateChangeRecordEqService;
    @Autowired
    private JgUseRegistrationManageServiceImpl jgUseRegistrationManageService;
    @Autowired
    private WorkFlowFeignService workFlowFeignService;

    private Map<String, Object> fillingMediumMap;

    /**
     * @param auditPassDate   通过时间
     * @param exportParamsMap 参数map
     */
    static void handleAuditPassedDate(Date auditPassDate, Map<String, Object> exportParamsMap) {
        LocalDate today;
        if (ValidationUtil.isEmpty(auditPassDate)) {
            // 发证日期为空取当前时间
            today = LocalDate.now();
        } else {
            today = auditPassDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        }
        exportParamsMap.put("year", today.getYear() + "");
        exportParamsMap.put("mon", today.getMonthValue());
        exportParamsMap.put("day", today.getDayOfMonth());
    }

    /**
     * 新增（提交）车用气瓶
     *
     * @param map map
     * @return list
     */
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public List<JgVehicleInformation> save(String submit, JSONObject map) {
        try {
            ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())) + "", ReginParams.class);
            JgVehicleInformationDto vehicleInfoDto = JSON.parseObject(JSON.toJSONString(map), JgVehicleInformationDto.class);

            List<Map<String, Object>> equipmentLists = (List<Map<String, Object>>) map.get("equipmentLists");
            if (CollectionUtils.isEmpty(equipmentLists) ||
                    equipmentLists.stream().map(v -> (String) v.get("chargingMedium")).distinct().count() != 1) {
                throw new BadRequest(CollectionUtils.isEmpty(equipmentLists) ? "请选择设备信息!" : "请选择相同充装介质设备！");
            }
            if (SUBMIT_TYPE_FLOW.equals(submit)) {
                this.repeatUsedEquipCheck(equipmentLists, reginParams.getCompany().getCompanyCode());
            }
            List<IdxBizJgInspectionDetectionInfo> inspectionDetectionInfoList = idxBizJgInspectionDetectionInfoService.checkInspectionInfo(
                    equipmentLists.stream()
                            .map(v -> (String) v.get("record"))
                            .collect(Collectors.toList())
            );

            if (inspectionDetectionInfoList.stream().anyMatch(info ->
                    ObjectUtils.isEmpty(info) || ObjectUtils.isEmpty(info.getInspectType()) ||
                            ObjectUtils.isEmpty(info.getInspectConclusion()) || ObjectUtils.isEmpty(info.getInspectOrgCode()))) {
                throw new BadRequest("请补充设备检验检测信息后提交！");
            }
            vehicleInfoDto.setNextInspectionDate(inspectionDetectionInfoList.stream()
                    .map(IdxBizJgInspectionDetectionInfo::getNextInspectDate)
                    .filter(Objects::nonNull)
                    .min(Date::compareTo)
                    .orElse(null));

            CompanyBo company = reginParams.getCompany();
            vehicleInfoDto.setCreateDate(new Date());
            vehicleInfoDto.setPromoter(reginParams.getUserModel().getUserId());

            // 车牌号码 字段的唯一性校验
            LambdaQueryWrapper<JgVehicleInformation> vehicleInfoWrapper = new LambdaQueryWrapper<JgVehicleInformation>()
                    .eq(JgVehicleInformation::getCarNumber, vehicleInfoDto.getCarNumber())
                    .eq(JgVehicleInformation::getIsDelete, false)
                    .ne(JgVehicleInformation::getStatus, "已作废")
                    .ne(JgVehicleInformation::getStatus, "使用单位待提交")
                    .ne(!ValidationUtil.isEmpty(vehicleInfoDto.getSequenceNbr()), JgVehicleInformation::getSequenceNbr, vehicleInfoDto.getSequenceNbr());
            Integer count = this.baseMapper.selectCount(vehicleInfoWrapper);
            if (count > 0) {
                throw new LocalBadRequest("车牌号码已存在，请重新输入！");
            }

            // 【A109】 车用气瓶登记业务 车辆VIN码 校验唯一性
            LambdaQueryWrapper<JgVehicleInformation> informationLambdaQueryWrapper = new LambdaQueryWrapper<JgVehicleInformation>()
                    .eq(JgVehicleInformation::getIdentificationCode, vehicleInfoDto.getIdentificationCode())
                    .eq(JgVehicleInformation::getIsDelete, false)
                    .ne(JgVehicleInformation::getStatus, "已作废")
                    .ne(JgVehicleInformation::getStatus, "使用单位待提交")
                    .ne(!ValidationUtil.isEmpty(vehicleInfoDto.getSequenceNbr()), JgVehicleInformation::getSequenceNbr, vehicleInfoDto.getSequenceNbr());
            Integer identificationCodeCount = this.baseMapper.selectCount(informationLambdaQueryWrapper);
            if (identificationCodeCount > 0) {
                throw new BadRequest("车辆VIN码已存在，请重新输入！");
            }

            // 使用单位信息
            if ("个人主体".equals(company.getCompanyType())) {
                vehicleInfoDto.setUseUnitName(company.getCompanyName().split("_")[1]);
                vehicleInfoDto.setUseUnitCreditCode(company.getCompanyCode().split("_")[1]);
            } else {
                vehicleInfoDto.setUseUnitName(company.getCompanyName());
                vehicleInfoDto.setUseUnitCreditCode(company.getCompanyCode());
            }


            // 接收单位信息
            if (!StringUtils.isEmpty(vehicleInfoDto.getReceiveOrgCode())) {
                String[] splitReceiveOrgCode = vehicleInfoDto.getReceiveOrgCode().split("_");
                CompanyModel result = Privilege.companyClient.queryByCompanyCode(splitReceiveOrgCode[0]).getResult();
                vehicleInfoDto.setReceiveOrgCode(splitReceiveOrgCode[0]);
                vehicleInfoDto.setReceiveOrgName(splitReceiveOrgCode[1]);
                vehicleInfoDto.setReceiveCompanyCode(result.getCompanyCode());
            }
            //检验机构信息
            if (!StringUtils.isEmpty(vehicleInfoDto.getInspectUnitCreditCode())) {
                String[] splitInspectUnitCreditCode = vehicleInfoDto.getInspectUnitCreditCode().split("_");
                vehicleInfoDto.setInspectUnitCreditCode(splitInspectUnitCreditCode[0]);
                vehicleInfoDto.setInspectUnitName(splitInspectUnitCreditCode[1]);
            }
            //安装单位信息
            if (!StringUtils.isEmpty(vehicleInfoDto.getInstallUnitCode())) {
                String[] splitInstallUnitCode = vehicleInfoDto.getInstallUnitCode().split("_");
                vehicleInfoDto.setInstallUnitCode(splitInstallUnitCode[0]);
                vehicleInfoDto.setInstallUnitName(splitInstallUnitCode[1]);
            }
            //属地监管部门
            if (!StringUtils.isEmpty(vehicleInfoDto.getOrgBranchCode())) {
                String[] splitOrgBranchCode = vehicleInfoDto.getOrgBranchCode().split("_");
                vehicleInfoDto.setOrgBranchCode(splitOrgBranchCode[0]);
                vehicleInfoDto.setOrgBranchName(splitOrgBranchCode[1]);
            }

            // 安全管理员
            Optional.ofNullable(map.getString("safetyManagerId"))
                    .filter(manager -> manager.contains("_"))
                    .map(manager -> manager.split("_"))
                    .ifPresent(data -> {
                        vehicleInfoDto.setSafetyManagerId(data[0]);
                        vehicleInfoDto.setSafetyManagerName(data[1]);
                    });

            // 产权单位信息
            if (!StringUtils.isEmpty(vehicleInfoDto.getEstateUnitName())) {
                String[] data = String.valueOf(map.getString("estateUnitName")).split("_");
                vehicleInfoDto.setEstateUnitCreditCode(data[0]);
                vehicleInfoDto.setEstateUnitName(data[1]);
            }

            // 其他附件
            if (!ObjectUtils.isEmpty(map.get("otherAccessories"))) {
                vehicleInfoDto.setOtherAccessories(JSONObject.toJSONString(map.get("otherAccessories")));
            }

            JgVehicleInformation vehicleInformation = new JgVehicleInformation();
            BeanUtils.copyProperties(vehicleInfoDto, vehicleInformation);
            vehicleInformation.setCreateUserId(reginParams.getUserModel().getUserId());
            vehicleInformation.setRegDate(new Date());
            vehicleInformation.setCreateUserName(reginParams.getUserModel().getRealName());
            vehicleInformation.setGasNum(equipmentLists.size());
            vehicleInformation.setVolume(String.valueOf(equipmentLists.stream()
                    .mapToDouble(x -> Double.parseDouble(String.valueOf(x.get("singleBottleVolume"))))
                    .sum()));
            vehicleInformation.setFillingMedium(equipmentLists.get(0).get("chargingMedium") + "");

            boolean hasId = StringUtils.isEmpty(vehicleInfoDto.getSequenceNbr());
            //新增
            if (hasId) {
                ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.SYDJ.getCode(), 1);
                if (!ObjectUtils.isEmpty(listResponseModel) && listResponseModel.getStatus() != HttpStatus.OK.value()) {
                    log.error("车用气瓶使用登记申请单单号获取失败！");
                    throw new BadRequest("车用气瓶使用登记申请单单号获取失败！");
                }
                String applyNo = listResponseModel.getResult().get(0);
                vehicleInformation.setApplyNo(applyNo);
                vehicleInformation.setStatus(SUBMIT_DATA.equals(submit) ? WorkFlowStatusEnum.USE_SUBMIT.getPass() : WorkFlowStatusEnum.USE_RECEIVE.getPass());
                this.save(vehicleInformation);
            } else {
                // 删除以前设备关联关系
                this.getBaseMapper().updateById(vehicleInformation);
                LambdaQueryWrapper<JgVehicleInformationEq> lambda = new QueryWrapper<JgVehicleInformationEq>().lambda();
                lambda.eq(JgVehicleInformationEq::getVehicleId, vehicleInformation.getSequenceNbr());
                jgVehicleInformationEqService.getBaseMapper().delete(lambda);
            }
            // 更新关联气瓶信息
            if (!CollectionUtils.isEmpty(equipmentLists)) {

                List<JgVehicleInformationEq> equipList = new ArrayList<>();
                equipmentLists.forEach(x -> {
                    JgVehicleInformationEq equip = new JgVehicleInformationEq();
                    equip.setEquId(String.valueOf(x.get("record")));
                    equip.setVehicleId(vehicleInformation.getSequenceNbr() + "");
                    equipList.add(equip);
                    jgResumeInfoService.createWithModel(JgResumeInfoDto.builder()
                            .applyNo(vehicleInformation.getApplyNo())
                            .businessType(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName())
                            .businessId(vehicleInformation.getSequenceNbr() + "")
                            .equId(String.valueOf(x.get("record")))
                            .approvalUnit(vehicleInformation.getReceiveOrgName())
                            .approvalUnitCode(vehicleInformation.getReceiveOrgCode())
                            .status("正常")
                            .build());
                });
                // 保存关联设备信息
                jgVehicleInformationEqService.saveBatch(equipList);
            }
            // 判断当前是否为提交
            if (SUBMIT_TYPE_FLOW.equals(submit)) {
                this.checkVesselCylinderIsUsed(vehicleInformation.getSequenceNbr(), equipmentLists.stream()
                        .map(x -> String.valueOf(x.get("record")))
                        .collect(Collectors.toList()));
                List<String> roleListNext = new ArrayList<>();
                List<String> roleListAll = new ArrayList<>();
                // 新增提交，没有instanceId需要发起流程
                if (StringUtils.isEmpty(vehicleInformation.getInstanceId())) {
                    // 启动并执行流程
                    ActWorkflowBatchDTO actWorkflowBatchDTO = new ActWorkflowBatchDTO();
                    List<ActWorkflowStartDTO> list = new ArrayList<>();
                    ActWorkflowStartDTO dto = new ActWorkflowStartDTO();
                    dto.setProcessDefinitionKey(DEFINITION_KEY);
                    dto.setBusinessKey(vehicleInformation.getApplyNo());
                    dto.setCompleteFirstTask(Boolean.TRUE);
                    // 下一节点执行人单位（下节点接收机构code）
                    dto.setNextExecuteUserCompanyCode(vehicleInformation.getReceiveCompanyCode());
                    list.add(dto);
                    actWorkflowBatchDTO.setProcess(list);
                    List<ProcessTaskDTO> processTasks = workflowService.startBatch(actWorkflowBatchDTO);
                    this.buildRoleList(processTasks, roleListNext, roleListAll);
                    List<WorkflowResultDto> workflowResultDtoList = commonService.buildWorkFlowInfo(processTasks);
                    if (!ObjectUtils.isEmpty(workflowResultDtoList) && !ObjectUtils.isEmpty(workflowResultDtoList.get(0))) {
                        WorkflowResultDto workflowResultDto = workflowResultDtoList.get(0);
                        this.updateData(vehicleInformation.getSequenceNbr(), "0", workflowResultDto, Boolean.TRUE, String.valueOf(map.get("equDefineCode")));
                    }
                } else {
                    // 执行流程
                    flowExecute(vehicleInformation.getSequenceNbr(), vehicleInformation.getInstanceId(), "0", "", String.valueOf(map.get("nextTaskId")), String.valueOf(map.get("equDefineCode")));
                }
            } else {
                ArrayList<TaskModelDto> list = new ArrayList<>();
                TaskModelDto dto = new TaskModelDto();
                TaskMessageDto taskMessageDto = new TaskMessageDto();
                BeanUtil.copyProperties(vehicleInformation, taskMessageDto);
                taskMessageDto.setEquipId(String.valueOf(map.get("equipId")));
                dto.setModel(taskMessageDto);
                dto.setTaskContent("来自车用气瓶【" + vehicleInformation.getCarNumber() + "】的登记业务办理," + "【申请单号：" + vehicleInformation.getApplyNo() + "】");
                dto.setTaskCode(vehicleInformation.getApplyNo());
                dto.setTaskType(String.valueOf(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getCode()));
                dto.setRelationId(String.valueOf(vehicleInformation.getSequenceNbr()));
                dto.setNextExecuteUser("");
                list.add(dto);
                commonService.buildTaskModel(list);
            }
            // 设备数据存历史数据，在流程完成时使用
            commonService.saveOrUpdateHistory(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName(), JSON.parseArray(JSON.toJSONString(equipmentLists)), null, vehicleInformation.getSequenceNbr() + "");
            return Collections.singletonList(vehicleInformation);
        } 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(DEFINITION_KEY)
                .equipRepeatUsedCheck(String.valueOf(equipMap.get("record")), companyCode));
    }

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

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

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

            LambdaQueryWrapper<JgVehicleInformation> lambda = new QueryWrapper<JgVehicleInformation>().lambda();
            lambda.eq(JgVehicleInformation::getInstanceId, instanceId);
            List<String> roleListNext = new ArrayList<>();
            List<String> roleListAll = new ArrayList<>();
            JgVehicleInformation vehicleInfo = this.getOne(lambda);
            ProcessTaskDTO processTaskDTO = workflowService.rollBack(instanceId);
            String nextTaskId = processTaskDTO.getNextTask().get(0).getId();
            this.buildRoleList(Collections.singletonList(processTaskDTO), roleListNext, roleListAll);
            // 待调整
            String taskCode = processTaskDTO.getNextTask().get(0).getKey();
            if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(taskCode)) {
                vehicleInfo.setStatus(Objects.requireNonNull(WorkFlowStatusEnum.getMessage(taskCode)).getRollBack());
            }
            vehicleInfo.setPromoter(RequestContext.getExeUserId());
            vehicleInfo.setNextExecuteIds(String.join(",", roleListNext));
            vehicleInfo.setNextTaskId(nextTaskId);
            List<WorkflowResultDto> workflowResultDtoList = commonService.buildWorkFlowInfo(Collections.singletonList(processTaskDTO));
            // 更新下一步可执行人
            String nextUserIds = workflowResultDtoList.get(0).getNextExecutorUserIds();
            vehicleInfo.setNextExecuteUserIds(nextUserIds);
            this.updateById(vehicleInfo);
            // 删除待办
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(vehicleInfo));
            jsonObject.put("nextTaskId", vehicleInfo.getNextTaskId());
            jsonObject.put("nextExecuteUser", vehicleInfo.getNextExecuteIds());
            jsonObject.put("taskType", BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getCode());
            jsonObject.put("flowStatus", this.getTaskCodeByName(vehicleInfo.getStatus()));
            jsonObject.put("flowStatusLabel", vehicleInfo.getStatus());
            jsonObject.put("maintenanceContract", null);// 不传合同照片附件信息//TODO
            // 判断撤回后当前的节点，如果当前节点为提交节点则页面可编辑
            jsonObject.put("pageType", this.getPageTypeByCurrentNode(vehicleInfo.getStatus()));
            commonService.rollbackTask(instanceId, jsonObject);

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

    private String getPageTypeByCurrentNode(String auditStatus) {
        if (WorkFlowStatusEnum.USE_SUBMIT.getPass().equals(auditStatus) || WorkFlowStatusEnum.USE_SUBMIT.getReject().equals(auditStatus) || WorkFlowStatusEnum.USE_SUBMIT.getRollBack().equals(auditStatus)) {
            return "edit";
        } else {
            return "look";
        }
    }

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

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

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

    /**
     * 查看详情
     *
     * @param sequenceNbr sequenceNbr
     * @return JgVehicleInformationModel
     */
    public JgVehicleInformationVo queryBySequenceNbr(Long sequenceNbr) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())) + "", ReginParams.class);

        JgVehicleInformationVo vo = new JgVehicleInformationVo();
        JgVehicleInformationDto dto = this.baseMapper.queryBySequenceNbr(sequenceNbr);
        if (Objects.isNull(dto)) {
            return null;
        }
        BeanUtils.copyProperties(dto, vo);
        //接收机构
        if (!ValidationUtil.isEmpty(dto.getReceiveOrgCode()) && !ValidationUtil.isEmpty(dto.getReceiveOrgName())) {
            vo.setReceiveOrgCode(dto.getReceiveCompanyCode() + "_" + dto.getReceiveOrgName());
        }
        //检验机构
        if (!ValidationUtil.isEmpty(dto.getInspectUnitCreditCode()) && !ValidationUtil.isEmpty(dto.getInspectUnitName())) {
            vo.setInspectUnitCreditCode(dto.getInspectUnitCreditCode() + "_" + dto.getInspectUnitName());
        }
        //安装单位
        if (!ValidationUtil.isEmpty(dto.getInstallUnitCode()) && !ValidationUtil.isEmpty(dto.getInstallUnitName())) {
            vo.setInstallUnitCode(dto.getInstallUnitCode() + "_" + dto.getInstallUnitName());
        }
        //所属监管单位
        if (!ValidationUtil.isEmpty(dto.getOrgBranchCode()) && !ValidationUtil.isEmpty(dto.getOrgBranchName())) {
            vo.setOrgBranchCode(dto.getOrgBranchCode() + "_" + dto.getOrgBranchName());
        }
        //安全管理员
        if (!ValidationUtil.isEmpty(dto.getSafetyManagerId()) && !ValidationUtil.isEmpty(dto.getSafetyManagerName())) {
            vo.setSafetyManagerId(dto.getSafetyManagerId() + "_" + dto.getSafetyManagerName());
        }
        //产权单位
        //if (!ValidationUtil.isEmpty(dto.getEstateUnitCreditCode()) && !ValidationUtil.isEmpty(dto.getEstateUnitName())) {
        //    vo.setEstateUnitName(dto.getEstateUnitCreditCode() + "_" + dto.getEstateUnitName());
        //}
        TzBaseEnterpriseInfo useCodeResult = tzBaseEnterpriseInfoMapper.selectOne(new QueryWrapper<TzBaseEnterpriseInfo>()
                .eq("use_unit_code", dto.getEstateUnitCreditCode())
        );

        if (useCodeResult != null) {
            String result = dto.getEstateUnitCreditCode() + "_" + dto.getEstateUnitName() + ("个人主体".equals(useCodeResult.getUnitType())
                    ? "_" + dto.getEstateUnitCreditCode().substring(dto.getEstateUnitCreditCode().length() - 4) : "");
            vo.setEstateUnitName(result);
        }
        vo.setIdCardFront(ObjectUtils.isEmpty(dto.getIdCardFront()) ? null : JSON.parseArray(dto.getIdCardFront()));
        vo.setIdCardBack(ObjectUtils.isEmpty(dto.getIdCardBack()) ? null : JSON.parseArray(dto.getIdCardBack()));
        vo.setDriveLicenseFront(ObjectUtils.isEmpty(dto.getDriveLicenseFront()) ? null : JSON.parseArray(dto.getDriveLicenseFront()));
        vo.setDriveLicenseBack(ObjectUtils.isEmpty(dto.getDriveLicenseBack()) ? null : JSON.parseArray(dto.getDriveLicenseBack()));
        vo.setVehicleRegistrationCertificate(ObjectUtils.isEmpty(dto.getVehicleRegistrationCertificate()) ? null : JSON.parseArray(dto.getVehicleRegistrationCertificate()));
        vo.setInspectionCertificate(ObjectUtils.isEmpty(dto.getInspectionCertificate()) ? null : JSON.parseArray(dto.getInspectionCertificate()));
        vo.setFilingNotice(ObjectUtils.isEmpty(dto.getFilingNotice()) ? null : JSON.parseArray(dto.getFilingNotice()));
        vo.setOtherAccessories(ObjectUtils.isEmpty(dto.getOtherAccessories()) ? null : JSON.parseArray(dto.getOtherAccessories()));
        vo.setCompanyInfo(reginParams.getCompany());

        LambdaQueryWrapper<JgVehicleInformationEq> vehicleInfoEqWrapper = new QueryWrapper<JgVehicleInformationEq>().lambda();
        vehicleInfoEqWrapper.eq(JgVehicleInformationEq::getVehicleId, sequenceNbr);
        List<JgVehicleInformationEq> vehicleInformationEqList = jgVehicleInformationEqService.getBaseMapper().selectList(vehicleInfoEqWrapper);

        // 非完成、非已作废时显示实时数据
        if (!(dto.getStatus().equals(FlowStatusEnum.TO_BE_FINISHED.getName()) || dto.getStatus().equals(FlowStatusEnum.TO_BE_DISCARD.getName()))) {
            vo.setEquipmentLists(
                    this.baseMapper.queryForUnitVesselEquipment(sequenceNbr,
                                    vehicleInformationEqList.stream()
                                            .map(JgVehicleInformationEq::getEquId)
                                            .collect(Collectors.toList())
                            ).stream()
                            .peek(v -> v.put("chargingMedium", getFillingMediumMap().get(v.getOrDefault("chargingMedium", "") + "")))
                            .collect(Collectors.toList())
            );
        } else {
            // 完成及已作废时显示历史数据详情
            JSONArray objects = commonService.queryHistoryDataObj(dto.getSequenceNbr());
            // 兼容老数据
            if (objects.isEmpty()) {
                vo.setEquipmentLists(
                        this.baseMapper.queryForUnitVesselEquipment(sequenceNbr,
                                        vehicleInformationEqList.stream()
                                                .map(JgVehicleInformationEq::getEquId)
                                                .collect(Collectors.toList())
                                ).stream()
                                .peek(v -> v.put("chargingMedium", getFillingMediumMap().get(v.getOrDefault("chargingMedium", "") + "")))
                                .collect(Collectors.toList())
                );
            } else {
                List equList = objects.toJavaList(Map.class);
                vo.setEquipmentLists(equList);
            }

        }
        vo.setEquDefineCode(
                vo.getEquipmentLists().stream()
                        .findFirst()
                        .map(map -> (String) map.get("equDefine"))
                        .orElse(null)
        );
        return vo;
    }

    /**
     * 执行流程
     *
     * @param sequenceNbr sequenceNbr
     * @param instanceId  instanceId
     * @param operate     操作
     * @param comment     意见
     * @param nextTaskId  nextTaskId
     */
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void flowExecute(Long sequenceNbr, String instanceId, String operate, String comment, String nextTaskId, String equDefineCode) {
        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);

            JgVehicleInformation jgVehicleInformation = this.getBaseMapper().selectById(sequenceNbr);
            // 组装信息
            TaskResultDTO dto = new TaskResultDTO();
            dto.setResultCode("approvalStatus");
            dto.setTaskId(jgVehicleInformation.getNextTaskId());
            dto.setComment(comment);
            HashMap<String, Object> map = new HashMap<>();
            map.put("approvalStatus", operate);
            if (jgVehicleInformation.getStatus().equals(WorkFlowStatusEnum.USE_SUBMIT.getReject()) || jgVehicleInformation.getStatus().equals(WorkFlowStatusEnum.USE_SUBMIT.getRollBack())) {
                map.put("approvalStatus", "提交");
            }
            dto.setVariable(map);
            // 接受机构
            if ("1".equals(operate) && WorkFlowStatusEnum.USE_RECEIVE.getPass().equals(jgVehicleInformation.getStatus())) {
                // 驳回到使用单位
                dto.setNextExecuteUserCompanyCode(jgVehicleInformation.getUseUnitCreditCode());
            } else {
                dto.setNextExecuteUserCompanyCode(jgVehicleInformation.getReceiveCompanyCode());
            }
            ProcessTaskDTO complete = cmWorkflowService.completeOrReject(jgVehicleInformation.getNextTaskId(), dto, operate);
            ArrayList<ProcessTaskDTO> processTaskDTOS = new ArrayList<>();
            processTaskDTOS.add(complete);
            List<WorkflowResultDto> resultDto = commonService.buildWorkFlowInfo(processTaskDTOS);
            if (!ObjectUtils.isEmpty(resultDto) && !ObjectUtils.isEmpty(resultDto.get(0))) {
                WorkflowResultDto workflowResultDto = resultDto.get(0);
                this.updateData(jgVehicleInformation.getSequenceNbr(), operate, workflowResultDto, Boolean.FALSE, equDefineCode);
            }
            this.delRepeatUseEquipData(jgVehicleInformation);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 更新数据
     *
     * @param sequenceNbr       sequenceNbr
     * @param operate           operate
     * @param workflowResultDto workflowResultDto
     * @param isFirst           isFirst
     */
    public void updateData(Long sequenceNbr, String operate, WorkflowResultDto workflowResultDto, Boolean isFirst, String equDefineCode) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())) + "", ReginParams.class);
        String role = workflowResultDto.getNextExecutorRoleIds();
        String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
        if (!ObjectUtils.isEmpty(workflowResultDto.getNextTaskCode())) {
            taskCode = workflowResultDto.getNextTaskCode();
        }
        JgVehicleInformation jgVehicleInformation = this.getBaseMapper().selectById(sequenceNbr);

        jgVehicleInformation.setNextTaskId(workflowResultDto.getNextTaskId());
        jgVehicleInformation.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
        commonService.deleteTasksByRelationId(sequenceNbr + "");
        if (isFirst) {
            jgVehicleInformation.setInstanceStatus(workflowResultDto.getExecutorRoleIds());
            jgVehicleInformation.setInstanceId(workflowResultDto.getInstanceId());
        }
        //非完成
        if (!FlowStatusEnum.TO_BE_FINISHED.getName().equals(taskCode)) {
            jgVehicleInformation.setNextExecuteIds(role);
            jgVehicleInformation.setPromoter(reginParams.getUserModel().getUserId());
            if (!ObjectUtils.isEmpty(jgVehicleInformation.getInstanceStatus())) {
                jgVehicleInformation.setInstanceStatus(jgVehicleInformation.getInstanceStatus() + "," + role);
            } else {
                jgVehicleInformation.setInstanceStatus(role);
            }
            if ("0".equals(operate)) {
                // 通过操作
                jgVehicleInformation.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getPass());
            } else {
                // 驳回操作
                jgVehicleInformation.setStatus(WorkFlowStatusEnum.getMessage(taskCode).getReject());
                jgVehicleInformation.setPromoter("");
            }
            if (isFirst) {
                this.buildTask(jgVehicleInformation, workflowResultDto);
            } else {
                // 更新代办状态
                HashMap<String, Object> params = new HashMap<>();
                params.put("relationId", jgVehicleInformation.getInstanceId());
                params.put("flowStatus", commonService.getDictionaryCodeByName(jgVehicleInformation.getStatus()));
                params.put("flowStatusLabel", jgVehicleInformation.getStatus());
                params.put("taskStatus", commonService.getDictionaryCodeByName(jgVehicleInformation.getStatus()));
                params.put("taskStatusLabel", jgVehicleInformation.getStatus());
                TaskV2Model taskV2Model = commonService.updateTaskModel(params);
                // 创建新的代办
                if (!ObjectUtils.isEmpty(taskV2Model)) {
                    TaskModelDto taskModelDto = new TaskModelDto();
                    BeanUtils.copyProperties(taskV2Model, taskModelDto);
                    TaskMessageDto taskMessageDto = new TaskMessageDto();
                    BeanUtil.copyProperties(jgVehicleInformation, taskMessageDto);
                    taskModelDto.setModel(taskMessageDto);
                    taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
                    taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                    taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                    taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
                    taskModelDto.setFlowCode(workflowResultDto.getNextTaskId());
                    if (WorkFlowStatusEnum.USE_SUBMIT.getCode().equals(taskCode) && "1".equals(operate)) {
                        taskModelDto.setPageType("edit");
                    }
                    commonService.buildTaskModel(Collections.singletonList(taskModelDto));
                } else {
                    workflowResultDto.setInstanceId(jgVehicleInformation.getInstanceId());
                    buildTask(jgVehicleInformation, workflowResultDto);
                }
            }
        } else {
            // 流程结束
            jgVehicleInformation.setStatus(taskCode);
            jgVehicleInformation.setNextExecuteUserIds("");

            // 生成使用登记证编号
            String receiveCompanyCode = jgVehicleInformation.getReceiveCompanyCode();
            CompanyModel receiveCompanyResult = Privilege.companyClient.queryByCompanyCode(receiveCompanyCode).getResult();
            //查询到局级
            // 如果不是局级公司，则查询其上级公司信息
            if (!"prefecture-level".equals(receiveCompanyResult.getLevel())) {
                CompanyModel receiveParentResult = Privilege.companyClient.seleteOne(receiveCompanyResult.getParentId()).getResult();
                receiveCompanyCode = receiveParentResult.getCompanyCode();
            }
            String code = this.generateVehicleUseRegistrationCode(receiveCompanyCode, equDefineCode);
            jgVehicleInformation.setUseRegistrationCode(code);
            jgVehicleInformation.setAuditPassDate(new Date());

            LambdaQueryWrapper<JgRegistrationHistory> lambdaSelect = new QueryWrapper<JgRegistrationHistory>().lambda();
            lambdaSelect.eq(JgRegistrationHistory::getCurrentDocumentId, String.valueOf(sequenceNbr));
            JgRegistrationHistory jgRegistrationHistory = jgRegistrationHistoryService.getBaseMapper().selectOne(lambdaSelect);
            String jsonData = jgRegistrationHistory.getChangeData();
            JSONArray jsonArray = JSONArray.parseArray(jsonData);

            // 登记证记录主键
            Long changeRecordId = sequence.nextId();

            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject mapData = jsonArray.getJSONObject(i);
                // 设备ID
                String equId = String.valueOf(mapData.get("record"));

                // 查询注册信息
                LambdaQueryWrapper<IdxBizJgRegisterInfo> queryRegisterWrapper = new QueryWrapper<IdxBizJgRegisterInfo>().lambda();
                queryRegisterWrapper.eq(IdxBizJgRegisterInfo::getRecord, equId);
                IdxBizJgRegisterInfo registerInfo = idxBizJgRegisterInfoMapper.selectOne(queryRegisterWrapper);
                registerInfo.setUseOrgCode(code);

                // 更新注册登记信息表
                LambdaUpdateWrapper<IdxBizJgRegisterInfo> updateRegisterWrapper = new UpdateWrapper<IdxBizJgRegisterInfo>().lambda();
                // 新增页面选择无设备代码后，在审批通过后自动生成设备代码
                jgUseRegistrationService.justGenerateEquCode(updateRegisterWrapper, registerInfo, jgVehicleInformation.getReceiveCompanyCode(), mapData, jgRegistrationHistory);
                updateRegisterWrapper.eq(IdxBizJgRegisterInfo::getRecord, registerInfo.getRecord());
                updateRegisterWrapper.set(true, IdxBizJgRegisterInfo::getUseOrgCode, code);
                updateRegisterWrapper.set(IdxBizJgRegisterInfo::getRegisterState, this.getRegCode());
                idxBizJgRegisterInfoService.update(updateRegisterWrapper);

                // 查询其他信息
                LambdaQueryWrapper<IdxBizJgOtherInfo> otherInfoWrapper = new QueryWrapper<IdxBizJgOtherInfo>().lambda();
                otherInfoWrapper.eq(IdxBizJgOtherInfo::getRecord, equId);
                IdxBizJgOtherInfo otherInfo = otherInfoMapper.selectOne(otherInfoWrapper);

                // 更新设备信息
                this.updateEquipMessage(jgVehicleInformation, mapData, registerInfo, otherInfo);

                // 更新es
                updateEsData(mapData, jgVehicleInformation, otherInfo);

                // 查询设备制造信息
                LambdaQueryWrapper<IdxBizJgFactoryInfo> factoryInfoWrapper = new LambdaQueryWrapper<>();
                factoryInfoWrapper.eq(IdxBizJgFactoryInfo::getRecord, equId);
                IdxBizJgFactoryInfo idxBizJgFactoryInfo = idxBizJgFactoryInfoMapper.selectOne(factoryInfoWrapper);

                // 生成tzs_jg_certificate_change_record_eq记录
                JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq();
                changeRecordEq.setChangeRecordId(String.valueOf(changeRecordId));//登记证记录主键
                changeRecordEq.setEquId(registerInfo.getRecord());//设备主键
                changeRecordEq.setProductCode(idxBizJgFactoryInfo.getFactoryNum());//产品编号
                certificateChangeRecordEqService.save(changeRecordEq);
            }
            // 更新新生成的历史数据的设备代码
            jgRegistrationHistory.setChangeData(JSON.toJSONString(jsonArray));
            jgRegistrationHistoryService.updateById(jgRegistrationHistory);

            // 更新代办状态
            HashMap<String, Object> params = new HashMap<>();
            params.put("relationId", jgVehicleInformation.getInstanceId());
            params.put("flowStatus", commonService.getDictionaryCodeByName(jgVehicleInformation.getStatus()));
            params.put("flowStatusLabel", jgVehicleInformation.getStatus());
            params.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
            params.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
            TaskMessageDto taskMessageDto = new TaskMessageDto();
            BeanUtil.copyProperties(jgVehicleInformation, taskMessageDto);
            params.put("model", taskMessageDto);
            TaskV2Model taskV2Model = commonService.updateTaskModel(params);

            // 取第一条设备的注册消息--用来获取这一批设备的设备种类/类别/品种
            LambdaQueryWrapper<IdxBizJgRegisterInfo> lambdaReg = new QueryWrapper<IdxBizJgRegisterInfo>().lambda();
            lambdaReg.eq(IdxBizJgRegisterInfo::getRecord, String.valueOf(jsonArray.getJSONObject(0).get("record")));
            IdxBizJgRegisterInfo registerInfo = idxBizJgRegisterInfoMapper.selectOne(lambdaReg);

            // 生成证书管理表记录
            generateRegistrationManage(jgVehicleInformation, registerInfo);

            // 生成一条tzs_jg_certificate_change_record记录
            generateCertificateChangeRecord(jgVehicleInformation, registerInfo, changeRecordId, taskV2Model);
        }
        this.getBaseMapper().updateById(jgVehicleInformation);
        commonService.saveExecuteFlowData2Redis(jgVehicleInformation.getInstanceId(), this.buildInstanceRuntimeData(jgVehicleInformation));
    }

    private void updateEsData(JSONObject dataMap, JgVehicleInformation jgVehicleInformation, IdxBizJgOtherInfo otherInfo) {
        // 更新es
        HashMap<String, Map<String, Object>> objMap = new HashMap<>();
        HashMap<String, Object> param = new HashMap<>();
        param.put("SUPERVISORY_CODE", otherInfo.getSupervisoryCode());
        param.put("USE_UNIT_CREDIT_CODE", dataMap.get("useUnitCreditCode"));
        param.put("USE_UNIT_NAME", dataMap.get("useUnitName"));
        param.put("ADDRESS", dataMap.getOrDefault("address", ""));
        param.put("USE_PLACE", jgVehicleInformation.getUseUnitAddress());
        param.put("STATUS", "已认领");
        param.put("EQU_STATE", 1);
        param.put("IS_INTO_MANAGEMENT", true);
        param.put("USE_PLACE_CODE", "610000#" + jgVehicleInformation.getVehicleApanage());
        param.put("ORG_BRANCH_CODE", jgVehicleInformation.getOrgBranchCode());
        param.put("ORG_BRANCH_NAME", jgVehicleInformation.getOrgBranchName());
        param.put("EQU_CODE", dataMap.get("equCode"));
        param.put("USE_ORG_CODE", jgVehicleInformation.getUseRegistrationCode());
        objMap.put((String) dataMap.get("record"), param);
        tzsServiceFeignClient.commonUpdateEsDataByIds(objMap);
    }

    private void buildTask(JgVehicleInformation jgVehicleInformation, WorkflowResultDto workflowResultDto) {
        // 代办消息
        ArrayList<TaskModelDto> list = new ArrayList<>();
        TaskModelDto dto = new TaskModelDto();
        dto.setTaskType(String.valueOf(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getCode()));
        dto.setTaskTypeLabel(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName());
        dto.setFlowCreateDate(jgVehicleInformation.getCreateDate());
        dto.setTaskName(workflowResultDto.getNextTaskName());//
        dto.setTaskCode(workflowResultDto.getNextTaskCode());
        dto.setRelationId(workflowResultDto.getInstanceId());
        dto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
        dto.setTaskStatus(commonService.getDictionaryCodeByName(WorkFlowStatusEnum.getMessage(workflowResultDto.getNextTaskCode()).getPass()));
        dto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
        dto.setFlowStatus(commonService.getDictionaryCodeByName(jgVehicleInformation.getStatus()));
        dto.setFlowStatusLabel(jgVehicleInformation.getStatus());
        dto.setStartUserId(jgVehicleInformation.getCreateUserId());
        dto.setStartUser(jgVehicleInformation.getRecUserName());
        dto.setStartUserCompanyName(jgVehicleInformation.getUseUnitName());
        dto.setStartDate(new Date());
        jgVehicleInformation.setInstanceId(workflowResultDto.getInstanceId());
        // 设备信息
        jgVehicleInformation.setNextExecuteIds(workflowResultDto.getNextExecutorRoleIds());
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtil.copyProperties(jgVehicleInformation, taskMessageDto);
        dto.setModel(taskMessageDto);
        dto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
        dto.setTaskContent("来自车用气瓶【" + jgVehicleInformation.getCarNumber() + "】的登记业务办理," + "【申请单号：" + jgVehicleInformation.getApplyNo() + "】");
        dto.setFlowCode(jgVehicleInformation.getNextTaskId());
        list.add(dto);
        commonService.buildTaskModel(list);
    }

    /**
     * 批量删除
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(List<Long> ids) {
        ids.forEach(id -> {
            JgVehicleInformation vehicleInformation = this.baseMapper.selectById(id);
            // 删除代办 + 中止流程
            commonService.deleteTaskModel(String.valueOf(id), vehicleInformation.getInstanceId());
            // 删除单子
            this.deleteBySeq(id);
            // 删除单子对应设备
            jgVehicleInformationEqMapper.delete(new LambdaQueryWrapper<JgVehicleInformationEq>()
                    .eq(JgVehicleInformationEq::getVehicleId, id));
            // 删除单子对应历史表数据
            jgRegistrationHistoryService.getBaseMapper().delete(new LambdaQueryWrapper<JgRegistrationHistory>()
                    .eq(JgRegistrationHistory::getCurrentDocumentId, vehicleInformation.getSequenceNbr()));
        });
    }

    public Page<Map<String, Object>> getPageList(JgVehicleInformationDto dto, String sort, Page<Map<String, Object>> page, List<String> roleIds) {
        SortVo sortMap = commonService.sortFieldConversion(sort);
        return this.baseMapper.getListPage(page, sortMap, dto, roleIds);
    }

    private void updateEquipMessage(JgVehicleInformation jgVehicleInformation, JSONObject map, IdxBizJgRegisterInfo registerInfo, IdxBizJgOtherInfo otherInfo) {
        String useOrgCode = jgVehicleInformation.getUseRegistrationCode();
        map.remove("status");
        map.remove("instanceId");
        map.remove("REC_DATE");
        IdxBizJgUseInfo useInfo = new IdxBizJgUseInfo();
        BeanUtil.copyProperties(map, useInfo);
        // 判断是否为西咸
        String isXiXian = XI_XIAN.getCode().equals(jgVehicleInformation.getVehicleApanage()) ? "1" : "0";
        jgVehicleInformation.setIsXixian(isXiXian);
        useInfo.setIsNotXiXian(isXiXian);
        useInfo.setProvince("610000");
        useInfo.setIsIntoManagement(Boolean.TRUE);
        useInfo.setAddress(jgVehicleInformation.getUseUnitAddress());
        LambdaQueryWrapper<IdxBizJgUseInfo> lambda = new QueryWrapper<IdxBizJgUseInfo>().lambda();
        lambda.eq(IdxBizJgUseInfo::getRecord, map.get("record"));

        // 修改设备使用状态为在用
        useInfo.setEquState(String.valueOf(EquimentEnum.ZAIYONG.getCode()));
        // 更新使用信息
        useInfoMapper.update(useInfo, lambda);

        //InspectionDetectionInfo inspectionDetectionInfo = new InspectionDetectionInfo();
        //BeanUtil.copyProperties(map, inspectionDetectionInfo);
        //LambdaQueryWrapper<InspectionDetectionInfo> inspectionLambda = new QueryWrapper<InspectionDetectionInfo>().lambda();
        //inspectionLambda.eq(InspectionDetectionInfo::getRecord, map.get("record"));
        // 更新检验检测信息
        //inspectionDetectionInfo.setInspectReport(jgVehicleInformation.getInspectionCertificate());
        //inspectionDetectionInfo.setInspectOrgName(jgVehicleInformation.getInspectUnitName());
        //inspectionDetectionInfo.setInspectOrgCode(jgVehicleInformation.getInspectUnitCreditCode());
        //inspectionDetectionInfo.setNextInspectDate(jgVehicleInformation.getNextInspectionDate());
        //inspectionDetectionInfoMapper.update(inspectionDetectionInfo, inspectionLambda);

        // 更新设备监管部门
        IdxBizJgSupervisionInfo idxBizJgSupervisionInfo = new IdxBizJgSupervisionInfo();
        if (map.containsKey("orgBranchCode") && !ObjectUtils.isEmpty(map.get("orgBranchCode"))) {
            String[] data = String.valueOf(map.getString("orgBranchCode")).split("_");
            HashMap<String, Object> parentMessage = (HashMap<String, Object>) Privilege.companyClient.queryByOrgcode(data[0]).getResult();
            // 目前平台返回key为compnay(存在拼写错误)
            CompanyModel parentModel = JSON.parseObject(JSON.toJSONString(parentMessage.get("compnay")), CompanyModel.class);
            idxBizJgSupervisionInfo.setOrgBranchCode(data[0]);
            idxBizJgSupervisionInfo.setOrgBranchName(data[1]);
            idxBizJgSupervisionInfo.setCompanyOrgBranchCode(parentModel.getCompanyCode());
            LambdaQueryWrapper<IdxBizJgSupervisionInfo> eq = new QueryWrapper<IdxBizJgSupervisionInfo>().lambda().eq(IdxBizJgSupervisionInfo::getRecord, map.get("record"));
            idxBizJgSupervisionInfoMapper.update(idxBizJgSupervisionInfo, eq);
        }
        // 更新设备使用登记证
        idxBizJgRegisterInfoMapper.updateUseOrgCodeByEquip(String.valueOf(map.get("record")), useOrgCode);
        // 车用气瓶生成监管码
        this.createCode(jgVehicleInformation, registerInfo, otherInfo);
    }

    /**
     * 生成监管码
     */
    public void createCode(JgVehicleInformation jgVehicleInformation, IdxBizJgRegisterInfo registerInfo, IdxBizJgOtherInfo otherInfo) {
        Map<String, Object> map = new HashMap<>();
        map.put("cityCode", XI_XIAN.getCode().equals(jgVehicleInformation.getVehicleApanage()) ? XIAN_YANG.getCode() : jgVehicleInformation.getVehicleApanage());
        map.put("isXiXian", jgVehicleInformation.getIsXixian());
        map.put("equCategory", registerInfo.getEquCategory());
        map.put("countyCode", XI_XIAN.getCode().equals(jgVehicleInformation.getVehicleApanage()) ? XIAN_YANG.getCode() : jgVehicleInformation.getVehicleApanage());

        // 调用服务创建代码
        ResponseModel<Map<String, Object>> code = tzsServiceFeignClient.createCode(map);
        Map<String, Object> result = code.getResult();

        // 更新其他信息
        if (result != null && !result.isEmpty()) {
            otherInfo.setSupervisoryCode(String.valueOf(result.get("superviseCode")));
            otherInfo.setClaimStatus("已认领");
            otherInfoMapper.updateById(otherInfo);
        }
    }

    /**
     * 获取类型为ZC的“已注册”的字典值
     *
     * @return code
     */
    private String getRegCode() {
        QueryWrapper<DataDictionary> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("type", "ZC");
        queryWrapper.eq("name", "已注册");
        queryWrapper.eq("is_delete", false);
        List<DataDictionary> list = iDataDictionaryService.list(queryWrapper);
        if (!list.isEmpty() && list.get(0) != null) {
            DataDictionary dictionary = list.get(0);
            return Optional.ofNullable(dictionary).map(DataDictionary::getCode).orElse("");
        }
        return "";
    }

    /**
     * 根据车辆属地生成使用登记证
     *
     * @param receiveCompanyCode 车辆属地
     * @return String
     */
    private String generateVehicleUseRegistrationCode(String receiveCompanyCode, String equDefineCode) {
        // 构建设备种类简称
        String useRegistration = String.format("瓶%s%s", equDefineCode.substring(1, 3), VehicleApanageEnum.of(receiveCompanyCode));
        // 调用服务端获取注册码
        ResponseModel<String> stringResponseModel = tzsServiceFeignClient.useRegistrationCode(useRegistration);
        return stringResponseModel.getResult();
    }

    /**
     * 打印车用气瓶登记证
     *
     * @param response    response
     * @param sequenceNbr 主键
     * @param printType   打印类型
     */
    public void exportVehicleUseRegistrationCertificate(String sequenceNbr, HttpServletResponse response, String printType) {
        Map<String, Object> exportParamsMap = new HashMap<>();
        JgVehicleInformation vehicleInformation = this.getById(sequenceNbr);

        if (Stream.of(vehicleInformation)
                .map(JgVehicleInformation::getReceiveOrgName)
                .anyMatch(Objects::isNull) ||
                Stream.of(vehicleInformation.getUseRegistrationCode(),
                                vehicleInformation.getUseUnitName(),
                                vehicleInformation.getUseUnitAddress())
                        .anyMatch(Objects::isNull)) {
            throw new BadRequest("使用登记证导出失败,请稍后重试或检查数据完整性!");
        }
        exportParamsMap.put("receiveOrgName", vehicleInformation.getReceiveOrgName());
        exportParamsMap.put("useRegistrationCode", vehicleInformation.getUseRegistrationCode());
        exportParamsMap.put("useUnitName", vehicleInformation.getUseUnitName());
        exportParamsMap.put("fullAddress", vehicleInformation.getUseUnitAddress());
        exportParamsMap.put("equDefineCode", "23T0");
        getAuditPassedDate(vehicleInformation.getAuditPassDate(), exportParamsMap);

        List<JgVehicleInformationEq> vehicleInformationEqList = jgVehicleInformationEqMapper.selectList(new QueryWrapper<JgVehicleInformationEq>().lambda().eq(JgVehicleInformationEq::getVehicleId, sequenceNbr));
        if (vehicleInformationEqList.isEmpty()) {
            throw new BadRequest("使用登记证导出失败,请稍后重试或检查数据完整性!");
        }

        List<IdxBizJgRegisterInfo> registerInfoList = idxBizJgRegisterInfoMapper.selectList(new QueryWrapper<IdxBizJgRegisterInfo>().in("RECORD", vehicleInformationEqList.stream()
                .map(JgVehicleInformationEq::getEquId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList())));
        if (!ValidationUtil.isEmpty(registerInfoList)) {
            populateEquipmentInformation(registerInfoList, exportParamsMap);
        }

        List<IdxBizJgUseInfo> userInfoList = idxBizJgUseInfoService.list(new QueryWrapper<IdxBizJgUseInfo>().in("RECORD", vehicleInformationEqList.stream()
                .map(JgVehicleInformationEq::getEquId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList())));

        //if (!ValidationUtil.isEmpty(userInfoList)) {
        //    exportParamsMap.put("useInnerCode", userInfoList.stream()
        //            .map(IdxBizJgUseInfo::getUseInnerCode)
        //            .filter(Objects::nonNull)
        //            .distinct()
        //            .collect(Collectors.joining(", ")));
        //}
        if (!ValidationUtil.isEmpty(userInfoList)) {
            exportParamsMap.put("useInnerCode", vehicleInformation.getCarNumber());
        }


        List<IdxBizJgFactoryInfo> factoryInfoList = idxBizJgFactoryInfoMapper.selectList(new QueryWrapper<IdxBizJgFactoryInfo>().in("RECORD", vehicleInformationEqList.stream()
                .map(JgVehicleInformationEq::getEquId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList())));

        if (!ValidationUtil.isEmpty(factoryInfoList)) {
            exportParamsMap.put("factoryNum", factoryInfoList.stream()
                    .map(IdxBizJgFactoryInfo::getFactoryNum)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.joining(", ")));
        }
        exportParamsMap.put("applyNo", vehicleInformation.getApplyNo());
        this.generateReport(vehicleInformation, printType, exportParamsMap, response);
    }

    public void exportVehicleUseRegistrationForm(String sequenceNbr, HttpServletResponse response, String printType) {
        Map<String, Object> exportParamsMap = new HashMap<>();
        JgVehicleInformation vehicleInformation = this.getById(sequenceNbr);
        List<JgVehicleInformationEq> vehicleInformationEqList = jgVehicleInformationEqMapper.selectList(new QueryWrapper<JgVehicleInformationEq>().lambda().eq(JgVehicleInformationEq::getVehicleId, sequenceNbr));
        if (vehicleInformationEqList.isEmpty()) {
            throw new BadRequest("使用登记证导出失败,请稍后重试或检查数据完整性!");
        }
        List<IdxBizJgRegisterInfo> registerInfoList = idxBizJgRegisterInfoMapper.selectList(new QueryWrapper<IdxBizJgRegisterInfo>().in("RECORD", vehicleInformationEqList.stream()
                .map(JgVehicleInformationEq::getEquId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList())));

        Optional<IdxBizJgRegisterInfo> optionalRegisterInfo = registerInfoList.stream().findFirst();
        String equDefine = "";
        if (optionalRegisterInfo.isPresent()) {
            IdxBizJgRegisterInfo registerInfo = optionalRegisterInfo.get();
            equDefine = registerInfo.getEquDefine();
        }

        List<EquipBasicInfoDto> equipBasicInfoList = this.baseMapper.queryForUnitVesselEquipment(Long.valueOf(sequenceNbr),
                        vehicleInformationEqList.stream()
                                .map(JgVehicleInformationEq::getEquId)
                                .collect(Collectors.toList())).stream()
                .map(map -> {
                    String useInnerCode = Objects.toString(map.get("useInnerCode"), "");
                    String produceUnitName = Objects.toString(map.get("produceUnitName"), "");
                    String factoryNum = Objects.toString(map.get("factoryNum"), "");
                    String produceDate = Objects.toString(map.get("produceDate"), "");
                    double nominalWorkingPressure = map.get("nominalWorkingPressure") != null ?
                            Double.parseDouble(map.get("nominalWorkingPressure").toString()) : 0.0;
                    exportParamsMap.merge("workPressure", nominalWorkingPressure, (oldVal, newVal) -> (double) oldVal + (double) newVal);
                    return new EquipBasicInfoDto(produceUnitName, produceDate, factoryNum, useInnerCode);
                })
                .collect(Collectors.toList());

        //填写本次办理使用登记的事由， 如新设备首次启用、 停用后启用、 改造、 使用单位更名、 使用地址变更、 过户、 移装、 达到设计使用年限等。
        exportParamsMap.put("registrationType", "新设备首次启用");
        exportParamsMap.put("equDefineName", CylinderTypeEnum.of(equDefine));
        exportParamsMap.put("equipDefine", "车用气瓶");
        exportParamsMap.put("gasNum", vehicleInformation.getGasNum());
        exportParamsMap.put("chargingMedium", vehicleInformation.getFillingMedium());
        exportParamsMap.put("volume", vehicleInformation.getVolume());
        exportParamsMap.put("equipBasicInfoList", equipBasicInfoList);
        exportParamsMap.put("installUnitName", vehicleInformation.getInstallUnitName());
        exportParamsMap.put("inspectUnitName", vehicleInformation.getInspectUnitName());
        exportParamsMap.put("useUnitName", vehicleInformation.getUseUnitName());
        exportParamsMap.put("useUnitAddress", vehicleInformation.getUseUnitAddress());
        exportParamsMap.put("useUnitCreditCode", vehicleInformation.getUseUnitCreditCode());
        exportParamsMap.put("carNumber", vehicleInformation.getCarNumber());
        exportParamsMap.put("identificationCode", vehicleInformation.getIdentificationCode());
        exportParamsMap.put("safetyManagerName", vehicleInformation.getSafetyManagerName());
        exportParamsMap.put("phone", vehicleInformation.getPhone());
        handleAuditPassedDate(vehicleInformation.getAuditPassDate(), exportParamsMap);
        exportParamsMap.put("useRegistrationCode", vehicleInformation.getUseRegistrationCode());
        String wordPath = "use-registration-form.ftl";
        // word转pdf
        File pdfFile;
        try {
            pdfFile = commonService.wordToPdf("车用气瓶使用登记表_", wordPath, exportParamsMap);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try {
            byte[] bytes = CommonServiceImpl.file2byte(pdfFile);
            String docTitle = pdfFile.getName();
            FileExporter.exportFile(FileExporter.FileType.valueOf("pdf"), docTitle, bytes, response);
        } catch (Exception e) {
            log.error("pdf文件转换失败：{}", e);
        } finally {
            try {
                Files.deleteIfExists(pdfFile.toPath());
            } catch (Exception e) {
                log.error("文件找不到，删除失败：{}", e);
            }
        }
    }

    private void generatePdfPrint(Map<String, Object> map, HttpServletResponse response) {
        // 设置默认值
        Arrays.stream(DEFAULT_KEYS).forEach(key -> map.computeIfAbsent(key, k -> ""));
        // 生成二维码,之前为设备监管码，调整为申请单号
        String qrCode = ImageUtils.generateQRCode((String) map.getOrDefault("applyNo", ""), 100, 100);
        map.put("supervisoryCode", qrCode);
        commonService.fillParamValueToPdf(map, response, "templates/use-registration-model-vehicle.pdf", "套打使用登记证.pdf", 12.0f);
    }

    private void generateReport(JgVehicleInformation vehicleInformation, String printType, Map<String, Object> exportParamsMap, HttpServletResponse response) {
        switch (printType) {
            case "0":
                // 使用登记证-普通打印--
                commonService.generateCertificateReport(exportParamsMap, response);
                break;
            case "1":
                // 使用登记证-套打--
                //this.generatePdfPrint(exportParamsMap, response);
                commonService.generateCertificateReportDoc(exportParamsMap, response);
                break;
            case "2":
                // 使用标志-普通打印--
                commonService.useFlagGenerate(buildUseFlagParam(vehicleInformation, exportParamsMap), response);
                break;
            case "3":
                // 使用标志-套打--
                commonService.fightUseFlagGenerate(this.setProductNameWithStatic(vehicleInformation, exportParamsMap), response);
                break;
            default:
                throw new BadRequest("Invalid print type");
        }
    }

    private UseFlagParamDto setProductNameWithStatic(JgVehicleInformation vehicleInformation, Map<String, Object> exportParamsMap) {
        UseFlagParamDto useFlagParamDto = buildUseFlagParam(vehicleInformation, exportParamsMap);
        useFlagParamDto.setEquipDefine("车用气瓶");
        return useFlagParamDto;
    }

    private void populateEquipmentInformation(List<IdxBizJgRegisterInfo> registerInfoList, Map<String, Object> exportParamsMap) {
        Optional<IdxBizJgRegisterInfo> optionalRegisterInfo = registerInfoList.stream().findFirst();
        if (optionalRegisterInfo.isPresent()) {
            IdxBizJgRegisterInfo registerInfo = optionalRegisterInfo.get();
            String equList = registerInfo.getEquList();
            String equCategory = registerInfo.getEquCategory();
            String equDefine = registerInfo.getEquDefine();
            List<EquipmentCategory> categoryList0 = commonService.getEquipmentCategoryList(equList, null);
            List<EquipmentCategory> categoryList1 = commonService.getEquipmentCategoryList(equCategory, null);
            if (notEmptyAndHasName(categoryList0)) {
                exportParamsMap.put("equList", categoryList0.get(0).getName());
            }
            if (notEmptyAndHasName(categoryList1)) {
                exportParamsMap.put("equCategory", categoryList1.get(0).getName());
            }
            exportParamsMap.put("equDefine", CylinderTypeEnum.of(equDefine));
            if (registerInfoList.stream().anyMatch(r -> r.getEquCode() == null)) {
                throw new BadRequest("使用登记证导出失败，设备代码为空！");
            }
            exportParamsMap.put("equCode", registerInfoList.stream()
                    .map(IdxBizJgRegisterInfo::getEquCode)
                    .filter(Objects::nonNull)
                    .collect(Collectors.joining(", ")));
            exportParamsMap.put("equListCode", equList);
        }
    }

    private boolean notEmptyAndHasName(List<EquipmentCategory> categoryList) {
        return !categoryList.isEmpty() && categoryList.get(0).getName() != null;
    }

    private UseFlagParamDto buildUseFlagParam(JgVehicleInformation vehicleInformation, Map<String, Object> exportParamsMap) {
        UseFlagParamDto useFlagParamDto = new UseFlagParamDto();
        useFlagParamDto.setEquList(exportParamsMap.get("equList") + "");
        useFlagParamDto.setEquListCode("0000");
        useFlagParamDto.setEquipCode(exportParamsMap.get("equCode") + "");
        useFlagParamDto.setEquipDefine(exportParamsMap.get("equDefine") == null ? "" : exportParamsMap.get("equDefine") + "");
        useFlagParamDto.setEquipCategory(exportParamsMap.get("equCategory") + "");
        useFlagParamDto.setUseUnitName(exportParamsMap.get("useUnitName") + "");
        useFlagParamDto.setUseInnerCode(exportParamsMap.get("useInnerCode") + "");
        useFlagParamDto.setReceiveOrgName(vehicleInformation.getReceiveOrgName());
        useFlagParamDto.setReceiveCompanyCode(vehicleInformation.getReceiveCompanyCode());
        useFlagParamDto.setNextInspectionDate(vehicleInformation.getNextInspectionDate());
        useFlagParamDto.setUseRegistrationCode(exportParamsMap.get("useRegistrationCode") + "");
        useFlagParamDto.setCarNumber(vehicleInformation.getCarNumber());
        useFlagParamDto.setFactoryNumber(exportParamsMap.get("factoryNum") + "");
        useFlagParamDto.setCylinderNumOrVolume(vehicleInformation.getGasNum() + "/" + vehicleInformation.getVolume());
        useFlagParamDto.setFillingMedium(vehicleInformation.getFillingMedium());
        useFlagParamDto.setApplyNo(vehicleInformation.getApplyNo());
        useFlagParamDto.setInspectionUnitName(vehicleInformation.getInspectUnitName());
        return useFlagParamDto;
    }

    private void checkVesselCylinderIsUsed(Long currentVehicleId, List<String> records) {
        Long usedNumber = this.getBaseMapper().countVesselCylinderIsUsedNumber(currentVehicleId, records);
        if (usedNumber > 0) {
            throw new BadRequest("存在已经登记过的气瓶！");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public JgVehicleInformation cancelApplication(Long sequenceNbr, String cancelReason) {
        // 1.更新为已作废
        JgVehicleInformation vehicleInformation = this.getById(sequenceNbr);
        String oldStatus = vehicleInformation.getStatus();
        vehicleInformation.setStatus(FlowStatusEnum.TO_BE_DISCARD.getName());
        vehicleInformation.setCancelReason(cancelReason);
        vehicleInformation.setCancelDate(new Date());
        vehicleInformation.setCancelUserId(RequestContext.getExeUserId());
        vehicleInformation.setNextExecuteUserIds("");
        vehicleInformation.setPromoter("");
        this.updateById(vehicleInformation);
        // 2.更新关联的业务
        processElseDataByStatus(oldStatus, vehicleInformation);
        return vehicleInformation;
    }


    private void processElseDataByStatus(String flowStatus, JgVehicleInformation vehicleInformation) {
        switch (flowStatus) {
            case "使用单位待提交":
                // 1.删除暂存时生成的待办
                commonService.deleteTasksByRelationId(vehicleInformation.getSequenceNbr() + "");
                break;
            case "已完成":
                // 1.删除与设备的关系，设备可再次发起使用登记
                this.clearUseInfoOfEquip(vehicleInformation);
                // 3.作废对应的使用登记证
                this.invalidUseRegistrationCertificate(vehicleInformation);
                break;
            default:
                // 流程中
                // 1.待办任务更新为已完成
                this.finishedTask(vehicleInformation);
                // 2.终止流程-工作流报错暂时注释掉
                cmWorkflowService.stopProcess(vehicleInformation.getInstanceId(), vehicleInformation.getCancelReason());
                // 3.释放流程占用的设备
                this.delRepeatUseEquipData(vehicleInformation);

        }
    }

    /**
     * 作废使用登记证 & 生成使用登记证的流水
     */
    private void invalidUseRegistrationCertificate(JgVehicleInformation jgVehicleInformation) {
        Integer count = this.baseMapper.selectCount(new LambdaQueryWrapper<JgVehicleInformation>()
                .eq(JgVehicleInformation::getUseRegistrationCode, jgVehicleInformation.getUseRegistrationCode()));
        // 一证对应多条使用登记单时，不作废证
        if (count > 1) {
            return;
        }
        JgUseRegistrationManage registrationManage = new JgUseRegistrationManage();
        registrationManage.setCertificateStatus(CertificateStatusEnum.YIZHUXIAO.getName());
        LambdaQueryWrapper<JgUseRegistrationManage> wrapper = new LambdaQueryWrapper<JgUseRegistrationManage>()
                .eq(JgUseRegistrationManage::getUseRegistrationCode, jgVehicleInformation.getUseRegistrationCode());
        jgUseRegistrationManageService.update(registrationManage, wrapper);

        // 生成使用登记证的作废流水
        Optional<JgCertificateChangeRecord> firstRecord = certificateChangeRecordService.getBaseMapper().selectList(new LambdaQueryWrapper<JgCertificateChangeRecord>()
                        .eq(JgCertificateChangeRecord::getUseRegistrationCode, jgVehicleInformation.getUseRegistrationCode())
                        .orderByAsc(JgCertificateChangeRecord::getCreateDate))
                .stream()
                .findFirst();

        JgCertificateChangeRecord changeRecord = new JgCertificateChangeRecord();
        changeRecord.setApplyNo(jgVehicleInformation.getApplyNo());
        changeRecord.setReceiveOrgName(jgVehicleInformation.getReceiveOrgName());
        changeRecord.setAuditPassDate(new Date());
        changeRecord.setRegType(BusinessTypeEnum.JG_USAGE_REGISTRATION.getName());
        changeRecord.setRegDate(jgVehicleInformation.getCreateDate());
        changeRecord.setChangeContent(this.buildVoidRecordContent(jgVehicleInformation));// 变更内容
        changeRecord.setUseRegistrationCode(jgVehicleInformation.getUseRegistrationCode());// 使用登记编号
        changeRecord.setReceiveCompanyCode(jgVehicleInformation.getReceiveCompanyCode());// 接收机构公司代码
        changeRecord.setUseUnitCreditCode(jgVehicleInformation.getUseUnitCreditCode());// 使用单位统一信用代码
        changeRecord.setUseUnitName(jgVehicleInformation.getUseUnitName());// 使用单位名称
        firstRecord.ifPresent(record -> changeRecord.setEquCategory(record.getEquCategory()));// 设备类别编码
        changeRecord.setCreateDate(new Date());
        firstRecord.ifPresent(record -> changeRecord.setRoutePath(record.getRoutePath()));
        certificateChangeRecordService.save(changeRecord);
    }

    /**
     * 作废的证变更内容
     *
     * @param obj JgVehicleInformation
     * @return result
     */
    private String buildVoidRecordContent(JgVehicleInformation obj) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        String companyType = reginParams.getCompany().getCompanyType();
        //监管单位 作废了【使用功能登记】 ，单号【DWBG202407050001】，作废日期2024-07-05
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        return companyType + "作废了【" + BusinessTypeEnum.JG_USAGE_REGISTRATION.getName() + "】，" +
                "单号【" + obj.getApplyNo() + "】，申请日期" + simpleDateFormat.format(obj.getRecDate());
    }

    private void clearUseInfoOfEquip(JgVehicleInformation vehicleInformation) {
        LambdaQueryWrapper<JgVehicleInformationEq> eqLambdaQueryWrapper = new LambdaQueryWrapper<JgVehicleInformationEq>().eq(JgVehicleInformationEq::getVehicleId, vehicleInformation.getSequenceNbr());
        List<JgVehicleInformationEq> eqList = jgVehicleInformationEqMapper.selectList(eqLambdaQueryWrapper);
        eqList.forEach(e -> {
            String record = e.getEquId();
            // 1.使用信息表部分字段赋空
            this.rollBackUseInfo(record);
            // 2.回滚更新idx_biz_jg_register_info表
            this.rollBackRegisterInfo(record);
            // 3.回滚更新idx_biz_jg_supervision_info表
            this.rollBackSupervisionInfo(record);
            // 4.es的EQU_STATE,  USE_ORG_CODE、ORG_BRANCH_CODE、ORG_BRANCH_NAME、STATUS
            this.rollBackForEquipEsInfo(record);
        });
    }

    private void rollBackForEquipEsInfo(String record) {
        Optional<ESEquipmentCategoryDto> optional = esEquipmentCategory.findById(record);
        if (optional.isPresent()) {
            ESEquipmentCategoryDto esEquipmentCategoryDto = optional.get();
            esEquipmentCategoryDto.setUSE_ORG_CODE(null);
            esEquipmentCategoryDto.setSTATUS(null);
            esEquipmentCategoryDto.setEQU_STATE(null);
            esEquipmentCategoryDto.setORG_BRANCH_CODE(null);
            esEquipmentCategoryDto.setORG_BRANCH_NAME(null);
            esEquipmentCategory.save(esEquipmentCategoryDto);
        }
    }

    private void rollBackSupervisionInfo(String record) {
        LambdaUpdateWrapper<IdxBizJgSupervisionInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(IdxBizJgSupervisionInfo::getRecord, record);
        updateWrapper.set(IdxBizJgSupervisionInfo::getOrgBranchName, null);
        updateWrapper.set(IdxBizJgSupervisionInfo::getOrgBranchCode, null);
        updateWrapper.set(IdxBizJgSupervisionInfo::getCompanyOrgBranchCode, null);
        idxBizJgSupervisionInfoMapper.update(null, updateWrapper);
    }

    private void rollBackRegisterInfo(String record) {
        LambdaUpdateWrapper<IdxBizJgRegisterInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(IdxBizJgRegisterInfo::getRecord, record);
        // 未注册，来源cb_data_dictionary type =  'ZC'
        updateWrapper.set(IdxBizJgRegisterInfo::getRegisterState, "6046");
        updateWrapper.set(IdxBizJgRegisterInfo::getUseOrgCode, null);
        updateWrapper.set(IdxBizJgRegisterInfo::getCarNumber, null);
        idxBizJgRegisterInfoService.update(updateWrapper);
    }

    private void rollBackUseInfo(String record) {
        LambdaUpdateWrapper<IdxBizJgUseInfo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(IdxBizJgUseInfo::getRecord, record);
        updateWrapper.set(IdxBizJgUseInfo::getCity, null);
        updateWrapper.set(IdxBizJgUseInfo::getCityName, null);
        updateWrapper.set(IdxBizJgUseInfo::getCounty, null);
        updateWrapper.set(IdxBizJgUseInfo::getCountyName, null);
        updateWrapper.set(IdxBizJgUseInfo::getStreetName, null);
        updateWrapper.set(IdxBizJgUseInfo::getProvince, null);
        updateWrapper.set(IdxBizJgUseInfo::getProvinceName, null);
        updateWrapper.set(IdxBizJgUseInfo::getEquState, null);
        updateWrapper.set(IdxBizJgUseInfo::getEstateUnitCreditCode, null);
        updateWrapper.set(IdxBizJgUseInfo::getEstateUnitName, null);
        updateWrapper.set(IdxBizJgUseInfo::getUsePlace, null);
        updateWrapper.set(IdxBizJgUseInfo::getLongitudeLatitude, null);
        updateWrapper.set(IdxBizJgUseInfo::getAddress, null);
        updateWrapper.set(IdxBizJgUseInfo::getSafetyManageDt, null);
        updateWrapper.set(IdxBizJgUseInfo::getSafetyManagerId, null);
        updateWrapper.set(IdxBizJgUseInfo::getSafetyManager, null);
        updateWrapper.set(IdxBizJgUseInfo::getFactoryUseSiteStreet, null);
        useInfoMapper.update(null, updateWrapper);
    }


    private void finishedTask(JgVehicleInformation vehicleInformation) {
        HashMap<String, Object> taskMap = new HashMap<>();
        taskMap.put("taskStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
        taskMap.put("taskStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
        taskMap.put("flowStatus", FlowStatusEnum.TO_BE_FINISHED.getCode());
        taskMap.put("flowStatusLabel", FlowStatusEnum.TO_BE_FINISHED.getName());
        taskMap.put("relationId", vehicleInformation.getInstanceId());
        TaskMessageDto taskMessageDto = new TaskMessageDto();
        vehicleInformation.setOtherAccessories(null);
        vehicleInformation.setDriveLicenseBack(null);
        vehicleInformation.setDriveLicenseFront(null);
        BeanUtils.copyProperties(vehicleInformation, taskMessageDto);
        taskMap.put("model", taskMessageDto);
        commonService.updateTaskModel(taskMap);
    }

    private Map<String, Object> getFillingMediumMap() {
        if (fillingMediumMap == null) {
            synchronized (this) {
                if (fillingMediumMap == null) {
                    List<DictionarieValueModel> fillingMedium = FeignUtil.remoteCall(() -> Systemctl.dictionarieClient.dictValues("FILLING_MEDIUM"));
                    fillingMediumMap = fillingMedium.stream().collect(Collectors.toMap(DictionarieValueModel::getDictDataKey, DictionarieValueModel::getDictDataValue));
                    return fillingMediumMap;
                } else {
                    return fillingMediumMap;
                }
            }
        }
        return fillingMediumMap;

    }

    private void generateCertificateChangeRecord(JgVehicleInformation jgVehicleInformation, IdxBizJgRegisterInfo registerInfo, Long changeRecordId, TaskV2Model taskV2Model) {
        Map<String, String> equType = new HashMap<>();
        equType.put("equList", this.baseMapper.getEquCategoryNameByCode(registerInfo.getEquList()));
        equType.put("equListCode", registerInfo.getEquList());
        equType.put("equCategory", this.baseMapper.getEquCategoryNameByCode(registerInfo.getEquCategory()));
        equType.put("equCategoryCode", registerInfo.getEquCategory());
        equType.put("equDefine", this.baseMapper.getEquCategoryNameByCode(registerInfo.getEquDefine()));
        equType.put("equDefineCode", registerInfo.getEquDefine());
        JgCertificateChangeRecord changeRecord = new JgCertificateChangeRecord();
        changeRecord.setApplyNo(jgVehicleInformation.getApplyNo());
        changeRecord.setReceiveOrgName(jgVehicleInformation.getReceiveOrgName());
        changeRecord.setAuditPassDate(new Date());
        changeRecord.setRegType(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName());
        changeRecord.setRegDate(jgVehicleInformation.getCreateDate());
        changeRecord.setChangeContent(this.buildRecordContent(jgVehicleInformation));//变更内容
        changeRecord.setUseRegistrationCode(jgVehicleInformation.getUseRegistrationCode());//使用登记编号
        changeRecord.setReceiveCompanyCode(jgVehicleInformation.getReceiveCompanyCode());//接收机构公司代码
        changeRecord.setCertificateNo(commonService.generateCertificateNo(equType, new Date(), jgVehicleInformation.getReceiveCompanyCode()));//登记证书唯一码
        changeRecord.setUseUnitCreditCode(jgVehicleInformation.getUseUnitCreditCode());//使用单位统一信用代码
        changeRecord.setUseUnitName(jgVehicleInformation.getUseUnitName());//使用单位名称
        changeRecord.setEquCategory(registerInfo.getEquCategory());//设备类别编码
        changeRecord.setRoutePath(Optional.ofNullable(taskV2Model).map(TaskV2Model::getRoutePath).orElse(""));
        changeRecord.setCreateDate(new Date());
        changeRecord.setSequenceNbr(changeRecordId);
        certificateChangeRecordService.save(changeRecord);
    }

    private void generateRegistrationManage(JgVehicleInformation jgVehicleInformation, IdxBizJgRegisterInfo registerInfo) {
        // 使用单位信息
        Map<String, Object> enterpriseInfo = commonService.getEnterpriseInfo(jgVehicleInformation.getUseUnitCreditCode());
        //
        Map<String, String> equType = new HashMap<>();
        equType.put("equList", this.baseMapper.getEquCategoryNameByCode(registerInfo.getEquList()));
        equType.put("equListCode", registerInfo.getEquList());
        equType.put("equCategory", this.baseMapper.getEquCategoryNameByCode(registerInfo.getEquCategory()));
        equType.put("equCategoryCode", registerInfo.getEquCategory());
        equType.put("equDefine", this.baseMapper.getEquCategoryNameByCode(registerInfo.getEquDefine()));
        equType.put("equDefineCode", registerInfo.getEquDefine());
        JgUseRegistrationManage jgUseRegistrationManage = new JgUseRegistrationManage();
        jgUseRegistrationManage.setUseUnitName(jgVehicleInformation.getUseUnitName());
        jgUseRegistrationManage.setApplyNo(jgVehicleInformation.getApplyNo());
        jgUseRegistrationManage.setCertificateStatus(CertificateStatusEnum.YIDENGJI.getName());
        jgUseRegistrationManage.setReceiveOrgName(jgVehicleInformation.getReceiveOrgName());
        jgUseRegistrationManage.setAuditPassDate(jgVehicleInformation.getAuditPassDate());
        jgUseRegistrationManage.setRegType(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName());
        jgUseRegistrationManage.setRegDate(jgVehicleInformation.getRegDate());
        jgUseRegistrationManage.setEquList(equType.get("equList"));
        jgUseRegistrationManage.setEquListCode(equType.get("equListCode"));
        jgUseRegistrationManage.setEquCategory(equType.get("equCategory"));
        jgUseRegistrationManage.setEquCategoryCode(equType.get("equCategoryCode"));
        jgUseRegistrationManage.setEquDefine(equType.get("equDefine"));
        jgUseRegistrationManage.setEquDefineCode(equType.get("equDefineCode"));
        jgUseRegistrationManage.setIsDelete(Boolean.FALSE);
        jgUseRegistrationManage.setRecUserId(jgVehicleInformation.getRecUserId());
        jgUseRegistrationManage.setRecUserName(jgVehicleInformation.getRecUserName());
        jgUseRegistrationManage.setRecDate(jgVehicleInformation.getRecDate());
        jgUseRegistrationManage.setCreateUserId(jgVehicleInformation.getCreateUserId());
        jgUseRegistrationManage.setCreateDate(jgVehicleInformation.getRecDate());
        jgUseRegistrationManage.setEquUseAddress("");
        jgUseRegistrationManage.setManageType("unit");
        jgUseRegistrationManage.setUseUnitAddress(!ValidationUtil.isEmpty(enterpriseInfo) ? (String) enterpriseInfo.get("address") : "");
        jgUseRegistrationManage.setUseRegistrationCode(jgVehicleInformation.getUseRegistrationCode());
        jgUseRegistrationManage.setUseUnitCreditCode(jgVehicleInformation.getUseUnitCreditCode());
        jgUseRegistrationManage.setReceiveCompanyCode(jgVehicleInformation.getReceiveCompanyCode());
        jgUseRegistrationManage.setCarNumber(jgVehicleInformation.getCarNumber());
        jgUseRegistrationManage.setCertificateNo(commonService.generateCertificateNo(equType, new Date(), jgVehicleInformation.getReceiveCompanyCode()));
        jgUseRegistrationManageService.save(jgUseRegistrationManage);
    }

    private String buildRecordContent(JgVehicleInformation obj) {
        //张三办理了【单位变更】 ，单号【DWBG202407050001】，办理日期2024-07-05
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        return obj.getRecUserName() + "办理了【" + BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName() + "】，" +
                "单号【" + obj.getApplyNo() + "】，申请日期" + simpleDateFormat.format(obj.getRecDate());
    }

    public void handleErrorVehicleForm(String applyNo) {
        LambdaQueryWrapper<JgVehicleInformation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JgVehicleInformation::getApplyNo, applyNo);
        JgVehicleInformation jgVehicleInformation = this.baseMapper.selectOne(queryWrapper);

        if (jgVehicleInformation != null) {
            String lockKey = CommonServiceImpl.buildJgExecuteLockKey(jgVehicleInformation.getInstanceId());
            RLock lock = redissonClient.getLock(lockKey);
            try {
                boolean isLocked = lock.tryLock(0, 180, TimeUnit.SECONDS);
                // 解决并发问题：多个人同时操作一个流程（并发执行通过、驳回、撤回）
                if (!isLocked) {
                    throw new BadRequest("当前流程已经被执行！请重新打开页面查看并执行！");
                }
                // 流程执行时，状态及权限校验
                ProcessTaskDTO complete = workFlowFeignService.handleErrorForm(jgVehicleInformation.getInstanceId(), jgVehicleInformation.getReceiveCompanyCode()).getResult();
                ArrayList<ProcessTaskDTO> processTaskDTOS = new ArrayList<>();
                processTaskDTOS.add(complete);
                List<WorkflowResultDto> resultDto = commonService.buildWorkFlowInfo(processTaskDTOS);
                if (!ObjectUtils.isEmpty(resultDto) && !ObjectUtils.isEmpty(resultDto.get(0))) {
                    WorkflowResultDto workflowResultDto = resultDto.get(0);
                    String role = workflowResultDto.getNextExecutorRoleIds();
                    String taskCode = FlowStatusEnum.TO_BE_FINISHED.getName();
                    if (!ObjectUtils.isEmpty(workflowResultDto.getNextTaskCode())) {
                        taskCode = workflowResultDto.getNextTaskCode();
                    }
                    jgVehicleInformation.setNextTaskId(workflowResultDto.getNextTaskId());
                    jgVehicleInformation.setNextExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                    jgVehicleInformation.setNextExecuteIds(role);
                    jgVehicleInformation.setInstanceStatus(
                            Optional.ofNullable(jgVehicleInformation.getInstanceStatus())
                                    .map(status -> String.join(",", status, role))
                                    .orElse(role)
                    );
                    jgVehicleInformation.setStatus(Objects.requireNonNull(WorkFlowStatusEnum.getMessage(taskCode)).getPass());
                    jgVehicleInformation.setPromoter(workflowResultDto.getStartUserId());
                    // 更新代办状态
                    HashMap<String, Object> params = new HashMap<>();
                    params.put("relationId", jgVehicleInformation.getInstanceId());
                    params.put("flowStatus", commonService.getDictionaryCodeByName(jgVehicleInformation.getStatus()));
                    params.put("flowStatusLabel", jgVehicleInformation.getStatus());
                    params.put("taskStatus", commonService.getDictionaryCodeByName(jgVehicleInformation.getStatus()));
                    params.put("taskStatusLabel", jgVehicleInformation.getStatus());
                    TaskV2Model taskV2Model = commonService.updateTaskModel(params);
                    // 创建新的代办
                    if (!ObjectUtils.isEmpty(taskV2Model)) {
                        TaskModelDto taskModelDto = new TaskModelDto();
                        BeanUtils.copyProperties(taskV2Model, taskModelDto);
                        TaskMessageDto taskMessageDto = new TaskMessageDto();
                        BeanUtil.copyProperties(jgVehicleInformation, taskMessageDto);
                        taskModelDto.setModel(taskMessageDto);
                        taskModelDto.setTaskName(workflowResultDto.getNextTaskName());
                        taskModelDto.setStartUserId(workflowResultDto.getExecutorId());
                        taskModelDto.setExecuteUserIds(workflowResultDto.getNextExecutorUserIds());
                        taskModelDto.setTaskStatusLabel(FlowStatusEnum.TO_BE_PROCESSED.getName());
                        taskModelDto.setNextExecuteUser(workflowResultDto.getNextExecutorRoleIds());
                        taskModelDto.setFlowCode(workflowResultDto.getNextTaskId());
                        commonService.buildTaskModel(Collections.singletonList(taskModelDto));
                    } else {
                        workflowResultDto.setInstanceId(jgVehicleInformation.getInstanceId());
                        buildTask(jgVehicleInformation, workflowResultDto);
                    }
                }
                this.getBaseMapper().updateById(jgVehicleInformation);
                commonService.saveExecuteFlowData2Redis(jgVehicleInformation.getInstanceId(), this.buildInstanceRuntimeData(jgVehicleInformation));
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }
    }

    /**
     * 车用气瓶保存历史数据
     *
     * @param map map
     * @return list
     */
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public List<JgVehicleInformation> saveOrUpdateHisData(JSONObject map) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())) + "", ReginParams.class);
        JgVehicleInformationDto vehicleInfoDto = JSON.parseObject(JSON.toJSONString(map), JgVehicleInformationDto.class);
        List<Map<String, Object>> equipmentLists = (List<Map<String, Object>>) map.get("equipmentLists");
        if (CollectionUtils.isEmpty(equipmentLists) ||
                equipmentLists.stream().map(v -> (String) v.get("chargingMedium")).distinct().count() != 1) {
            throw new BadRequest(CollectionUtils.isEmpty(equipmentLists) ? "请选择设备信息!" : "请选择相同充装介质设备！");
        }

        List<IdxBizJgInspectionDetectionInfo> inspectionDetectionInfoList = idxBizJgInspectionDetectionInfoService.checkInspectionInfo(
                equipmentLists.stream()
                        .map(v -> (String) v.get("record"))
                        .collect(Collectors.toList())
        );

        if (inspectionDetectionInfoList.stream().anyMatch(info ->
                ObjectUtils.isEmpty(info) || ObjectUtils.isEmpty(info.getInspectType()) ||
                        ObjectUtils.isEmpty(info.getInspectConclusion()) || ObjectUtils.isEmpty(info.getInspectOrgCode()))) {
            throw new BadRequest("请补充设备检验检测信息后提交！");
        }

        vehicleInfoDto.setNextInspectionDate(inspectionDetectionInfoList.stream()
                .map(IdxBizJgInspectionDetectionInfo::getNextInspectDate)
                .filter(Objects::nonNull)
                .min(Date::compareTo)
                .orElse(null));

        CompanyBo company = reginParams.getCompany();
        vehicleInfoDto.setCreateDate(new Date());
        vehicleInfoDto.setPromoter(reginParams.getUserModel().getUserId());

        // 车牌号码 字段的唯一性校验
        LambdaQueryWrapper<JgVehicleInformation> vehicleInfoWrapper = new LambdaQueryWrapper<JgVehicleInformation>()
                .eq(JgVehicleInformation::getCarNumber, vehicleInfoDto.getCarNumber())
                .eq(JgVehicleInformation::getIsDelete, false)
                .ne(JgVehicleInformation::getStatus, "已作废")
                .ne(JgVehicleInformation::getStatus, "使用单位待提交")
                .ne(!ValidationUtil.isEmpty(vehicleInfoDto.getSequenceNbr()), JgVehicleInformation::getSequenceNbr, vehicleInfoDto.getSequenceNbr());
        Integer count = this.baseMapper.selectCount(vehicleInfoWrapper);
        if (count > 0) {
            throw new LocalBadRequest("车牌号码已存在，请重新输入！");
        }

        // 【A109】 车用气瓶登记业务 车辆VIN码 校验唯一性
        LambdaQueryWrapper<JgVehicleInformation> informationLambdaQueryWrapper = new LambdaQueryWrapper<JgVehicleInformation>()
                .eq(JgVehicleInformation::getIdentificationCode, vehicleInfoDto.getIdentificationCode())
                .eq(JgVehicleInformation::getIsDelete, false)
                .ne(JgVehicleInformation::getStatus, "已作废")
                .ne(JgVehicleInformation::getStatus, "使用单位待提交")
                .ne(!ValidationUtil.isEmpty(vehicleInfoDto.getSequenceNbr()), JgVehicleInformation::getSequenceNbr, vehicleInfoDto.getSequenceNbr());
        Integer identificationCodeCount = this.baseMapper.selectCount(informationLambdaQueryWrapper);
        if (identificationCodeCount > 0) {
            throw new BadRequest("车辆VIN码已存在，请重新输入！");
        }

        // 使用单位信息
        if ("个人主体".equals(company.getCompanyType())) {
            vehicleInfoDto.setUseUnitName(company.getCompanyName().split("_")[1]);
            vehicleInfoDto.setUseUnitCreditCode(company.getCompanyCode().split("_")[1]);
        } else {
            vehicleInfoDto.setUseUnitName(company.getCompanyName());
            vehicleInfoDto.setUseUnitCreditCode(company.getCompanyCode());
        }

        // 接收单位信息
        if (!StringUtils.isEmpty(vehicleInfoDto.getReceiveOrgCode())) {
            String[] splitReceiveOrgCode = vehicleInfoDto.getReceiveOrgCode().split("_");
            CompanyModel result = Privilege.companyClient.queryByCompanyCode(splitReceiveOrgCode[0]).getResult();
            vehicleInfoDto.setReceiveOrgCode(splitReceiveOrgCode[0]);
            vehicleInfoDto.setReceiveOrgName(splitReceiveOrgCode[1]);
            vehicleInfoDto.setReceiveCompanyCode(result.getCompanyCode());
        }
        //检验机构信息
        if (!StringUtils.isEmpty(vehicleInfoDto.getInspectUnitCreditCode())) {
            String[] splitInspectUnitCreditCode = vehicleInfoDto.getInspectUnitCreditCode().split("_");
            vehicleInfoDto.setInspectUnitCreditCode(splitInspectUnitCreditCode[0]);
            vehicleInfoDto.setInspectUnitName(splitInspectUnitCreditCode[1]);
        }
        //安装单位信息
        if (!StringUtils.isEmpty(vehicleInfoDto.getInstallUnitCode())) {
            String[] splitInstallUnitCode = vehicleInfoDto.getInstallUnitCode().split("_");
            vehicleInfoDto.setInstallUnitCode(splitInstallUnitCode[0]);
            vehicleInfoDto.setInstallUnitName(splitInstallUnitCode[1]);
        }
        //属地监管部门
        if (!StringUtils.isEmpty(vehicleInfoDto.getOrgBranchCode())) {
            String[] splitOrgBranchCode = vehicleInfoDto.getOrgBranchCode().split("_");
            vehicleInfoDto.setOrgBranchCode(splitOrgBranchCode[0]);
            vehicleInfoDto.setOrgBranchName(splitOrgBranchCode[1]);
        }

        // 安全管理员
        Optional.ofNullable(map.getString("safetyManagerId"))
                .filter(manager -> manager.contains("_"))
                .map(manager -> manager.split("_"))
                .ifPresent(data -> {
                    vehicleInfoDto.setSafetyManagerId(data[0]);
                    vehicleInfoDto.setSafetyManagerName(data[1]);
                });

        // 产权单位信息
        if (!StringUtils.isEmpty(vehicleInfoDto.getEstateUnitName())) {
            String[] data = String.valueOf(map.getString("estateUnitName")).split("_");
            vehicleInfoDto.setEstateUnitCreditCode(data[0]);
            vehicleInfoDto.setEstateUnitName(data[1]);
        }

        // 其他附件
        if (!ObjectUtils.isEmpty(map.get("otherAccessories"))) {
            vehicleInfoDto.setOtherAccessories(JSONObject.toJSONString(map.get("otherAccessories")));
        }

        JgVehicleInformation vehicleInformation = new JgVehicleInformation();
        BeanUtils.copyProperties(vehicleInfoDto, vehicleInformation);
        vehicleInformation.setCreateUserId(reginParams.getUserModel().getUserId());
        vehicleInformation.setRegDate(new Date());
        vehicleInformation.setCreateUserName(reginParams.getUserModel().getRealName());
        vehicleInformation.setGasNum(equipmentLists.size());
        vehicleInformation.setVolume(String.valueOf(equipmentLists.stream()
                .mapToDouble(x -> Double.parseDouble(String.valueOf(x.get("singleBottleVolume"))))
                .sum()));
        vehicleInformation.setFillingMedium(equipmentLists.get(0).get("chargingMedium") + "");
        vehicleInformation.setAuditPassDate(new Date());

        // 登记证记录表主键
        Long changeRecordId = sequence.nextId();
        //新增
        if (StringUtils.isEmpty(vehicleInfoDto.getSequenceNbr())) {
            ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.SYDJ.getCode(), 1);
            if (!ObjectUtils.isEmpty(listResponseModel) && listResponseModel.getStatus() != HttpStatus.OK.value()) {
                log.error("车用气瓶使用登记申请单单号获取失败！");
                throw new BadRequest("车用气瓶使用登记申请单单号获取失败！");
            }
            String applyNo = listResponseModel.getResult().get(0);
            vehicleInformation.setApplyNo(applyNo);
            vehicleInformation.setStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
            vehicleInformation.setRegType("1");//历史登记
            this.save(vehicleInformation);

            // 取第一条设备的注册消息--用来获取这一批设备的设备种类/类别/品种
            LambdaQueryWrapper<IdxBizJgRegisterInfo> lambdaReg = new QueryWrapper<IdxBizJgRegisterInfo>().lambda();
            lambdaReg.eq(IdxBizJgRegisterInfo::getRecord, String.valueOf(equipmentLists.get(0).get("record")));
            IdxBizJgRegisterInfo registerInfo = idxBizJgRegisterInfoMapper.selectOne(lambdaReg);
            // 生成证书管理表记录
            generateRegistrationManage(vehicleInformation, registerInfo);
            // 生成一条tzs_jg_certificate_change_record记录
            generateCertificateChangeRecord(vehicleInformation, registerInfo, changeRecordId, null);
        } else {
            // 删除以前设备关联关系
            this.getBaseMapper().updateById(vehicleInformation);
            LambdaQueryWrapper<JgVehicleInformationEq> lambda = new QueryWrapper<JgVehicleInformationEq>().lambda();
            lambda.eq(JgVehicleInformationEq::getVehicleId, vehicleInformation.getSequenceNbr());
            jgVehicleInformationEqService.getBaseMapper().delete(lambda);
            this.getBaseMapper().updateById(vehicleInformation);
            JgUseRegistrationManage useRegistrationCode = jgUseRegistrationManageService.lambdaQuery()
                    .eq(JgUseRegistrationManage::getUseRegistrationCode, vehicleInformation.getUseRegistrationCode())
                    .one();
            if (useRegistrationCode != null) {
                useRegistrationCode.setCarNumber(vehicleInformation.getCarNumber());
                jgUseRegistrationManageService.updateById(useRegistrationCode);
            }
        }

        // 更新关联气瓶信息
        if (!CollectionUtils.isEmpty(equipmentLists)) {
            List<JgVehicleInformationEq> equipList = new ArrayList<>();
            equipmentLists.forEach(x -> {
                JgVehicleInformationEq equip = new JgVehicleInformationEq();
                equip.setEquId(String.valueOf(x.get("record")));
                equip.setVehicleId(vehicleInformation.getSequenceNbr() + "");
                equipList.add(equip);
                jgResumeInfoService.createWithModel(JgResumeInfoDto.builder()
                        .applyNo(vehicleInformation.getApplyNo())
                        .businessType(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName())
                        .businessId(vehicleInformation.getSequenceNbr() + "")
                        .equId(String.valueOf(x.get("record")))
                        .approvalUnit(vehicleInformation.getReceiveOrgName())
                        .approvalUnitCode(vehicleInformation.getReceiveOrgCode())
                        .status("正常")
                        .build());

                // 查询注册信息
                LambdaQueryWrapper<IdxBizJgRegisterInfo> queryRegisterWrapper = new QueryWrapper<IdxBizJgRegisterInfo>().lambda();
                queryRegisterWrapper.eq(IdxBizJgRegisterInfo::getRecord, String.valueOf(x.get("record")));
                IdxBizJgRegisterInfo registerInfo = idxBizJgRegisterInfoMapper.selectOne(queryRegisterWrapper);
                registerInfo.setUseOrgCode(vehicleInformation.getUseRegistrationCode());

                // 更新注册登记信息表
                LambdaUpdateWrapper<IdxBizJgRegisterInfo> updateRegisterWrapper = new UpdateWrapper<IdxBizJgRegisterInfo>().lambda();
                // 新增页面选择无设备代码后，在审批通过后自动生成设备代码
                this.generateEquCode(updateRegisterWrapper, registerInfo, vehicleInformation.getReceiveCompanyCode());
                updateRegisterWrapper.eq(IdxBizJgRegisterInfo::getRecord, registerInfo.getRecord());
                updateRegisterWrapper.set(true, IdxBizJgRegisterInfo::getUseOrgCode, vehicleInformation.getUseRegistrationCode());
                updateRegisterWrapper.set(IdxBizJgRegisterInfo::getRegisterState, this.getRegCode());
                idxBizJgRegisterInfoService.update(updateRegisterWrapper);

                // 查询其他信息
                LambdaQueryWrapper<IdxBizJgOtherInfo> otherInfoWrapper = new QueryWrapper<IdxBizJgOtherInfo>().lambda();
                otherInfoWrapper.eq(IdxBizJgOtherInfo::getRecord, String.valueOf(x.get("record")));
                IdxBizJgOtherInfo otherInfo = otherInfoMapper.selectOne(otherInfoWrapper);

                // 更新设备信息
                this.updateEquipInfo(vehicleInformation, registerInfo, otherInfo, String.valueOf(x.get("record")));
                // 更新es
                this.updateEquipEsData(vehicleInformation, otherInfo, registerInfo, String.valueOf(x.get("record")));
                // 查询设备制造信息
                LambdaQueryWrapper<IdxBizJgFactoryInfo> factoryInfoWrapper = new LambdaQueryWrapper<>();
                factoryInfoWrapper.eq(IdxBizJgFactoryInfo::getRecord, String.valueOf(x.get("record")));
                IdxBizJgFactoryInfo idxBizJgFactoryInfo = idxBizJgFactoryInfoMapper.selectOne(factoryInfoWrapper);

                // 生成tzs_jg_certificate_change_record_eq记录
                JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq();
                changeRecordEq.setChangeRecordId(String.valueOf(changeRecordId));//登记证记录主键
                changeRecordEq.setEquId(registerInfo.getRecord());//设备主键
                changeRecordEq.setProductCode(idxBizJgFactoryInfo.getFactoryNum());//产品编号
                certificateChangeRecordEqService.save(changeRecordEq);

            });

            // 保存关联设备信息
            jgVehicleInformationEqService.saveBatch(equipList);
        }

        return Collections.singletonList(vehicleInformation);
    }

    /**
     * 系统类型的code 自动生成设备代码
     *
     * @param lambda             lambda
     * @param registerInfo       注册信息
     * @param receiveCompanyCode 接收机构行政区划代码
     */
    public void generateEquCode(LambdaUpdateWrapper<IdxBizJgRegisterInfo> lambda, IdxBizJgRegisterInfo registerInfo, String receiveCompanyCode) {
        // 新增设备时选择无设备代码且在设备代码为空【未做安装告知（使用登记、安装告知会生成设备代码）】
        if (EquCodeTypeEnum.SYSTEM_GENERATED.getCode().equals(registerInfo.getEquCodeType()) && StringUtils.isEmpty(registerInfo.getEquCode())) {
            // 更新注册信息表的设备代码字段
            String equCode = jgUseRegistrationService.getEquCode(registerInfo, receiveCompanyCode);
            registerInfo.setEquCode(equCode);
            lambda.set(true, IdxBizJgRegisterInfo::getEquCode, equCode);
        }
    }

    private void updateEquipInfo(JgVehicleInformation jgVehicleInformation, IdxBizJgRegisterInfo registerInfo, IdxBizJgOtherInfo otherInfo, String equId) {
        String useOrgCode = jgVehicleInformation.getUseRegistrationCode();
        IdxBizJgUseInfo useInfo = new IdxBizJgUseInfo();
        // 判断是否为西咸
        String isXiXian = XI_XIAN.getCode().equals(jgVehicleInformation.getVehicleApanage()) ? "1" : "0";
        jgVehicleInformation.setIsXixian(isXiXian);
        useInfo.setIsNotXiXian(isXiXian);
        useInfo.setProvince("610000");
        useInfo.setIsIntoManagement(Boolean.TRUE);
        useInfo.setAddress(jgVehicleInformation.getUseUnitAddress());
        LambdaQueryWrapper<IdxBizJgUseInfo> lambda = new QueryWrapper<IdxBizJgUseInfo>().lambda();
        lambda.eq(IdxBizJgUseInfo::getRecord, equId);

        // 修改设备使用状态为在用
        useInfo.setEquState(String.valueOf(EquimentEnum.ZAIYONG.getCode()));
        // 更新使用信息
        useInfoMapper.update(useInfo, lambda);

        // 更新设备监管部门
        IdxBizJgSupervisionInfo idxBizJgSupervisionInfo = new IdxBizJgSupervisionInfo();
        HashMap<String, Object> parentMessage = (HashMap<String, Object>) Privilege.companyClient.queryByOrgcode(jgVehicleInformation.getOrgBranchCode()).getResult();
        // 目前平台返回key为compnay(存在拼写错误)
        CompanyModel parentModel = JSON.parseObject(JSON.toJSONString(parentMessage.get("compnay")), CompanyModel.class);
        idxBizJgSupervisionInfo.setOrgBranchCode(jgVehicleInformation.getOrgBranchCode());
        idxBizJgSupervisionInfo.setOrgBranchName(jgVehicleInformation.getOrgBranchName());
        idxBizJgSupervisionInfo.setCompanyOrgBranchCode(parentModel.getCompanyCode());
        LambdaQueryWrapper<IdxBizJgSupervisionInfo> eq = new QueryWrapper<IdxBizJgSupervisionInfo>().lambda().eq(IdxBizJgSupervisionInfo::getRecord, equId);
        idxBizJgSupervisionInfoMapper.update(idxBizJgSupervisionInfo, eq);
        // 更新设备使用登记证
        idxBizJgRegisterInfoMapper.updateUseOrgCodeByEquip(equId, useOrgCode);
        // 车用气瓶生成监管码
        this.createCode(jgVehicleInformation, registerInfo, otherInfo);
    }

    private void updateEquipEsData(JgVehicleInformation jgVehicleInformation, IdxBizJgOtherInfo otherInfo, IdxBizJgRegisterInfo registerInfo, String equId) {
        // 更新es
        HashMap<String, Map<String, Object>> objMap = new HashMap<>();
        HashMap<String, Object> param = new HashMap<>();
        param.put("SUPERVISORY_CODE", otherInfo.getSupervisoryCode());
        param.put("USE_UNIT_CREDIT_CODE", jgVehicleInformation.getUseUnitCreditCode());
        param.put("USE_UNIT_NAME", jgVehicleInformation.getUseUnitName());
        //param.put("ADDRESS", otherInfo.get);
        param.put("USE_PLACE", jgVehicleInformation.getUseUnitAddress());
        param.put("STATUS", "已认领");
        param.put("EQU_STATE", 1);
        param.put("IS_INTO_MANAGEMENT", true);
        param.put("ORG_BRANCH_CODE", jgVehicleInformation.getOrgBranchCode());
        param.put("ORG_BRANCH_NAME", jgVehicleInformation.getOrgBranchName());
        param.put("EQU_CODE", registerInfo.getEquCode());
        param.put("USE_ORG_CODE", jgVehicleInformation.getUseRegistrationCode());
        objMap.put(equId, param);
        tzsServiceFeignClient.commonUpdateEsDataByIds(objMap);
    }
}