package com.ruoyi.project.business.service.impl;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.AsyncUtil;
import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.enums.LanguageEnum;
import com.ruoyi.common.exception.ServiceErrorException;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.importExcel.excel.helper.BasicExcelHelper;
import com.ruoyi.common.importExcel.excel.helper.BasicTableInfoHelper;
import com.ruoyi.common.importExcel.excel.tempInfo.ParaRelatedCaseActionHelper;
import com.ruoyi.common.importExcel.excel.tempInfo.ParaRelatedCaseInfoHelper;
import com.ruoyi.common.importExcel.excel.tempInfo.ParaRelatedCaseLogicHelper;
import com.ruoyi.common.importExcel.utils.ExcelUtils;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.jep.JEPUtils;
import com.ruoyi.framework.redis.RedisCache;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.business.domain.TpCaseElevator;
import com.ruoyi.project.business.domain.TpParaLibrary;
import com.ruoyi.project.business.domain.TpParaRelatedAction;
import com.ruoyi.project.business.domain.TpParaRelatedCase;
import com.ruoyi.project.business.domain.TpParaRelatedLogic;
import com.ruoyi.project.business.domain.TpParabar;
import com.ruoyi.project.business.domain.vo.parabar.RelatedModelVO;
import com.ruoyi.project.business.dto.*;
import com.ruoyi.project.business.enums.ComputedFlagEnum;
import com.ruoyi.project.business.enums.DelFlagEnum;
import com.ruoyi.project.business.enums.DisplayFlagEnum;
import com.ruoyi.project.business.enums.EditableEnum;
import com.ruoyi.project.business.enums.InputTypeEnum;
import com.ruoyi.project.business.enums.JEPFuncEnum;
import com.ruoyi.project.business.enums.JEPLogicEnum;
import com.ruoyi.project.business.enums.JEPSplitEnum;
import com.ruoyi.project.business.enums.LogicEnum;
import com.ruoyi.project.business.enums.OperationEnum;
import com.ruoyi.project.business.enums.OperationFlagEnum;
import com.ruoyi.project.business.enums.RelationshipEnum;
import com.ruoyi.project.business.enums.RunTypeEnum;
import com.ruoyi.project.business.enums.StatusEnum;
import com.ruoyi.project.business.mapper.TpParaRelatedCaseMapper;
import com.ruoyi.project.business.service.ITpCaseElevatorService;
import com.ruoyi.project.business.service.ITpParaLibraryService;
import com.ruoyi.project.business.service.ITpParaRelatedActionService;
import com.ruoyi.project.business.service.ITpParaRelatedCaseService;
import com.ruoyi.project.business.service.ITpParaRelatedLogicService;
import com.ruoyi.project.business.service.ITpParabarService;
import com.ruoyi.project.business.service.quotation.ITqSpecificationService;
import com.ruoyi.project.system.domain.SysDictData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author jubs
 */
