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.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.jg.api.dto.*;
import com.yeejoin.amos.boot.module.jg.api.entity.*;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.VehicleApanageEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.WorkFlowStatusEnum;
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.biz.config.LocalBadRequest;
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.ymt.api.entity.*;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquimentEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.*;
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.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 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.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.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseModel;
import javax.servlet.http.HttpServletResponse;
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.*;
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";
    @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 JgVehicleInformationEqMapper jgVehicleInformationEqMapper;
    @Autowired
    private IdxBizJgUseInfoServiceImpl idxBizJgUseInfoService;
    @Autowired
    private IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoService;
    @Autowired
    private IdxBizJgRegisterInfoMapper idxBizJgRegisterInfoMapper;
    @Autowired
    private IdxBizJgUseInfoMapper useInfoMapper;
    @Autowired
    private IdxBizJgSupervisionInfoMapper idxBizJgSupervisionInfoMapper;
    @Autowired
    private InspectionDetectionInfoMapper inspectionDetectionInfoMapper;
    @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;

    /**
     * 新增（提交）车用气瓶
     *
     * @param map map
     * @return list
     */
    @Transactional(rollbackFor = Exception.class)
    public List<JgVehicleInformation> save(String submit, 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)) {
            throw new BadRequest("请选择设备");
        }

        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()) ||
                        ObjectUtils.isEmpty(info.getInspectOrgName()))) {
            throw new BadRequest("请补充设备检验检测信息后提交！");
        }

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

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

        // 使用单位信息
        vehicleInfoDto.setUseUnitName(company.getCompanyName());
        vehicleInfoDto.setUseUnitCreditCode(company.getCompanyCode());

        // 接收单位信息
        if (!StringUtils.isEmpty(vehicleInfoDto.getReceiveOrgCode())) {
            List<LinkedHashMap> tree = commonService.getCreatTree();
            String[] splitReceiveOrgCode = vehicleInfoDto.getReceiveOrgCode().split("_");
            String orgCode = this.recursiveMatching(tree, splitReceiveOrgCode[0]);
            vehicleInfoDto.setReceiveOrgCode(orgCode);
            vehicleInfoDto.setReceiveCompanyCode(splitReceiveOrgCode[0]);
            vehicleInfoDto.setReceiveOrgName(splitReceiveOrgCode[1]);
        }
        //检验机构信息
        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]);
        }

        JgVehicleInformation vehicleInformation = new JgVehicleInformation();
        BeanUtils.copyProperties(vehicleInfoDto, vehicleInformation);
        vehicleInformation.setCreateUserId(reginParams.getUserModel().getUserId());
        vehicleInformation.setCreateUserName(reginParams.getUserModel().getRealName());
        vehicleInformation.setGasNum(equipmentLists.size());

        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("SEQUENCE_NBR")));
                equip.setVehicleId(vehicleInformation.getSequenceNbr() + "");
                equipList.add(equip);
            });
            // 保存关联设备信息
            jgVehicleInformationEqService.saveBatch(equipList);
        }
        // 判断当前是否为提交
        if (SUBMIT_TYPE_FLOW.equals(submit)) {
            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);
                }
            } else {
                // 执行流程
                flowExecute(vehicleInformation.getSequenceNbr(), vehicleInformation.getInstanceId(), "0", "", String.valueOf(map.get("nextTaskId")));
            }
        } 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);
    }

    public void updateHistory(JSONObject map, String equipId, String currentDocumentId, String supervisoryCode) {
        JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
        LambdaQueryWrapper<JgRegistrationHistory> lambda = new QueryWrapper<JgRegistrationHistory>().lambda();
        // lambda.eq(JgRegistrationHistory::getEquId, equipId);
        lambda.eq(JgRegistrationHistory::getCurrentDocumentId, currentDocumentId);
        lambda.eq(JgRegistrationHistory::getRegistrationClass, "车用气瓶登记");
        Integer integer = jgRegistrationHistoryService.getBaseMapper().selectCount(lambda);
        if (integer > 0) {
            jgRegistrationHistory.setChangeData(JSON.toJSONString(map));
            jgRegistrationHistoryService.update(jgRegistrationHistory, lambda);
        } else {
            jgRegistrationHistory.setChangeData(JSON.toJSONString(map));
            jgRegistrationHistory.setStatus("new");
            jgRegistrationHistory.setRegistrationClass("车用气瓶登记");
            jgRegistrationHistory.setSupervisoryCode(supervisoryCode);
            jgRegistrationHistory.setEquId(equipId);
            jgRegistrationHistory.setCurrentDocumentId(currentDocumentId);
            jgRegistrationHistoryService.save(jgRegistrationHistory);
        }

    }

    private void createTaskModel(JgVehicleInformation vehicle, String taskName, String submitType, String nextUserIds) {
        if ("1".equals(submitType)) {
            TaskModelDto taskModelDto = new TaskModelDto();
            taskModelDto.setFlowCreateDate(vehicle.getRegDate());
            taskModelDto.setTaskName(taskName);
            taskModelDto.setTaskCode(vehicle.getApplyNo());
            taskModelDto.setTaskContent(this.buildTaskContent(vehicle));
            taskModelDto.setTaskDesc("");
            taskModelDto.setTaskType(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getCode());
            taskModelDto.setTaskTypeLabel(BusinessTypeEnum.JG_VEHICLE_GAS_APPLICATION.getName());
            taskModelDto.setRelationId(vehicle.getInstanceId());
            taskModelDto.setExecuteUserIds(nextUserIds);
            FlowStatusEnum flowStatusEnum = this.getTaskStatus(submitType);
            taskModelDto.setTaskStatus(flowStatusEnum.getCode());
            taskModelDto.setTaskStatusLabel(flowStatusEnum.getName());
            taskModelDto.setFlowStatus(this.getTaskStatusByName(vehicle.getStatus()));
            taskModelDto.setFlowStatusLabel(vehicle.getStatus());
            taskModelDto.setStartUserId(vehicle.getCreateUserId());
            taskModelDto.setStartUser(vehicle.getRecUserName());
            taskModelDto.setFlowCode(vehicle.getNextTaskId());
            taskModelDto.setStartUserCompanyName(vehicle.getUseUnitName());
            taskModelDto.setNextExecuteUser(vehicle.getNextExecuteIds());
            taskModelDto.setStartDate(vehicle.getCreateDate());
            TaskMessageDto taskMessageDto = new TaskMessageDto();
            BeanUtil.copyProperties(vehicle, taskMessageDto);
            taskModelDto.setModel(taskMessageDto);
            commonService.buildTaskModel(Collections.singletonList(taskModelDto));

            // redis流程实时数据更新
            commonService.saveExecuteFlowData2Redis(vehicle.getInstanceId(), this.buildInstanceRuntimeData(vehicle));
        }
    }

    /**
     * 摘要构建
     *
     * @param dto 业务
     * @return 摘要
     */
    private String buildTaskContent(JgVehicleInformation dto) {
        List<Map<String, Object>> list = this.baseMapper.selectEquipList(dto.getSequenceNbr());
        String supervisoryCode = "";
        String equList = "";
        if (!CollectionUtils.isEmpty(list)) {
            Map<String, Object> map = list.get(0);
            if (map.containsKey("EQU_LIST")) {
                equList = map.get("EQU_LIST") + "";
            }
            if (map.containsKey("SUPERVISORY_CODE")) {
                supervisoryCode = map.get("SUPERVISORY_CODE") + "";
            }
        }
        supervisoryCode = StringUtils.isEmpty(supervisoryCode) ? "无" : supervisoryCode;
        String format = String.format("来自%s【%s】等的业务办理，【申请单号：%s】等", equList, supervisoryCode, dto.getApplyNo());
        return format;
    }

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

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

    /**
     * 撤回操作
     *
     * @param instanceId  instanceId
     * @param _nextTaskId nextTaskId
     */
    @Transactional(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
            commonService.rollbackTask(instanceId, jsonObject);

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

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

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

        List<Map<String, Object>> list = this.baseMapper.selectEquipList(sequenceNbr);
        if (!ObjectUtils.isEmpty(list)) {
            vo.setEquipmentLists(list);
        }
        return vo;
    }

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

            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);
            }
        } 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) {
        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.deleteTaskModel(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 = generateVehicleUseRegistrationCode(receiveCompanyCode);
            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);
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject mapData = jsonArray.getJSONObject(i);

                // 查询注册信息
                LambdaQueryWrapper<IdxBizJgRegisterInfo> queryRegisterWrapper = new QueryWrapper<IdxBizJgRegisterInfo>().lambda();
                queryRegisterWrapper.eq(IdxBizJgRegisterInfo::getRecord, String.valueOf(mapData.get("record")));
                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, String.valueOf(mapData.get("record")));
                IdxBizJgOtherInfo otherInfo = otherInfoMapper.selectOne(otherInfoWrapper);

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

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

            // 更新代办状态
            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);
            commonService.updateTaskModel(params);
        }
        commonService.saveExecuteFlowData2Redis(jgVehicleInformation.getInstanceId(), this.buildInstanceRuntimeData(jgVehicleInformation));
        this.getBaseMapper().updateById(jgVehicleInformation);
    }

    public 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("ORG_BRANCH_CODE", jgVehicleInformation.getOrgBranchCode());
        param.put("ORG_BRANCH_NAME", jgVehicleInformation.getOrgBranchName());
        param.put("USE_ORG_CODE", jgVehicleInformation.getUseRegistrationCode());
        objMap.put((String) dataMap.get("record"), param);
        tzsServiceFeignClient.commonUpdateEsDataByIds(objMap);
    }

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

    /**
     * 批量删除
     *
     * @param ids ids
     */
    public void deleteBatch(List<Long> ids) {
        JgVehicleInformation jgVehicleInformation = new JgVehicleInformation();
        jgVehicleInformation.setIsDelete(true);
        LambdaQueryWrapper<JgVehicleInformation> lambda = new QueryWrapper<JgVehicleInformation>().lambda();
        lambda.in(JgVehicleInformation::getSequenceNbr, ids);
        // 删除暂存的待办
        ids.forEach(id -> commonService.deleteTaskModel(String.valueOf(id)));
        this.update(jgVehicleInformation, lambda);
    }

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

    public 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.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("_");
            List<LinkedHashMap> tree = commonService.getCreatTree();
            String orgCode = this.recursiveMatching(tree, data[0]);
            idxBizJgSupervisionInfo.setOrgBranchCode(orgCode);
            idxBizJgSupervisionInfo.setOrgBranchName(data[1]);
            idxBizJgSupervisionInfo.setCompanyOrgBranchCode(data[0]);
            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);
        }
    }

    /**
     * 递归属地监管部门树匹配监管部门
     *
     * @param tree          监管树
     * @param orgBranchCode 监管部门companyCode
     * @return 监管部门orgCode
     */
    public String recursiveMatching(List<LinkedHashMap> tree, String orgBranchCode) {
        if (tree != null) {
            for (LinkedHashMap map : tree) {
                if (orgBranchCode.equals(map.get("companyCode"))) {
                    return (String) map.get("orgCode");
                }
                if (map.containsKey("children") && map.get("children") instanceof List) {
                    String result = recursiveMatching((List<LinkedHashMap>) map.get("children"), orgBranchCode);
                    if (!"".equals(result)) {
                        return result;
                    }
                }
            }
        }
        return "";
    }

    /**
     * 获取类型为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) {
        StringBuilder useRegistration = new StringBuilder("容3T");
        if (!ObjectUtils.isEmpty(receiveCompanyCode)) {
            ResponseModel<String> stringResponseModel = tzsServiceFeignClient.useRegistrationCode(useRegistration.append(VehicleApanageEnum.of(receiveCompanyCode)) + "");
            return stringResponseModel.getResult();
        }
        return null;
    }

    /**
     * 打印车用气瓶登记证
     *
     * @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("使用登记证导出失败,请稍后重试或检查数据完整性!");
        }

        IdxBizJgRegisterInfo registerInfo = idxBizJgRegisterInfoService.getOne(new QueryWrapper<IdxBizJgRegisterInfo>().eq("RECORD", vehicleInformationEqList.get(0).getEquId()));
        if (registerInfo != null) {
            populateEquipmentInformation(registerInfo, exportParamsMap);
        }

        IdxBizJgUseInfo useInfo = idxBizJgUseInfoService.getOneData(vehicleInformationEqList.get(0).getEquId());
        if (useInfo != null && useInfo.getUseInnerCode() != null) {
            exportParamsMap.put("useInnerCode", useInfo.getUseInnerCode());
        }

        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)
                    .collect(Collectors.joining(", ")));
        }
        exportParamsMap.put("applyNo", vehicleInformation.getApplyNo());
        this.generateReport(vehicleInformation, printType, exportParamsMap, response);
    }

    private void generateReport(JgVehicleInformation vehicleInformation, String printType, Map<String, Object> exportParamsMap, HttpServletResponse response) {
        switch (printType) {
            case "0":
                commonService.generateCertificateReport(exportParamsMap, response);
                break;
            case "1":
                commonService.generatePdfPrint(exportParamsMap, response);
                break;
            case "2":
                commonService.useFlagGenerate(buildUseFlagParam(vehicleInformation, exportParamsMap), response);
                break;
            case "3":
                commonService.fightUseFlagGenerate(buildUseFlagParam(vehicleInformation, exportParamsMap), response);
                break;
            default:
                throw new BadRequest("Invalid print type");
        }
    }

    private void populateEquipmentInformation(IdxBizJgRegisterInfo registerInfo, Map<String, Object> exportParamsMap) {
        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);
        List<EquipmentCategory> categoryList2 = commonService.getEquipmentCategoryList(equDefine, null);
        if (notEmptyAndHasName(categoryList0)) {
            exportParamsMap.put("equList", categoryList0.get(0).getName());
        }
        if (notEmptyAndHasName(categoryList1)) {
            exportParamsMap.put("equCategory", categoryList1.get(0).getName());
        }
        if (notEmptyAndHasName(categoryList2)) {
            exportParamsMap.put("equDefine", "特种气瓶（车用）");
        }
        if (registerInfo.getEquCode() == null) {
            throw new BadRequest("使用登记证导出失败,设备代码为空!");
        }
        exportParamsMap.put("equCode", registerInfo.getEquCode());
        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(Systemctl.dictionarieClient.value("FILLING_MEDIUM", vehicleInformation.getFillingMedium()).getResult().getDictDataValue());
        useFlagParamDto.setApplyNo(vehicleInformation.getApplyNo());
        useFlagParamDto.setInspectionUnitName(vehicleInformation.getInspectUnitName());
        return useFlagParamDto;
    }
}