@Service
@Slf4j
public class TpParaRelatedCaseServiceImpl extends ServiceImpl<TpParaRelatedCaseMapper, TpParaRelatedCase> implements
    ITpParaRelatedCaseService {

    @Resource
    private ITpCaseElevatorService iTpCaseElevatorService;

    @Resource
    private ITpParaRelatedLogicService iTpParaRelatedLogicService;

    @Resource
    private ITpParaRelatedActionService iTpParaRelatedActionService;

    @Resource
    private ITpParaLibraryService iTpParaLibraryService;

    @Resource
    private ITpParabarService tpParabarService;

    @Resource
    private ITqSpecificationService iTqSpecificationService;

    @Resource
    private ITpParaLibraryService tpParaLibraryService;

    @Resource
    private RedisCache redisCache;

    @PostConstruct
    public void init()
    {
        refreshCache();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int saveOrUpdateDto(TpParaRelatedCaseDto tpParaRelatedCase) {

        if (RunTypeEnum.REAL_TIME.getCode().equals(tpParaRelatedCase.getRunType())) {
            tpParaRelatedCase.setRunIndex(null);
        }
        Integer operationFlag = tpParaRelatedCase.getOperationFlag();
        Date date = new Date();
        // @Date 2024/6/11 8:50 @Author jubs 😀 @description: 校验用例名称唯一
        if (checkNameUnique(tpParaRelatedCase.getCaseName(), tpParaRelatedCase.getId())) {
            throw new ServiceErrorException(MessageUtils.message("relatedCase.notUnique"));
        }

        if (OperationFlagEnum.ADD.getFlag().equals(operationFlag)) {
            if (tpParaRelatedCase.getRelationEnters() == null || tpParaRelatedCase.getRelationEnters().isEmpty()) {
                throw new ServiceErrorException(MessageUtils.message("relatedCase.atLeastModel"));
            }
            if (tpParaRelatedCase.getLogicList() == null || tpParaRelatedCase.getLogicList().isEmpty()) {
                throw new ServiceErrorException(MessageUtils.message("relatedCase.atLeastCase"));
            }
            if (tpParaRelatedCase.getActionList() == null || tpParaRelatedCase.getActionList().isEmpty()) {
                throw new ServiceErrorException(MessageUtils.message("relatedCase.atLeastResult"));
            }
            TpParaRelatedCase basicInfo = new TpParaRelatedCase();
            BeanUtils.copyBeanProp(basicInfo, tpParaRelatedCase);
            basicInfo.setStatus(StatusEnum.ENABLE.getCode());
            basicInfo.setCreateBy(SecurityUtils.getStrUserId());
            basicInfo.setCreateTime(date);
            save(basicInfo);

            tpParaRelatedCase.getRelationEnters().forEach(item -> {
                item.setRelatedCaseId(basicInfo.getId());
                item.setCreateBy(SecurityUtils.getStrUserId());
                item.setCreateTime(date);
            });
            List<TpCaseElevator> caseElevators = tpParaRelatedCase.getRelationEnters().stream().map(
                item -> {
                    TpCaseElevator caseElevator = new TpCaseElevator();
                    BeanUtils.copyBeanProp(caseElevator, item);
                    return caseElevator;
                }
            ).collect(Collectors.toList());

            iTpCaseElevatorService.saveBatch(caseElevators);

            tpParaRelatedCase.getLogicList().forEach(item -> {
                item.setCaseId(basicInfo.getId());
                item.setCreateBy(SecurityUtils.getStrUserId());
                item.setCreateTime(date);
            });
            List<TpParaRelatedLogic> logicList = tpParaRelatedCase.getLogicList().stream().map(item -> {
                TpParaRelatedLogic logic = new TpParaRelatedLogic();
                BeanUtils.copyBeanProp(logic, item);
                return logic;
            }).collect(Collectors.toList());
            iTpParaRelatedLogicService.saveBatch(logicList);

            tpParaRelatedCase.getActionList().forEach(item -> {
                item.setCaseId(basicInfo.getId());
                item.setCreateBy(SecurityUtils.getStrUserId());
                item.setCreateTime(date);
            });
            List<TpParaRelatedAction> actionList = tpParaRelatedCase.getActionList().stream().map(item -> {
                TpParaRelatedAction action = new TpParaRelatedAction();
                BeanUtils.copyBeanProp(action, item);
                return action;
            }).collect(Collectors.toList());

            iTpParaRelatedActionService.saveBatch(actionList);


        } else if (OperationFlagEnum.EDIT.getFlag().equals(operationFlag)) {
            TpParaRelatedCase sqlData = getById(tpParaRelatedCase.getId());
            if (sqlData == null) {
                //数据已被删除
                throw new ServiceErrorException(MessageUtils.message("common.dataDeleted"));
            }
            if (!ValidateUtils.allowUpdate(sqlData.getUpdateTime(), tpParaRelatedCase.getUpdateTime())) {
                throw new ServiceErrorException(MessageUtils.message("common.dataUpdated"));
            }
            BeanUtils.copyBeanProp(sqlData, tpParaRelatedCase);
            sqlData.setUpdateBy(SecurityUtils.getStrUserId());
            sqlData.setUpdateTime(date);
            updateById(sqlData);
            if (Objects.isNull(tpParaRelatedCase.getRunIndex())){
                update(Wrappers.<TpParaRelatedCase>lambdaUpdate().set(TpParaRelatedCase::getRunIndex, null)
                        .eq(TpParaRelatedCase::getId, tpParaRelatedCase.getId()));
            }

            List<Long> logicDeleteIds = tpParaRelatedCase.getLogicDeleteIds();

            List<Long> actionDeleteIds = tpParaRelatedCase.getActionDeleteIds();

            List<Long> relationEnterDeleteIds = tpParaRelatedCase.getDeleteRelationEnterIds();
            List<TpParaRelatedLogic> logicList;
            List<TpParaRelatedAction> actionList;
            List<TpCaseElevator> relationEnters;
            //处理删除部分
            if (logicDeleteIds != null && !logicDeleteIds.isEmpty()) {
                logicList = iTpParaRelatedLogicService.list(
                    Wrappers.<TpParaRelatedLogic>lambdaQuery()
                        .in(TpParaRelatedLogic::getId, logicDeleteIds)
                );
                if (logicList != null && !logicList.isEmpty()) {
                    logicList.forEach(item -> {
                        item.setUpdateBy(SecurityUtils.getStrUserId());
                        item.setUpdateTime(date);
                        item.setDelFlag(DelFlagEnum.DELETED.getValue());
                    });
                    iTpParaRelatedLogicService.updateBatchById(logicList);
                }
            }
            if (actionDeleteIds != null && !actionDeleteIds.isEmpty()) {
                actionList = iTpParaRelatedActionService.list(
                    Wrappers.<TpParaRelatedAction>lambdaQuery()
                        .in(TpParaRelatedAction::getId, actionDeleteIds)
                );
                if (actionList != null && !actionList.isEmpty()) {
                    actionList.forEach(item -> {
                        item.setUpdateBy(SecurityUtils.getStrUserId());
                        item.setUpdateTime(date);
                        item.setDelFlag(DelFlagEnum.DELETED.getValue());
                    });
                    iTpParaRelatedActionService.updateBatchById(actionList);
                }
            }
            if (relationEnterDeleteIds != null && !relationEnterDeleteIds.isEmpty()) {
                relationEnters = iTpCaseElevatorService.list(
                    Wrappers.<TpCaseElevator>lambdaQuery()
                        .in(TpCaseElevator::getId, relationEnterDeleteIds)
                );
                if (relationEnters != null && !relationEnters.isEmpty()) {
                    relationEnters.forEach(item -> {
                        item.setUpdateBy(SecurityUtils.getStrUserId());
                        item.setUpdateTime(date);
                        item.setDelFlag(DelFlagEnum.DELETED.getValue());
                    });
                    iTpCaseElevatorService.updateBatchById(relationEnters);
                }

            }

            //处理修改部分
            List<TpParaRelatedLogic> logicListNeedUpdate = tpParaRelatedCase.getLogicList().stream()
                .filter(item -> OperationFlagEnum.EDIT.getFlag().equals(item.getOperationFlag()))
                .collect(Collectors.toList());
            List<TpParaRelatedAction> actionListNeedUpdate = tpParaRelatedCase.getActionList().stream()
                .filter(item -> OperationFlagEnum.EDIT.getFlag().equals(item.getOperationFlag()))
                .collect(Collectors.toList());
            if (!logicListNeedUpdate.isEmpty()) {
                logicListNeedUpdate.forEach(item -> {
                    item.setUpdateBy(SecurityUtils.getStrUserId());
                    item.setUpdateTime(date);
                });
                iTpParaRelatedLogicService.updateBatchById(logicListNeedUpdate);
            }

            if (!actionListNeedUpdate.isEmpty()) {
                actionListNeedUpdate.forEach(item -> {
                    item.setUpdateBy(SecurityUtils.getStrUserId());
                    item.setUpdateTime(date);
                });
                iTpParaRelatedActionService.updateBatchById(actionListNeedUpdate);
            }

            //处理新增部分
            List<TpParaRelatedLogic> logicListNeedInsert = tpParaRelatedCase.getLogicList().stream()
                .filter(item -> OperationFlagEnum.ADD.getFlag().equals(item.getOperationFlag()))
                .collect(Collectors.toList());

            List<TpParaRelatedAction> actionListNeedInsert = tpParaRelatedCase.getActionList().stream()
                .filter(item -> OperationFlagEnum.ADD.getFlag().equals(item.getOperationFlag()))
                .collect(Collectors.toList());
            List<TpCaseElevator> relationEntersNeedInsert = tpParaRelatedCase.getRelationEnters().stream()
                .filter(item -> OperationFlagEnum.ADD.getFlag().equals(item.getOperationFlag()))
                .collect(Collectors.toList());
            if (!logicListNeedInsert.isEmpty()) {
                logicListNeedInsert.forEach(item -> {
                    item.setCreateBy(SecurityUtils.getStrUserId());
                    item.setCreateTime(date);
                    item.setCaseId(tpParaRelatedCase.getId());
                });
                iTpParaRelatedLogicService.saveBatch(logicListNeedInsert);
            }
            if (!actionListNeedInsert.isEmpty()) {
                actionListNeedInsert.forEach(item -> {
                    item.setCreateBy(SecurityUtils.getStrUserId());
                    item.setCreateTime(date);
                    item.setCaseId(tpParaRelatedCase.getId());
                });
                iTpParaRelatedActionService.saveBatch(actionListNeedInsert);
            }
            if (!relationEntersNeedInsert.isEmpty()) {
                relationEntersNeedInsert.forEach(item -> {
                    item.setCreateBy(SecurityUtils.getStrUserId());
                    item.setCreateTime(date);
                    item.setRelatedCaseId(tpParaRelatedCase.getId());
                });
                iTpCaseElevatorService.saveBatch(relationEntersNeedInsert);

            }

        } else {
            log.info("错误的操作标识符");
        }

        refreshCache();
        return 0;
    }


    @Override
    public TableDataInfo getTableList(TpParaRelatedCaseDto tpParaRelatedCaseDto) {
        List<TpParaRelatedCase> list = list(
            Wrappers.<TpParaRelatedCase>lambdaQuery()
                .eq(TpParaRelatedCase::getDelFlag, DelFlagEnum.NORMAL.getValue())
                    .in(CollectionUtils.isNotEmpty(tpParaRelatedCaseDto.getIds()), TpParaRelatedCase::getId, tpParaRelatedCaseDto.getIds())
                .like(StringUtils.isNotBlank(tpParaRelatedCaseDto.getCaseName()), TpParaRelatedCase::getCaseName,
                    tpParaRelatedCaseDto.getCaseName())
                .eq(StringUtils.isNotBlank(tpParaRelatedCaseDto.getStatus()), TpParaRelatedCase::getStatus,
                    tpParaRelatedCaseDto.getStatus())
                    .eq(StringUtils.isNotBlank(tpParaRelatedCaseDto.getRunType()), TpParaRelatedCase::getRunType,
                            tpParaRelatedCaseDto.getRunType())
        );

        //设置分页属性
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setTotal(new PageInfo(list).getTotal());

        if (list.isEmpty()) {
            return rspData;
        }

        List<TpParaRelatedCaseDto> res = list.stream().map(item -> {
            TpParaRelatedCaseDto resultDto = new TpParaRelatedCaseDto();
            BeanUtils.copyBeanProp(resultDto, item);
            return resultDto;
        }).collect(Collectors.toList());

        List<Long> caseIds = res.stream().map(TpParaRelatedCaseDto::getId).collect(Collectors.toList());

        List<TpParaRelatedActionDto> actionList = iTpParaRelatedActionService.queryMoreInfo(caseIds);
        Map<Long, List<TpParaRelatedActionDto>> caseIdToActionMap = actionList.stream()
            .collect(Collectors.groupingBy(TpParaRelatedActionDto::getCaseId));

        List<TpParaRelatedLogicDto> logicList = iTpParaRelatedLogicService.queryMoreInfo(caseIds);
        Map<Long, List<TpParaRelatedLogicDto>> caseIdToLogicMap = logicList.stream()
            .collect(Collectors.groupingBy(TpParaRelatedLogic::getCaseId));

        //查询关联梯形数量
        List<TpCaseElevator> elevators = iTpCaseElevatorService.list(
            Wrappers.<TpCaseElevator>lambdaQuery()
                .in(TpCaseElevator::getRelatedCaseId, caseIds)
                .eq(TpCaseElevator::getDelFlag, DelFlagEnum.NORMAL.getValue())
        );
        List<Long> relatedElevatorIds = elevators.stream().map(TpCaseElevator::getElevatorModelId).collect(Collectors.toList());
        List<RelatedModelVO> relatedModelVOList = Lists.newArrayList();
        if (CollectionUtils.isNotEmpty(relatedElevatorIds)) {
            TpParabar tpParabar = new TpParabar();
            tpParabar.setShowType(false);
            tpParabar.setRelatedType("2");
            relatedModelVOList = tpParabarService.getRelatedModelList(tpParabar);
        }
        Map<Long, String> modelNameMap = relatedModelVOList.stream().collect(Collectors.toMap(RelatedModelVO::getParabarId, RelatedModelVO::getRelatedModel));
        Map<Long, List<TpCaseElevator>> countMap = elevators.stream()
            .collect(Collectors.groupingBy(TpCaseElevator::getRelatedCaseId));

        res.forEach(item -> {
            if (countMap.containsKey(item.getId())) {
                item.setRelatedModel(countMap.get(item.getId()).stream().map(it -> modelNameMap.get(it.getElevatorModelId())).collect(Collectors.joining(";")));
            }
            List<TpParaRelatedActionDto> actions = caseIdToActionMap.get(item.getId());
            List<TpParaRelatedLogicDto> logics = caseIdToLogicMap.get(item.getId());
            StringBuilder logicStr = new StringBuilder();
            StringBuilder actionStr = new StringBuilder();
            //先拼装 条件内容
            if (ObjectUtils.isNotEmpty(logics)) {
                for (int i = 0; i < logics.size(); i++) {
                    TpParaRelatedLogicDto logicDto = logics.get(i);
                    OperationEnum operationEnum = OperationEnum.fromByValue(logicDto.getOperation());
                    String operationName = "";
                    LanguageEnum languageEnum = LanguageEnum.getByLabel(tpParaRelatedCaseDto.getCurrentLocale());

                    switch (languageEnum) {
                        case CHINESE:
                            operationName = operationEnum.getNameZH();
                            break;
                        case ENGLISH:
                            operationName = operationEnum.getNameUS();
                            break;
                        case RUSSIAN:
                            operationName = operationEnum.getNameRU();
                            break;
                        case SPANISH:
                            operationName = operationEnum.getNameES();
                            break;
                    }
                    logicStr.append(logicDto.getParaName())
                        .append(" ")
                        .append(operationName)
                        .append(" ")
                        .append((InputTypeEnum.SELECT.getCode().equals(logicDto.getInputType())
                            || InputTypeEnum.INPUT_SELECT.getCode().equals(logicDto.getInputType()))
                            ? logicDto.getLabel() : logicDto.getValue());
                    if (i != logics.size() - 1) {
                        String andOrStr = " " +
                            (RelationshipEnum.ALL_MATCH.getCode().equals(item.getRelationship()) ? "AND" : "OR")
                            + " ";
                        logicStr.append(andOrStr);
                    }
                }
            }

            item.setLogicStr(logicStr.toString());
            //拼装 结果内容
            //回显公式
            List<String> paramsList = new ArrayList<>();
            if (ObjectUtils.isNotEmpty(actions)) {
                for (TpParaRelatedActionDto data : actions) {
                    if (ComputedFlagEnum.YES.getCode().equals(data.getComputedFlag())) {
                        paramsList.addAll(JEPUtils.getParam(data.getValue()));
                    }
                }
            }
            Map<String, String> codeToNameMap = new HashMap<>();
            if (!paramsList.isEmpty()) {
                paramsList = paramsList.stream().distinct().sorted(
                    Comparator.comparingInt(String::length)
                ).collect(Collectors.toList());
                //查询所有的 参数
                List<TpParaLibrary> libraries = iTpParaLibraryService.list(
                    Wrappers.<TpParaLibrary>lambdaQuery()
                        .in(TpParaLibrary::getParaCode, paramsList)
                );

                if (!libraries.isEmpty()) {
                    codeToNameMap = libraries.stream().collect(Collectors
                        .toMap(TpParaLibrary::getParaCode, TpParaLibrary::getParaName));
                }
            }
            if (ObjectUtils.isNotEmpty(actions)) {
                for (int i = 0; i < actions.size(); i++) {
                    TpParaRelatedActionDto actionDto = actions.get(i);
                    if (ComputedFlagEnum.YES.getCode().equals(actionDto.getComputedFlag())) {
                        //替换逻辑判断符号 && ||
                        actionDto.setValue(
                            actionDto.getValue()
                                .replace(JEPLogicEnum.OR.getLogicValue(), JEPLogicEnum.OR.getLogicKey()));
                        actionDto.setValue(actionDto.getValue()
                            .replace(JEPLogicEnum.AND.getLogicValue(), JEPLogicEnum.AND.getLogicKey()));
                        //替换 方法
                        List<String> funcList = JEPUtils.getFuncShort(actionDto.getValue());
                        for (String func : funcList) {
                            String formula = actionDto.getValue();
                            formula = formula.replace(JEPSplitEnum.FUNC_SPLIT_FLAG.getFuncKey(), "");
                            func = func.replace(JEPSplitEnum.FUNC_SPLIT_FLAG.getFuncKey(), "");
                            JEPFuncEnum jEPFuncEnum = JEPFuncEnum.fromByKey(func);
                            formula = formula.replace(func, jEPFuncEnum.getFuncValue());
                            actionDto.setValue(formula);
                        }
                        //替换 参数
                        String formula = actionDto.getValue();
                        List<String> params = JEPUtils.getParam(formula);
                        for (String s : params) {
                            s = s.replace(JEPSplitEnum.PARAM_SPLIT_FLAG.getFuncKey(), "");
                            if (codeToNameMap.containsKey(s)) {
                                formula = formula.replace(s, codeToNameMap.get(s))
                                    .replace(JEPSplitEnum.PARAM_SPLIT_FLAG.getFuncKey(), "");
                                actionDto.setValue(formula);
                            }
                        }
                    }
                    actionStr.append(actionDto.getParaName())
                        .append(" ")
                        .append(StringUtils.isNotBlank(actionDto.getValue()) ? actionDto.getValue() : "")
                        .append(" ")
                        .append(EditableEnum.ACTIVE.getCode().equals(actionDto.getEditable()) ?
                            EditableEnum.ACTIVE.getValue() : EditableEnum.INACTIVE.getValue())
                        .append(" ")
                        .append(DisplayFlagEnum.SHOW.getCode().equals(actionDto.getDisplayFlag()) ?
                            DisplayFlagEnum.SHOW.getValue() : DisplayFlagEnum.HIDE.getValue())
                        .append(" ");
                    if (i != actions.size() - 1) {
                        actionStr.append(", ");
                    }

                }
            }
            item.setActionStr(actionStr.toString());
        });
        rspData.setRows(res);
        return rspData;
    }

    // 缓存所有的梯型联动配置
    private void refreshCache(){
        List<TpParaRelatedCaseCache> relatedCaseCacheList = baseMapper.getRelatedCaseCacheList();
        Map<Long, String> caseModelsMap = baseMapper.getRelatedElevators().stream()
                .filter(item -> StringUtils.isNotBlank(item.getElevatorIds()))
                .collect(toMap(TpParaRelatedCaseCache::getId, TpParaRelatedCaseCache::getElevatorIds));
        relatedCaseCacheList.forEach(item -> {
            item.setElevatorIds(caseModelsMap.get(item.getId()));
            item.getLogics().forEach(logic -> {
                OperationEnum operationEnum = OperationEnum.fromByValue(logic.getOperation());
                logic.setOperation(operationEnum.getNameZH());
            });
        });
        redisCache.setCacheObject(CacheConstants.RELATED_CASE_KEY, relatedCaseCacheList);
        redisCache.setCacheObject(CacheConstants.RELATED_CASE_TIME_KEY, DateUtils.getTime());
    }

    @Override
    public Map<String, Object> getRelatedCaseAll(String lastUpdate) {
        Map<String, Object> result = Maps.newHashMap();
        String time = redisCache.getCacheObject(CacheConstants.RELATED_CASE_TIME_KEY);
        result.put("lastUpdate", time);
        if (StringUtils.isBlank(lastUpdate) || !lastUpdate.equals(time)) {
            result.put("cases", redisCache.getCacheObject(CacheConstants.RELATED_CASE_KEY));
        }
        return result;
    }

    @Override
    public TpParaRelatedCaseDto getInfoById(Long id) {
        TpParaRelatedCaseDto basicInfo = new TpParaRelatedCaseDto();

        TpParaRelatedCase tpParaRelatedCase = getById(id);
        if (Objects.isNull(tpParaRelatedCase)) {
            //数据已被删除
            throw new ServiceErrorException(MessageUtils.message("common.dataDeleted"));
        }
        BeanUtils.copyBeanProp(basicInfo, tpParaRelatedCase);
        //查找关联梯型
        List<TpCaseElevatorDto> elevatorList = iTpCaseElevatorService.initData(tpParaRelatedCase.getId());
        basicInfo.setRelationEnters(elevatorList);

        //条件list
        List<TpParaRelatedLogicDto> logicDtos = iTpParaRelatedLogicService.queryMoreInfo(
            Collections.singletonList(basicInfo.getId()));

        basicInfo.setLogicList(logicDtos);

        //结果list
        List<TpParaRelatedActionDto> actionDtos = iTpParaRelatedActionService.queryMoreInfo(
            Collections.singletonList(basicInfo.getId()));
        basicInfo.setActionList(actionDtos);
        return basicInfo;
    }

    @Override
    public int changeStatus(TpParaRelatedCaseDto param) {
        TpParaRelatedCase sqlData = getById(param.getId());
        if (sqlData == null) {
            //数据已被删除
            throw new ServiceErrorException(MessageUtils.message("common.dataDeleted"));
        }
        if (!ValidateUtils.allowUpdate(sqlData.getUpdateTime(), param.getUpdateTime())) {
            throw new ServiceErrorException(MessageUtils.message("common.dataUpdated"));
        }
        sqlData.setStatus(param.getStatus());
        sqlData.setUpdateBy(SecurityUtils.getStrUserId());
        sqlData.setUpdateTime(new Date());
        updateById(sqlData);
        refreshCache();
        return 1;
    }

    @Override
    public List<TpCaseElevatorDto> initData(Long caseId) {
        return iTpCaseElevatorService.initData(caseId);
    }

    @Override
    public Map<String, Object> getInfoByTpElevatorModelId(Long tpElevatorModelId) {
        Map<String, Object> finalResult = new HashMap<>();
        List<Map<String, Object>> resultList = new ArrayList<>();
        //通过区域梯型id 在 tp_case_elevator 中查找 related_case
        List<TpCaseElevator> caseElevators = iTpCaseElevatorService.list(
            Wrappers.<TpCaseElevator>lambdaQuery()
                .eq(TpCaseElevator::getElevatorModelId, tpElevatorModelId)
                .eq(TpCaseElevator::getDelFlag, DelFlagEnum.NORMAL.getValue())
        );
        if (caseElevators == null || caseElevators.isEmpty()) {
            //未查询到数据
            // throw new ServiceErrorException(MessageUtils.message("relatedCase.queryNoData"));
            return finalResult;
        }
        List<Long> relatedCaseId = caseElevators.stream().map(TpCaseElevator::getRelatedCaseId).distinct()
            .collect(Collectors.toList());

        List<TpParaRelatedCase> tpParaRelatedCases = list(
            Wrappers.<TpParaRelatedCase>lambdaQuery()
                .in(TpParaRelatedCase::getId, relatedCaseId)
                .eq(TpParaRelatedCase::getDelFlag, DelFlagEnum.NORMAL.getValue())
                .eq(TpParaRelatedCase::getStatus, StatusEnum.ENABLE.getCode())
        );
        if (tpParaRelatedCases == null || tpParaRelatedCases.isEmpty()) {
            return finalResult;
        }

        //logicList
        List<TpParaRelatedLogicDto> logicAllDtos = iTpParaRelatedLogicService
            .queryMoreInfo(relatedCaseId);
        //actionList
        List<TpParaRelatedActionDto> actionAllDtos = iTpParaRelatedActionService
            .queryMoreInfo(relatedCaseId);

        //根据 id 分组
        Map<Long, List<TpParaRelatedLogicDto>> relatedIdToLogic = logicAllDtos.stream()
            .collect(Collectors.groupingBy(TpParaRelatedLogicDto::getCaseId));

        Map<Long, List<TpParaRelatedActionDto>> relatedIdToAction = actionAllDtos.stream()
            .collect(Collectors.groupingBy(TpParaRelatedActionDto::getCaseId));

        for (TpParaRelatedCase tpParaRelatedCase : tpParaRelatedCases) {
            Map<String, Object> result = new HashMap<>();

            //逻辑关系
            result.put("relationship", tpParaRelatedCase.getRelationship());
            result.put("caseName", tpParaRelatedCase.getCaseName());
            result.put("runType", tpParaRelatedCase.getRunType());
            result.put("runIndex", tpParaRelatedCase.getRunIndex());
            //infoList
            List<TpParaRelatedLogicInfo> infoList = new ArrayList<>();
            List<TpParaRelatedLogicDto> logicDtos = relatedIdToLogic
                .getOrDefault(tpParaRelatedCase.getId(), new ArrayList<>());
            List<TpParaRelatedActionDto> actionDtos = relatedIdToAction
                .getOrDefault(tpParaRelatedCase.getId(), new ArrayList<>());

            for (TpParaRelatedLogicDto logicDto : logicDtos) {
                TpParaRelatedLogicInfo logicInfo = new TpParaRelatedLogicInfo();
                logicInfo.setParaCode(logicDto.getParaCode());
                logicInfo.setParaName(logicDto.getParaName());
                logicInfo.setParaNameRU(logicDto.getParaNameRU());
                logicInfo.setParaNameES(logicDto.getParaNameES());
                logicInfo.setParaNameUS(logicDto.getParaNameUS());
                logicInfo.setValue(logicDto.getValue());
                OperationEnum operationEnum = OperationEnum.fromByValue(logicDto.getOperation());
                logicInfo.setOperation(operationEnum.getNameZH());
                logicInfo.setInputType(logicDto.getInputType());
                infoList.add(logicInfo);
            }
            result.put("condition", infoList);
            result.put("conditionKeys",
                infoList.stream().map(TpParaRelatedLogicInfo::getParaCode).collect(Collectors.toList()));

            //actionInfos
            List<TpParaRelatedActionInfo> actionInfos = new ArrayList<>();

            for (TpParaRelatedActionDto actionDto : actionDtos) {
                TpParaRelatedActionInfo actionInfo = new TpParaRelatedActionInfo();
                actionInfo.setParaCode(actionDto.getParaCode());
                actionInfo.setParaName(actionDto.getParaName());
                actionInfo.setParaNameRU(actionDto.getParaNameRU());
                actionInfo.setParaNameES(actionDto.getParaNameES());
                actionInfo.setParaNameUS(actionDto.getParaNameUS());
                // @Date 2024/6/11 15:37 @Author jubs 😀 @description: 如果是计算属性，需要解析后的公式值
                if (ComputedFlagEnum.YES.getCode().equals(actionDto.getComputedFlag())) {
                    actionInfo.setComputedFlag(ComputedFlagEnum.YES.getCode());
                    actionInfo.setValueFormulaTxt(actionDto.getValueFormulaTxt());
                } else {
                    actionInfo.setComputedFlag(ComputedFlagEnum.NO.getCode());
                }
                actionInfo.setValue(actionDto.getValue());
                actionInfo.setEditable(actionDto.getEditable());
                actionInfo.setEmptyFlag(actionDto.getEmptyFlag());
                actionInfo.setDisplayFlag(actionDto.getDisplayFlag());
                actionInfo.setOptionList(new ArrayList<>());
                if ((InputTypeEnum.SELECT.getCode().equals(actionDto.getInputType())
                    || InputTypeEnum.INPUT_SELECT.getCode().equals(actionDto.getInputType()))
                    && StringUtils.isNotBlank(actionDto.getSelectItem())) {
                    //封装可选options
                    List<String> selectItems = Arrays.asList(actionDto.getSelectItem().split(";"));
                    if (!selectItems.isEmpty()) {
                        List<Option> optionList = actionDto.getOptions().stream()
                            .filter(o -> selectItems.contains(o.getValue())).map(
                                item -> {
                                    Option option = new Option();
                                    option.setValue(item.getValue());
                                    option.setLabel(item.getLabel());
                                    option.setLabelRU(item.getLabelRU());
                                    option.setLabelES(item.getLabelES());
                                    option.setLabelUS(item.getLabelUS());
                                    return option;
                                }
                            ).collect(Collectors.toList());
                        actionInfo.setOptionList(optionList);
                    }
                }
                actionInfos.add(actionInfo);
            }
            result.put("result", actionInfos);
            resultList.add(result);
        }
        // 立即执行
        Map<String, Object> realTimeMap = new HashMap<>();
        // 提交时执行
        List<Map<String, Object>> onCommitList = new ArrayList<>();

        // List转Map 方便查询
        for (Map<String, Object> map : resultList) {
            String runType = (String)map.get("runType");
            // 提交时执行
            if (RunTypeEnum.ON_COMMIT.getCode().equals(runType)) {
                onCommitList.add(map);
            } else {
                // 立即执行
                List<String> conditionKeys = (List<String>)map.get("conditionKeys");
                for (String key : conditionKeys) {
                    List<Map<String, Object>> realTimeList = (List<Map<String, Object>>)realTimeMap.get(key);
                    if (CollUtil.isEmpty(realTimeList)) {
                        realTimeList = new ArrayList<>();
                    }
                    realTimeList.add(map);
                    realTimeMap.put(key, realTimeList);
                }
            }
        }
        Comparator<Map<String, Object>> comparator = Comparator.comparing(m -> (Integer)m.get("runIndex"));
        onCommitList.sort(comparator);
        finalResult.put("realTime", realTimeMap);
        finalResult.put("onCommit", onCommitList);
        return finalResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteById(Long id, Date updateTime) {
        TpParaRelatedCase sqlData = getById(id);
        if (sqlData == null||DelFlagEnum.DELETED.getValue().equals(sqlData.getDelFlag())) {
            //数据已被删除
            throw new ServiceErrorException(MessageUtils.message("common.dataDeleted"));
        }
        if (!ValidateUtils.allowUpdate(sqlData.getUpdateTime(), updateTime)) {
            throw new ServiceErrorException(MessageUtils.message("common.dataUpdated"));
        }
        Date date = new Date();
        //删除关联表
        List<TpCaseElevator> caseElevators = iTpCaseElevatorService.list(
            Wrappers.<TpCaseElevator>lambdaQuery()
                .eq(TpCaseElevator::getRelatedCaseId, id)
                .eq(TpCaseElevator::getDelFlag, DelFlagEnum.NORMAL.getValue())
        );


        // @Date 2024/6/27 13:04 @Author jubs 😀 @description:不需要限制
        if (caseElevators != null && !caseElevators.isEmpty()) {
                /*List<Long> elevatorIds=caseElevators.stream().map(TpCaseElevator::getElevatorModelId).collect(Collectors.toList());
                // @Date 2024/6/21 11:11 @Author jubs 😀 @description:追加限制 如果报价 引用了规则，则不允许删除
                List<TqSpecification> relaTedTqSpecification = iTqSpecificationService.list(
                        Wrappers.<TqSpecification>lambdaQuery()
                                .in(TqSpecification::getElevatorModelId, elevatorIds)
                                .eq(TqSpecification::getDelFlag, DelFlagEnum.NORMAL.getValue()));
                if(CollectionUtils.isNotEmpty(relaTedTqSpecification)){
                    throw  new ServiceErrorException(MessageUtils.message("relatedCase.validateDeleteError"));
                }*/
            caseElevators.forEach(item -> {
                item.setUpdateBy(SecurityUtils.getStrUserId());
                item.setUpdateTime(date);
                item.setDelFlag(DelFlagEnum.DELETED.getValue());
            });
            iTpCaseElevatorService.updateBatchById(caseElevators);
        }
        //删除条件表
        List<TpParaRelatedLogic> logicList = iTpParaRelatedLogicService.list(
            Wrappers.<TpParaRelatedLogic>lambdaQuery()
                .eq(TpParaRelatedLogic::getCaseId, id)
                .eq(TpParaRelatedLogic::getDelFlag, DelFlagEnum.NORMAL.getValue())
        );
        if (logicList != null && !logicList.isEmpty()) {
            logicList.forEach(item -> {
                item.setUpdateBy(SecurityUtils.getStrUserId());
                item.setUpdateTime(date);
                item.setDelFlag(DelFlagEnum.DELETED.getValue());
            });
            iTpParaRelatedLogicService.updateBatchById(logicList);
        }
        //删除结果表
        List<TpParaRelatedAction> resultList = iTpParaRelatedActionService.list(
            Wrappers.<TpParaRelatedAction>lambdaQuery()
                .eq(TpParaRelatedAction::getCaseId, id)
                .eq(TpParaRelatedAction::getDelFlag, DelFlagEnum.NORMAL.getValue())
        );
        if (resultList != null && !resultList.isEmpty()) {
            resultList.forEach(item -> {
                item.setUpdateBy(SecurityUtils.getStrUserId());
                item.setUpdateTime(date);
                item.setDelFlag(DelFlagEnum.DELETED.getValue());
            });
            iTpParaRelatedActionService.updateBatchById(resultList);
        }
        sqlData.setUpdateTime(date);
        sqlData.setUpdateBy(SecurityUtils.getStrUserId());
        sqlData.setDelFlag(DelFlagEnum.DELETED.getValue());
        updateById(sqlData);

        refreshCache();
        return 1;
    }


    boolean checkNameUnique(String name, Long id) {
        List<TpParaRelatedCase> list = list(Wrappers.<TpParaRelatedCase>lambdaQuery()
            .eq(TpParaRelatedCase::getCaseName, name)
            .ne(id != null, TpParaRelatedCase::getId, id)
            .eq(TpParaRelatedCase::getDelFlag, DelFlagEnum.NORMAL.getValue()));
        return list != null && !list.isEmpty();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchChangeRelation(TpParaValidationDto param) {
        List<Long> elevatorIds = param.getElevatorModelIds();
        if (CollectionUtils.isEmpty(elevatorIds)) {
            throw new ServiceException("梯型不能为空");
        }
        List<Long> caseIds = param.getRelatedCaseIds();
        if (CollectionUtils.isEmpty(caseIds)) {
            throw new ServiceException("联动不能为空");
        }

        iTpCaseElevatorService.remove(Wrappers.<TpCaseElevator>lambdaQuery()
                .in(TpCaseElevator::getRelatedCaseId, caseIds)
                .in(TpCaseElevator::getElevatorModelId, elevatorIds)
        );

        if (param.getIsAppend()){
            List<TpCaseElevator> caseElevators = new ArrayList<>();
            caseIds.forEach(caseId -> {
                caseElevators.addAll(elevatorIds.stream().map(elevatorId -> {
                    TpCaseElevator item = new TpCaseElevator();
                    item.setRelatedCaseId(caseId);
                    item.setElevatorModelId(elevatorId);
                    return item;
                }).collect(Collectors.toList()));
            });
            iTpCaseElevatorService.saveBatch(caseElevators);
        }

        refreshCache();
        return true;
    }

    @Override
    public List<? extends List<? extends BasicExcelHelper>> getRelatedCaseList() {
        List<List<? extends BasicExcelHelper>> result = com.google.common.collect.Lists.newArrayList();

        // 1. 获取所有联动规则
        List<TpParaRelatedCase> list = list(Wrappers.<TpParaRelatedCase>lambdaQuery()
                .eq(TpParaRelatedCase::getDelFlag, DelFlagEnum.NORMAL.getValue())
                .orderByAsc(TpParaRelatedCase::getId));
        if (CollectionUtils.isEmpty(list)){
            return result;
        }
        // 1.1 关联梯型信息
        Map<Long, List<TpCaseElevator>> caseElevatorMap = iTpCaseElevatorService.list(Wrappers.<TpCaseElevator>lambdaQuery()
                .eq(TpCaseElevator::getDelFlag, DelFlagEnum.NORMAL.getValue()))
                .stream().collect(Collectors.groupingBy(TpCaseElevator::getRelatedCaseId));

        TpParabar paraBarParam = new TpParabar();
        paraBarParam.setShowType(Boolean.FALSE);
        paraBarParam.setRelatedType(null);
        List<RelatedModelVO> relatedModelVOList = tpParabarService.getRelatedModelList(paraBarParam);
        Map<Long, String> elevatorModelNameMap = relatedModelVOList.stream().collect(Collectors.toMap(RelatedModelVO::getParabarId, RelatedModelVO::getRelatedModel));

        Map<String, String> logicMap = DictUtils.getDictCache("logic_operation").stream()
                .collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        Map<String, String> runMap = DictUtils.getDictCache("run_type").stream()
                .collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        Map<String, String> statusMap = DictUtils.getDictCache("status_switch").stream()
                .collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        result.add(list.stream().map(item -> {
            ParaRelatedCaseInfoHelper excelHelper = new ParaRelatedCaseInfoHelper();
            BeanUtils.copyProperties(item, excelHelper);

            excelHelper.setRelationship(logicMap.get(item.getRelationship()));
            excelHelper.setRunType(runMap.get(item.getRunType()));
            if (Objects.nonNull(item.getRunIndex())){
                excelHelper.setRunIndex(item.getRunIndex().toString());
            }
            excelHelper.setStatus(statusMap.get(item.getStatus()));
            List<TpCaseElevator> relation = caseElevatorMap.get(item.getId());
            if (CollectionUtils.isNotEmpty(relation)){
                excelHelper.setRelatedModel(relation.stream().map(row -> elevatorModelNameMap.get(row.getElevatorModelId()))
                        .collect(Collectors.joining(";")));
            }
            return excelHelper;
        }).collect(Collectors.toList()));

        Map<Long, String> caseNameMap = list.stream().collect(Collectors.toMap(TpParaRelatedCase::getId, TpParaRelatedCase::getCaseName));
        TpParaLibrary library = new TpParaLibrary();
        List<TpParaLibrary> libraryList = tpParaLibraryService.selectTpParaLibraryList(library).stream()
                .sorted(Comparator.comparing(item -> -item.getParaName().length())).collect(Collectors.toList());
        Map<String, String> paraNameMap = libraryList.stream().collect(Collectors.toMap(TpParaLibrary::getParaCode, TpParaLibrary::getParaName));

        List<Long> caseIds = list.stream().map(TpParaRelatedCase::getId).collect(toList());

        // 2. 获取联动用例
        List<TpParaRelatedLogic> logicList = iTpParaRelatedLogicService.list(Wrappers.<TpParaRelatedLogic>lambdaQuery()
                .eq(TpParaRelatedLogic::getDelFlag, DelFlagEnum.NORMAL.getValue())
                .in(TpParaRelatedLogic::getCaseId, caseIds)
                .orderByAsc(TpParaRelatedLogic::getCaseId));
        Map<String, String> repationMap = DictUtils.getDictCache("relation_options").stream()
                .collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        result.add(logicList.stream().map(item -> {
            ParaRelatedCaseLogicHelper logic = new ParaRelatedCaseLogicHelper();
            logic.setCaseName(caseNameMap.get(item.getCaseId()));
            logic.setParaCode(paraNameMap.get(item.getParaCode()));
            logic.setOperation(repationMap.get(item.getOperation()));
            logic.setValue(item.getValue());
            return logic;
        }).collect(Collectors.toList()));

        // 3. 获取联动结果
        List<TpParaRelatedAction> actionList = iTpParaRelatedActionService.list(Wrappers.<TpParaRelatedAction>lambdaQuery()
                .eq(TpParaRelatedAction::getDelFlag, DelFlagEnum.NORMAL.getValue())
                .in(TpParaRelatedAction::getCaseId, caseIds)
                .orderByAsc(TpParaRelatedAction::getCaseId));
        Map<String, String> yesNoMap = DictUtils.getDictCache("yes_no_tinyint").stream()
                .collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        result.add(actionList.stream().map(item -> {
            ParaRelatedCaseActionHelper action = new ParaRelatedCaseActionHelper();
            action.setCaseName(caseNameMap.get(item.getCaseId()));
            action.setParaCode(paraNameMap.get(item.getParaCode()));
            action.setSelectItem(item.getSelectItem());
            action.setValue(item.getValue());
            action.setComputedFlag(yesNoMap.get(item.getComputedFlag()));
            action.setEditable(yesNoMap.get(item.getEditable()));
            action.setDisplayFlag(yesNoMap.get(item.getDisplayFlag()));
            action.setEmptyFlag(yesNoMap.get(item.getEmptyFlag()));
            return action;
        }).collect(Collectors.toList()));

        return result;
    }

    @Override
    public ExcelUtils.UploadResult<ParaRelatedCaseInfoHelper> checkCaseInfo(BasicTableInfoHelper tableInfoHelper, List<ParaRelatedCaseInfoHelper> list) {

        TpParabar paraBarParam = new TpParabar();
        paraBarParam.setShowType(Boolean.FALSE);
        paraBarParam.setRelatedType(null);
        List<RelatedModelVO> relatedModelVOList = tpParabarService.getRelatedModelList(paraBarParam);
        Map<String, Long> elevatorModelNameMap = relatedModelVOList.stream().collect(Collectors.toMap(RelatedModelVO::getRelatedModel, RelatedModelVO::getParabarId));


        return ExcelUtils.checkData(list, it -> {
            List<String> businessErrors = new ArrayList();

            if (Objects.nonNull(it.getRelatedModel())){
                String invalidNames = Arrays.stream(it.getRelatedModel().split(";"))
                        .filter(modelName -> Objects.isNull(elevatorModelNameMap.get(modelName)))
                        .collect(Collectors.joining(";"));
                if (StringUtils.isNotBlank(invalidNames)) {
                    businessErrors.add("关联梯型不存在：" + invalidNames);
                }
            }

            if (isNotBlank(it.getStatus()) && isBlank(DictUtils.getDictValue("status_switch", it.getStatus()))){
                businessErrors.add("状态不存在：" + it.getStatus());
            }

            return businessErrors;
        });
    }

    @Override
    public ExcelUtils.UploadResult<ParaRelatedCaseLogicHelper> checkCaseLogic(BasicTableInfoHelper tableInfoHelper, List<ParaRelatedCaseLogicHelper> list) {
        return ExcelUtils.checkData(list, it -> {
            List<String> businessErrors = new ArrayList();

            return businessErrors;
        });
    }

    @Override
    public ExcelUtils.UploadResult<ParaRelatedCaseActionHelper> checkCaseAction(BasicTableInfoHelper tableInfoHelper, List<ParaRelatedCaseActionHelper> list) {
        return ExcelUtils.checkData(list, it -> {
            List<String> businessErrors = new ArrayList();

            return businessErrors;
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> insertParaRelatedCase(BasicTableInfoHelper basicTableInfoHelper, List<HashMap> dataList) {
        if (CollectionUtils.isEmpty(dataList)){
            throw new ServiceException("导入数据不能为空");
        }
        TpParaLibrary library = new TpParaLibrary();
        List<TpParaLibrary> libraryList = tpParaLibraryService.selectTpParaLibraryList(library).stream()
                .sorted(Comparator.comparing(item -> -item.getParaName().length())).collect(Collectors.toList());
        Map<String, String> paraMap = libraryList.stream().collect(Collectors.toMap(TpParaLibrary::getParaName, TpParaLibrary::getParaCode));

        // 用于公式替换
        Function<String, String> replaceNames = formula -> {
            if (isBlank(formula)){
                return "";
            }

            // 1. 替换逻辑操作符
            for (JEPLogicEnum item : JEPLogicEnum.values()) {
                formula = formula.replaceAll(StringUtils.initLogicRegpx(item.getLogicKey()), item.getLogicValue());
            }

            // 2. 替换函数操作符
            for (JEPFuncEnum item : JEPFuncEnum.values()) {
                formula = formula.replaceAll(StringUtils.initFuncRegpx(item.getFuncValue()), Matcher.quoteReplacement("$@$" + item.getFuncKey() + "$@$"));
            }

            // 3. 替换变量名
            for (TpParaLibrary item: libraryList){
                formula = formula.replaceAll(StringUtils.initRegpx(item.getParaName()), Matcher.quoteReplacement("$_$" + item.getParaCode() + "$_$"));
            }

            return formula;
        };

        TpParabar paraBarParam = new TpParabar();
        paraBarParam.setShowType(Boolean.FALSE);
        paraBarParam.setRelatedType(null);
        List<RelatedModelVO> relatedModelVOList = tpParabarService.getRelatedModelList(paraBarParam);
        Map<String, Long> elevatorModelNameMap = relatedModelVOList.stream().collect(Collectors.toMap(RelatedModelVO::getRelatedModel, RelatedModelVO::getParabarId));

        Map<String, List<HashMap>> map = dataList.stream().collect(Collectors.groupingBy(item -> (String)item.get("sheetName")));
        // 1. 参数联动规则信息导入
        List<ParaRelatedCaseInfoHelper> caseInfoHelpers = transform(map.get("参数联动规则信息"), ParaRelatedCaseInfoHelper.class);
        List<TpParaRelatedCase> relatedCaseList = new ArrayList<>();
        List<TpCaseElevator> relationList = new ArrayList<>();

        Map<String, String> logicMap = DictUtils.getDictCache("logic_operation").stream()
                .collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));
        Map<String, String> runMap = DictUtils.getDictCache("run_type").stream()
                .collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));
        Map<String, String> statusMap = DictUtils.getDictCache("status_switch").stream()
                .collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));
        Map<String, String> relationMap = DictUtils.getDictCache("relation_options").stream()
                .collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));
        Map<String, String> yesNoMap = DictUtils.getDictCache("yes_no_tinyint").stream()
                .collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));

        for (ParaRelatedCaseInfoHelper item: caseInfoHelpers) {
            TpParaRelatedCase relatedCase = new TpParaRelatedCase();
            BeanUtils.copyProperties(item, relatedCase);
            relatedCase.setStatus(statusMap.get(item.getStatus()));
            relatedCase.setRelationship(logicMap.get(item.getRelationship()));
            relatedCase.setRunType(runMap.get(item.getRunType()));
            if (RunTypeEnum.ON_COMMIT.getCode().equals(relatedCase.getRunType()) && Objects.nonNull(item.getRunIndex())){
                relatedCase.setRunIndex(Integer.parseInt(item.getRunIndex()));
            }
            relatedCaseList.add(relatedCase);

            relationList.addAll(Arrays.stream(item.getRelatedModel().split(";")).map(modelName -> {
                TpCaseElevator relation = new TpCaseElevator();
                relation.setCaseName(item.getCaseName());
                relation.setElevatorModelId(elevatorModelNameMap.get(modelName));
                return relation;
            }).collect(Collectors.toList()));
        }

        // 1.2 更新数据
        baseMapper.clearAll();
        if (CollectionUtils.isNotEmpty(relatedCaseList)){

            saveBatch(relatedCaseList);
        }
        Map<String, Long> idMap = relatedCaseList.stream().collect(Collectors.toMap(TpParaRelatedCase::getCaseName, TpParaRelatedCase::getId));
        relationList.forEach(relation -> relation.setRelatedCaseId(idMap.get(relation.getCaseName())));
        iTpCaseElevatorService.clearAll();
        if (CollectionUtils.isNotEmpty(relationList)){
            iTpCaseElevatorService.saveBatch(relationList);
        }

        // 2. 联动用例导入
        List<ParaRelatedCaseLogicHelper> caseLogicHelpers = transform(map.get("联动用例"), ParaRelatedCaseLogicHelper.class);
        List<TpParaRelatedLogic> caseLogicList = new ArrayList<>();
        for (ParaRelatedCaseLogicHelper item: caseLogicHelpers) {
            TpParaRelatedLogic relatedLogic = new TpParaRelatedLogic();
            BeanUtils.copyProperties(item, relatedLogic);
            relatedLogic.setCaseId(idMap.get(item.getCaseName()));
            relatedLogic.setParaCode(paraMap.get(item.getParaCode()));;
            relatedLogic.setOperation(relationMap.get(item.getOperation()));
            caseLogicList.add(relatedLogic);
        }
        iTpParaRelatedLogicService.clearAll();
        if (CollectionUtils.isNotEmpty(caseLogicList)){
            iTpParaRelatedLogicService.saveBatch(caseLogicList);
        }

        // 3. 联动结果导入
        List<ParaRelatedCaseActionHelper> caseActionHelpers = transform(map.get("联动结果"), ParaRelatedCaseActionHelper.class);
        List<TpParaRelatedAction> caseActionList = new ArrayList<>();
        for (ParaRelatedCaseActionHelper item: caseActionHelpers) {
            TpParaRelatedAction relatedAction = new TpParaRelatedAction();
            BeanUtils.copyProperties(item, relatedAction);
            relatedAction.setCaseId(idMap.get(item.getCaseName()));
            relatedAction.setParaCode(paraMap.get(item.getParaCode()));
            relatedAction.setComputedFlag(yesNoMap.get(item.getComputedFlag()));
            if (LogicEnum.YES.getValue().equals(relatedAction.getComputedFlag())){
                relatedAction.setValueFormulaTxt(replaceNames.apply(relatedAction.getValue()));
            }
            relatedAction.setEditable(yesNoMap.get(item.getEditable()));
            relatedAction.setDisplayFlag(yesNoMap.get(item.getDisplayFlag()));
            relatedAction.setEmptyFlag(yesNoMap.get(item.getEmptyFlag()));
            caseActionList.add(relatedAction);
        }
        iTpParaRelatedActionService.clearAll();
        if (CollectionUtils.isNotEmpty(caseActionList)){
            iTpParaRelatedActionService.saveBatch(caseActionList);
        }

        refreshCache();
        return new ArrayList<>();
    }

    private <T> List<T> transform(List<HashMap> data, Class<? extends T> clazz) {
        if (CollectionUtils.isEmpty(data)) {
            return com.google.common.collect.Lists.newArrayList();
        }
        return data.stream()
                .map(item -> JSON.parseObject(JSON.toJSONString(item), clazz))
                .filter(Objects::nonNull).collect(toList());
    }
}
