package com.lcrx.selector.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;
import com.lcrx.selector.constant.RedisKey;
import com.lcrx.selector.entity.DO.VariantTableDO;
import com.lcrx.selector.entity.DTO.*;
import com.lcrx.selector.entity.DO.InitializeResultDO;
import com.lcrx.selector.entity.PO.ConfigurationBasisPO;
import com.lcrx.selector.entity.PO.ConfigurationCharacteristicValuePO;
import com.lcrx.selector.repository.ConfigurationBasisRepository;
import com.lcrx.selector.repository.ConfigurationCharacteristicValueRepository;
import com.lcrx.selector.utils.RedisHelper;
import com.lcrx.selector.utils.SnowflakeHelper;
import com.lcrx.selector.utils.StringHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ###
 */
@Service
public class SelectorService {
    @Value("${applicationSettings.sessionTimeout}")
    private Long sessionTimeout;
    @Value("${applicationSettings.system}")
    private String system;

    private final VariantTableService variantTableService;
    private final RedisHelper redisHelper;
    private final SnowflakeHelper snowflakeHelper;
    private final ConfigurationBasisRepository configurationBasisRepository;
    private final ConfigurationCharacteristicValueRepository configurationCharacteristicValueRepository;

    @Autowired
    public SelectorService(VariantTableService variantTableService,
                           RedisHelper redisHelper,
                           SnowflakeHelper snowflakeHelper,
                           ConfigurationBasisRepository configurationBasisRepository,
                           ConfigurationCharacteristicValueRepository configurationCharacteristicValueRepository
    ) {
        this.variantTableService = variantTableService;
        this.redisHelper = redisHelper;
        this.snowflakeHelper = snowflakeHelper;
        this.configurationBasisRepository = configurationBasisRepository;
        this.configurationCharacteristicValueRepository = configurationCharacteristicValueRepository;
    }

    public InitializationOutputDTO initialization(InitializationInputDTO initializationInputDTO)
    {
        //缓存total特征值
        String sessionId = Long.toString(snowflakeHelper.nextId());
        redisHelper.set(RedisKey.getTotalCharacteristicKey(sessionId), JSON.toJSONString(initializationInputDTO.getCharacteristicList()), sessionTimeout);

        List<InitializationInputDTO.KeyValuesBean> keyValues = initializationInputDTO.getKeyValues();

        if (!StringHelper.isNullOrEmpty(initializationInputDTO.getConfigId())) {
            /*ModelBasicInfo modelBasicInfo = cacheService.getConfigByConfigId(dataSourceFlag,Long.parseLong(bomInitializeInputV2DTO.getConfigId()));
            bomCode = modelBasicInfo.getBomCode();
            division = modelBasicInfo.getDivision();*/
        }

        InitializationOutputDTO initializationOutputDTO = initializationSelector("", initializationInputDTO);
        initializationOutputDTO.setSessionId(sessionId);

        //处理天生不可用的。
        dealWithIsolated(initializationOutputDTO);

        //如果要默认机型，则调用前置验证方法。
        if (!StringHelper.isNullOrEmpty(initializationInputDTO.getConfigId())) {

            ConfigurationBasisPO configurationBasisPO = refreshSelectedCharacteristic(initializationOutputDTO.getSessionId(), Long.valueOf(initializationInputDTO.getConfigId()));

            List<PreVerifyInputDTO.SelectedCharacteristicListBean> selectedCharacteristicListBeans = configurationBasisPO.getConfigurationCharacteristicValuePOList().stream().map(
                    configurationCharacteristicValuePO -> {
                        PreVerifyInputDTO.SelectedCharacteristicListBean selectedCharacteristicListBean = new PreVerifyInputDTO.SelectedCharacteristicListBean();

                        selectedCharacteristicListBean.setCharacteristicName(configurationCharacteristicValuePO.getCharacteristicName());
                        selectedCharacteristicListBean.setCharacteristicValueName(configurationCharacteristicValuePO.getCharacteristicValueName());
                        selectedCharacteristicListBean.setQuantity(configurationCharacteristicValuePO.getCharacteristicValueQuantity());
                        selectedCharacteristicListBean.setDesc(configurationCharacteristicValuePO.getCharacteristicValueDesc());
                        return selectedCharacteristicListBean;
                    }).collect(Collectors.toList());

            PreVerifyInputDTO preVerifyInputDTO = buildPreVerifyInputDTO(
                    initializationInputDTO.getProductGroupCode(),
                    initializationInputDTO.getMaterialCode(),
                    initializationInputDTO.getOperator(),
                    "",
                    "",
                    initializationOutputDTO.getSessionId(),
                    selectedCharacteristicListBeans
            );

            PreVerifyOutputDTO preVerifyOutputDTO = preVerify(preVerifyInputDTO);

            initializationOutputDTO.setActiveValues(preVerifyOutputDTO.getActiveValues().stream().map(
                    activeValuesBean -> {
                        InitializationOutputDTO.ActiveValuesBean valuesBean = new InitializationOutputDTO.ActiveValuesBean();

                        valuesBean.setCharacteristicName(activeValuesBean.getCharacteristicName());
                        valuesBean.setValues(activeValuesBean.getValues());

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

            String redisSelectedCharacteristic = redisHelper.get(RedisKey.getSelectedCharacteristicKey(initializationOutputDTO.getSessionId()));
            if(StringHelper.isNullOrEmpty(redisSelectedCharacteristic))
            {
                //todo 处理返回值
            }

            HashMap<String, String> selectedCharacteristicValueMap = JSON.parseObject(redisSelectedCharacteristic,
                    new TypeReference<HashMap<String, String>>(){});

            List<InitializationOutputDTO.SelectedValuesBean> selectedValuesBeans = new ArrayList<>();
            for(Map.Entry<String, String> selectedCharacteristicValue : selectedCharacteristicValueMap.entrySet())
            {
                InitializationOutputDTO.SelectedValuesBean selectedValuesBean = new InitializationOutputDTO.SelectedValuesBean();

                selectedValuesBean.setCharacteristicName(selectedCharacteristicValue.getKey());
                selectedValuesBean.setCharacteristicValueName(selectedCharacteristicValue.getValue());

                configurationBasisPO.getConfigurationCharacteristicValuePOList().forEach(
                        configurationCharacteristicValuePO -> {
                       if(configurationCharacteristicValuePO.getCharacteristicName().equals(selectedCharacteristicValue.getKey())
                            &&configurationCharacteristicValuePO.getCharacteristicValueName().equals(selectedCharacteristicValue.getValue())){

                           selectedValuesBean.setQuantity(configurationCharacteristicValuePO.getCharacteristicValueQuantity());
                           selectedValuesBean.setDesc(configurationCharacteristicValuePO.getCharacteristicValueDesc());
                       }
                });

                selectedValuesBeans.add(selectedValuesBean);
            }

            initializationOutputDTO.setSelectedValues(selectedValuesBeans);
        }

/*        if (bomInitializeOutputV2DTO != null) {
            //因mode兼容老逻辑，所以使用action支持edit或者view
            if(attributesBeanVO.getAction().toUpperCase().equals(Mode.edit.code.toUpperCase())) {
                dealWithDisableAtAll(bomInitializeOutputV2DTO);

                if (GlobalConstant.BASIC_MACHINE_DEFAULT.equals(bomInitializeInputV2DTO.getReferenceModel())) {
                    PreValidationOutputV2DTO preValidationOutputV2DTO = preValidate(
                            buildPreValidationInputV2DTO(
                                    division,
                                    bomCode,
                                    bomInitializeInputV2DTO.getBusinessKey(),
                                    bomInitializeInputV2DTO.getUserCode(),
                                    token, "",
                                    "",
                                    bomInitializeOutputV2DTO.getDefaultValues(),
                                    bomInitializeInputV2DTO.getAttributes()
                            ),
                            token, dataSourceFlag);

                    bomInitializeOutputV2DTO.setActiveValues(new ArrayList<>(preValidationOutputV2DTO.getActiveValues()));
                    bomInitializeOutputV2DTO.setSelectedValues(new ArrayList<>(bomInitializeOutputV2DTO.getDefaultValues()));
                } else {
                    bomInitializeOutputV2DTO.setDefaultValues(new ArrayList<>());
                }
            }

            //如果要默认机型，则调用前置验证方法。
            if (!StringUtil.isNullOrEmpty(bomInitializeInputV2DTO.getConfigId())) {
                BrushConfigurationInputDTO brushConfigurationInputDTO = new BrushConfigurationInputDTO();

                brushConfigurationInputDTO.setBomCode(bomCode);
                brushConfigurationInputDTO.setBusinessKey(bomInitializeInputV2DTO.getBusinessKey());
                brushConfigurationInputDTO.setConfigId(Long.parseLong(bomInitializeInputV2DTO.getConfigId()));
                brushConfigurationInputDTO.setDivision(division);
                brushConfigurationInputDTO.setToken(bomInitializeInputV2DTO.getToken());
                brushConfigurationInputDTO.setUserCode(bomInitializeInputV2DTO.getUserCode());

                BrushConfigurationOutputDTO brushConfigurationOutputDTO = brushConfiguration(brushConfigurationInputDTO, token, dataSourceFlag);

                bomInitializeOutputV2DTO.setActiveValues(new ArrayList<>(brushConfigurationOutputDTO.getActiveValues()));
                bomInitializeOutputV2DTO.setSelectedValues(new ArrayList<>(brushConfigurationOutputDTO.getSelectedCharacteristicList()));
            }

            //处理selected values里不是active的特征值
            if(attributesBeanVO.getAction().toUpperCase().equals(Mode.edit.code.toUpperCase())) {
                if (Objects.nonNull(bomInitializeOutputV2DTO.getActiveValues()) && bomInitializeOutputV2DTO.getActiveValues().size() > 0) {
                    for (CharacteristicValuesBean characteristicValuesBean : bomInitializeOutputV2DTO.getActiveValues()) {

                        if (Objects.nonNull(bomInitializeOutputV2DTO.getSelectedValues()) && bomInitializeOutputV2DTO.getSelectedValues().size() > 0) {
                            for (PreValidationInputV2DTO.SelectedCharacteristicBean selectedCharacteristicBean : bomInitializeOutputV2DTO.getSelectedValues()) {
                                if (selectedCharacteristicBean.getCharacteristicCode().equals(characteristicValuesBean.getCharacteristicCode())) {
                                    if (!characteristicValuesBean.getValues().contains(selectedCharacteristicBean.getCharacteristicValueCode())) {
                                        bomInitializeOutputV2DTO.getSelectedValues().remove(selectedCharacteristicBean);
                                    }

                                    break;
                                }
                            }
                        }
                    }
                }

                //todo 先临时处理隐藏C只有一个非默认可选的问题
                List<CharacteristicValuesBean> singleActiveValues = bomInitializeOutputV2DTO.getActiveValues().stream().filter(activeValue->activeValue.getValues().size() == 1
                        && bomInitializeOutputV2DTO.getSelectedValues() != null && bomInitializeOutputV2DTO.getSelectedValues().stream().
                        noneMatch(selectValue->selectValue.getCharacteristicCode().equals(activeValue.getCharacteristicCode()))).collect(Collectors.toList());
                if(singleActiveValues.size() > 0) {
                    List<PreValidationInputV2DTO.SelectedCharacteristicBean> selectedCharacteristicBeans = new ArrayList<>();

                    for (CharacteristicValuesBean characteristicValuesBean : singleActiveValues) {
                        PreValidationInputV2DTO.SelectedCharacteristicBean selectedCharacteristicBean = new PreValidationInputV2DTO.SelectedCharacteristicBean();

                        selectedCharacteristicBean.setCharacteristicCode(characteristicValuesBean.getCharacteristicCode());
                        selectedCharacteristicBean.setCharacteristicValueCode(characteristicValuesBean.getValues().get(0));

                        bomInitializeOutputV2DTO.getSelectedValues().add(selectedCharacteristicBean);
                        selectedCharacteristicBeans.add(selectedCharacteristicBean);
                    }

                    PreValidationOutputV2DTO preValidationOutputV2DTO = preValidate(
                            buildPreValidationInputV2DTO(
                                    division,
                                    bomCode,
                                    bomInitializeInputV2DTO.getBusinessKey(),
                                    bomInitializeInputV2DTO.getUserCode(),
                                    token, "",
                                    "",
                                    bomInitializeOutputV2DTO.getSelectedValues(),
                                    bomInitializeInputV2DTO.getAttributes()
                            ),
                            token, dataSourceFlag);

                    if(preValidationOutputV2DTO.getResult()) {
                        bomInitializeOutputV2DTO.setActiveValues(new ArrayList<>(preValidationOutputV2DTO.getActiveValues()));
                    }
                    else {
                        //假如验证失败复原选中
                        bomInitializeOutputV2DTO.getSelectedValues().removeAll(selectedCharacteristicBeans);
                    }
                }
            }
        }

        //处理一下选中的V都不在所有的特征值集合里的。
        if (Objects.nonNull(bomInitializeOutputV2DTO.getCharacteristicList()) && Objects.nonNull(bomInitializeOutputV2DTO.getSelectedValues()) && bomInitializeOutputV2DTO.getSelectedValues().size() > 0) {
            for (CharacteristicBean characteristicBean : bomInitializeOutputV2DTO.getCharacteristicList()) {
                for (PreValidationInputV2DTO.SelectedCharacteristicBean selectedCharacteristicBean : bomInitializeOutputV2DTO.getSelectedValues()) {
                    if (selectedCharacteristicBean.getCharacteristicCode().equals(characteristicBean.getCode())) {
                        if (!characteristicBean.getCharacteristicValues().stream().anyMatch(characteristicValueBean ->
                                characteristicValueBean.getCode().equals(selectedCharacteristicBean.getCharacteristicValueCode())
                        )){
                            bomInitializeOutputV2DTO.getSelectedValues().remove(selectedCharacteristicBean);
                        }

                        break;
                    }
                }
            }
        }

        if (bomInitializeOutputV2DTO != null) {
            bomInitializeOutputV2DTO.setResult(true);
        }

        String atsSimeSpan = "";//AST耗时计算

        if (attributes != null && attributes.size() > 0) {
            Optional<AttributesBeanDTO> attributesBeanOptional = attributes.stream().filter(a -> GlobalConstant.ATTRIBUTE_KEY_INCLUDE_ATS.equals(a.getKey())).findFirst();
            AttributesBeanDTO attributesBean = attributesBeanOptional.orElse(null);

            if (attributesBean != null && attributesBean.getValue().toUpperCase().equals("TRUE")) {

                //todo ATS 加载太慢，影响使用
                if ((lmsBindFlag &&dataSourceFlag.equals(lmsDataSource))||(smbBindFlag &&dataSourceFlag.equals(smbDataSource)) ) {

                    if (Objects.nonNull(atsDivisions)) {
                        if (atsDivisions.contains(bomInitializeInputV2DTO.getDivision())) {
                            long atsStartTime = DateUtil.fromDateStringToLong();
                            updateBomInitializeOutputV2DTO(bomInitializeInputV2DTO, bomInitializeOutputV2DTO, token, attributesBeanVO.getCdbid(), attributesBeanVO.getDataType(), attributesBeanVO.getRoleVisibleType(), dataSourceFlag);
                            long atsStopTime = DateUtil.fromDateStringToLong();
                            atsSimeSpan = " ;ats took：" + (atsStopTime - atsStartTime) + "ms";
                        }
                    }

                }
            }
        }

        if (bomInitializeOutputV2DTO != null) {
            bomInitializeOutputV2DTO.setActiveValues(bomInitializeOutputV2DTO.getActiveValues().stream().map(m -> {
                if (m.getValues().size() > 0) {
                    m.setValues(m.getValues().stream().distinct().collect(Collectors.toList()));
                }
                return m;
            }).collect(Collectors.toList()));
        }*/

        return initializationOutputDTO;
    }

    /**
     * 处理原生就不可选择的特征值
     *
     * @param initializationOutputDTO 初始化输出参数
     */
    private void dealWithIsolated(InitializationOutputDTO initializationOutputDTO) {
        Map<String, List<String>> activeValues = initializationOutputDTO.getActiveValues().stream().collect(
                Collectors.toMap(InitializationOutputDTO.ActiveValuesBean::getCharacteristicName,
                        InitializationOutputDTO.ActiveValuesBean::getValues));

        initializationOutputDTO.getCharacteristicList().forEach(characteristic ->
                characteristic.getValues().forEach(characteristicValue -> {
                    if (activeValues.containsKey(characteristic.getName())
                            && !activeValues.get(characteristic.getName()).contains(characteristicValue.getName())
                    ) {
                        characteristicValue.setIsolated(true);
                    } else {
                        characteristicValue.setIsolated(false);
                    }
                })
        );
    }

    /**
     * 根据配置id刷新选中的信息
     * @param sessionId 会话id
     * @param configId 配置id
     *
     */
    private ConfigurationBasisPO refreshSelectedCharacteristic(String sessionId, Long configId)
    {
        ConfigurationBasisPO configurationBasisPO = null;

        if(Objects.nonNull(configId)) {
            configurationBasisPO = configurationBasisRepository.getOne(configId);

            HashMap<String, String> selectedCharacteristicValueMap = configurationBasisPO.getConfigurationCharacteristicValuePOList().stream().collect(HashMap::new,
                    (map, selectedCharacteristicListBean) -> {
                        map.put(selectedCharacteristicListBean.getCharacteristicName(),
                                selectedCharacteristicListBean.getCharacteristicValueName());
                    }, HashMap::putAll);

            redisHelper.set(RedisKey.getSelectedCharacteristicKey(sessionId),
                    JSON.toJSONString(selectedCharacteristicValueMap), sessionTimeout);
        }

        return configurationBasisPO;
    }

    /**
     * 构建前置验证入参
     * @param productGroupCode 产品组
     * @param materialCode 物料编号
     * @param operator 操作人
     * @param characteristicName 特征名称
     * @param characteristicValueName 特征值名称
     * @param sessionId sessionId
     * @param selectedCharacteristicListBeans 选中特征值
     * @return 前置验证入参
     */
    private PreVerifyInputDTO buildPreVerifyInputDTO(String productGroupCode,
                                                     String materialCode,
                                                     String operator,
                                                     String characteristicName,
                                                     String characteristicValueName,
                                                     String sessionId,
                                                     List<PreVerifyInputDTO.SelectedCharacteristicListBean> selectedCharacteristicListBeans
                                                     ) {

        PreVerifyInputDTO preVerifyInputDTO = new PreVerifyInputDTO();

        preVerifyInputDTO.setProductGroupCode(productGroupCode);
        preVerifyInputDTO.setMaterialCode(materialCode);
        preVerifyInputDTO.setOperator(operator);
        preVerifyInputDTO.setCharacteristicName(characteristicName);
        preVerifyInputDTO.setCharacteristicValueName(characteristicValueName);
        preVerifyInputDTO.setSessionId(sessionId);
        preVerifyInputDTO.setSelectedCharacteristicList(selectedCharacteristicListBeans);

        return preVerifyInputDTO;
    }

    /**
     * 初始化数据
     *
     * @param mode     模式
     * @param initializationInputDTO     入参
     */
    private InitializationOutputDTO initializationSelector(String mode, InitializationInputDTO initializationInputDTO) {
        InitializationOutputDTO initializationOutputDTO = new InitializationOutputDTO();
        Map<String, List<String>> characteristicValuesMap = new LinkedHashMap<>();

        for(InitializationInputDTO.CharacteristicListBean characteristicListBean : initializationInputDTO.getCharacteristicList())
        {
            characteristicValuesMap.put(characteristicListBean.getName(),
                    characteristicListBean.getValues().stream().map(InitializationInputDTO.CharacteristicListBean.ValuesBean::getName).collect(Collectors.toList()));
        }

        Map<Integer, VariantTableDO> variantTableDOMap = variantTableService.getVariantTable(
                initializationInputDTO.getSystem(),
                initializationInputDTO.getProductGroupCode(),
                initializationInputDTO.getMaterialCode()
                );

        if(Objects.isNull(variantTableDOMap) || variantTableDOMap.size() == 0)
        {
            return initializationOutputDTO;
        }

        initializationOutputDTO.setConstraintCharacteristicNames(new ArrayList<>());

        variantTableDOMap.forEach((key, value) -> {
            initializationOutputDTO.getConstraintCharacteristicNames().removeAll(value.getConstraintCharacteristicName());
            initializationOutputDTO.getConstraintCharacteristicNames().addAll(value.getConstraintCharacteristicName());
        });

        Map<Integer, Map<Integer, Map<String, List<String>>>> variantTableMap = new HashMap<>(variantTableDOMap.size());

        variantTableService.buildVariantTableStructure(variantTableDOMap, variantTableMap);

        Map<Integer, Map<Integer, Map<String, List<String>>>> tempVariantTableMap = new HashMap<>(variantTableMap);

        Map<String, List<String>> relationship = new HashMap<>();
        //标明失效的行
        Map<Integer, List<Integer>> aryInvalidGroup = new HashMap<>();

        int isSuccess;
        /*// todo 为了不让VT的0值的default rule被忽略，所以cvs全集要加入#
        aryCVSClone.forEach((k, v)->{
            v.add(variantTableLinePlaceholderValue);
        });*/

        do {
            //初始化 为 0
            isSuccess = 0;
            InitializeResultDO bomInitializeExResult = variantTableService.initializeMaterialVariantTable(characteristicValuesMap, tempVariantTableMap, aryInvalidGroup);
            tempVariantTableMap = bomInitializeExResult.getVariantTableMap();
            aryInvalidGroup = bomInitializeExResult.getInvalidGroupMap();
            Map<Integer, Map<String, List<String>>> aryRSTemp = bomInitializeExResult.getVariantTableGroupMap();

            //变式表之间取交集
            for (Map.Entry<Integer, Map<String, List<String>>> data : aryRSTemp.entrySet()) {
                for (Map.Entry<String, List<String>> rKvp : data.getValue().entrySet()) {
                    if (!relationship.containsKey(rKvp.getKey())) {
                        relationship.put(rKvp.getKey(), rKvp.getValue());
                    } else {
                        relationship.get(rKvp.getKey()).retainAll(rKvp.getValue());
                    }
                }
            }
            Map<String, List<String>> dicUpdate = new HashMap<>(relationship.size());
            //判断relationship 结果集是否 与 BOMInitialize(bomCode, aryCVSClone, division);结果集一致，如不一直则继续循环处理aryCVSClone结果集
            for (Map.Entry<String, List<String>> relationshipItem : relationship.entrySet()) {
                List<String> aryCVSValue = characteristicValuesMap.get(relationshipItem.getKey());
                List<String> relationshipItemValue = relationship.get(relationshipItem.getKey());

                //如过数量为0 ，则直接跳出循环
                if (aryCVSValue.size() == 0 || relationshipItemValue.size() == 0) {
                    isSuccess = 0;
                    break;
                }

                List<String> result = new ArrayList<>();
                Collections.addAll(result, new String[aryCVSValue.size()]);
                Collections.copy(result, aryCVSValue);
                //两个结果集取交集，
                result.retainAll(relationshipItemValue);
                //如过交集后个数，与原数据 个数不一致，则将交集结果 赋值 aryCVSClone
                if (result.size() != aryCVSValue.size() || result.size() != relationshipItemValue.size()) {
                    List<String> aryCVSResult = new ArrayList<>(result);

                    characteristicValuesMap.put(relationshipItem.getKey(), aryCVSResult);
                    dicUpdate.put(relationshipItem.getKey(), new ArrayList<>(aryCVSResult));

                    //证明V 不一样
                    isSuccess++;
                }
            }
            relationship.putAll(dicUpdate);

            if (characteristicValuesMap.size() == 0) {
                isSuccess = 0;
            }
        } while (isSuccess != 0);

        /*if (relationship.size() > 0) {
            for (BasicDataPropertyValue propertyValue : aryValue) {
                String r3code = StringHelper.trimLeadingCharacter(propertyValue.getR3Code(), '0');
                int tempv = Integer.parseInt(StringHelper.trimLeadingCharacter(propertyValue.getR3VCode().replace(propertyValue.getR3Code(), ""), '0'));

                if (tempv != 0 && relationship.containsKey(r3code)) {
                    //存在则为有效
                    if (!relationship.get(r3code).contains(tempv)) {
                        //存在VT异常的V
                        if (propertyValue.getIsDefault() == 1) {
                            //说明存在基准为不可选的错误状态
                            propertyValue.setIsAllow(-1);
                        } else {
                            propertyValue.setIsAllow(0);
                        }
                    }
                }
            }
        }*/

        //重新构建数据，保证数据顺序
        Map<String, List<String>> newRelationship = new LinkedHashMap<>();
        for (Map.Entry<String, List<String>> ary : characteristicValuesMap.entrySet()) {
            if (relationship.containsKey(ary.getKey())) {
                newRelationship.put(ary.getKey(), relationship.get(ary.getKey()));
            }
        }

        initializationOutputDTO.setMaterialCode(initializationInputDTO.getMaterialCode());
        initializationOutputDTO.setProductGroupCode(initializationInputDTO.getProductGroupCode());

        buildBomInitializeOutput(initializationInputDTO, initializationOutputDTO, newRelationship);

        return initializationOutputDTO;
    }

    public BuildConfigurationOutputDTO buildConfiguration(BuildConfigurationInputDTO buildConfigurationInputDTO) {
        BuildConfigurationOutputDTO buildConfigurationOutputDTO = new BuildConfigurationOutputDTO();

        if (buildConfigurationInputDTO.getSelectedComplete()) {
            //todo 后置校验先不做
        }

        ConfigurationBasisPO configurationBasisPO = buildConfigurationBasis(buildConfigurationInputDTO);

        configurationBasisRepository.save(configurationBasisPO);

        buildConfigurationOutputDTO.setConfigId(configurationBasisPO.getConfigId());

        return buildConfigurationOutputDTO;
    }

    private ConfigurationBasisPO buildConfigurationBasis(BuildConfigurationInputDTO BuildConfigurationInputDTO) {
        ConfigurationBasisPO configurationBasisPO = new ConfigurationBasisPO();

        Long configId = snowflakeHelper.nextId();
        Long id;
        configurationBasisPO.setConfigId(configId);
        configurationBasisPO.setProductGroupCode(BuildConfigurationInputDTO.getProductGroupCode());
        configurationBasisPO.setMaterialCode(BuildConfigurationInputDTO.getMaterialCode());
        configurationBasisPO.setOperator(BuildConfigurationInputDTO.getOperator());
        configurationBasisPO.setCreateTime(new Date());

        List<ConfigurationCharacteristicValuePO> configurationCharacteristicValuePOList = new ArrayList<>();

        for (BuildConfigurationInputDTO.SelectedCharacteristicListBean selectedCharacteristicListBean : BuildConfigurationInputDTO.getSelectedCharacteristicList()
        ) {
            id = snowflakeHelper.nextId();

            ConfigurationCharacteristicValuePO configurationCharacteristicValuePO = new ConfigurationCharacteristicValuePO();

            configurationCharacteristicValuePO.setId(id);
            configurationCharacteristicValuePO.setConfigId(configId);
            configurationCharacteristicValuePO.setCharacteristicName(selectedCharacteristicListBean.getCharacteristicName());
            configurationCharacteristicValuePO.setCharacteristicValueName(selectedCharacteristicListBean.getCharacteristicValueName());
            configurationCharacteristicValuePO.setCharacteristicValueQuantity(selectedCharacteristicListBean.getQuantity());
            //todo zjw修改 新增备注
            configurationCharacteristicValuePO.setCharacteristicValueDesc(selectedCharacteristicListBean.getDesc());
            configurationCharacteristicValuePO.setConfigurationBasisPO(configurationBasisPO);

            configurationCharacteristicValuePOList.add(configurationCharacteristicValuePO);
        }

        configurationBasisPO.setConfigurationCharacteristicValuePOList(configurationCharacteristicValuePOList);

        return configurationBasisPO;
    }

    private void buildBomInitializeOutput(InitializationInputDTO initializationInputDTO, InitializationOutputDTO initializationOutputDTO, Map<String, List<String>> relationship) {
        List<InitializationOutputDTO.CharacteristicListBean> characteristicListBeans = new ArrayList<>();
        List<InitializationOutputDTO.ActiveValuesBean> activeValuesBeans = new ArrayList<>();

        int index = 1;
        for (InitializationInputDTO.CharacteristicListBean inputCharacteristicListBean : initializationInputDTO.getCharacteristicList()
        ) {
            InitializationOutputDTO.CharacteristicListBean characteristicListBean = new InitializationOutputDTO.CharacteristicListBean();

            characteristicListBean.setName(inputCharacteristicListBean.getName());
            characteristicListBean.setType(inputCharacteristicListBean.getType());
            characteristicListBean.setPairCharacteristicValueName(inputCharacteristicListBean.getPairCharacteristicName());

            List<InitializationOutputDTO.CharacteristicListBean.ValuesBean> characteristicValueBeans = new ArrayList<>();

            for (InitializationInputDTO.CharacteristicListBean.ValuesBean valuesBean : inputCharacteristicListBean.getValues()
            ) {
                InitializationOutputDTO.CharacteristicListBean.ValuesBean characteristicValueBean = new InitializationOutputDTO.CharacteristicListBean.ValuesBean();

                characteristicValueBean.setName(valuesBean.getName());
                //todo zjw修改 新增数量型C值
                List<InitializationInputDTO.KeyValuesBean> keyValues = valuesBean.getKeyValues();
                List<InitializationOutputDTO.KeyValuesBean> list1 = new ArrayList<>();
                if(!CollectionUtils.isEmpty(keyValues)){
                    keyValues.forEach(keyValuesBean -> {
                        InitializationOutputDTO.KeyValuesBean keyValuesBean1 = new InitializationOutputDTO.KeyValuesBean();
                        keyValuesBean1.setKey(keyValuesBean.getKey());
                        keyValuesBean1.setValue(keyValuesBean.getValue());
                        list1.add(keyValuesBean1);
                    });
                }
                characteristicValueBean.setKeyValues(list1);
                characteristicValueBeans.add(characteristicValueBean);
            }

            characteristicListBean.setValues(characteristicValueBeans);
            characteristicListBeans.add(characteristicListBean);

            index += 1;
        }

        for (Map.Entry<String, List<String>> entry : relationship.entrySet()) {
            InitializationOutputDTO.ActiveValuesBean activeValuesBean = new InitializationOutputDTO.ActiveValuesBean();

            activeValuesBean.setCharacteristicName(entry.getKey());
            activeValuesBean.setValues(entry.getValue().stream().map(Object::toString).collect(Collectors.toList()));
            activeValuesBeans.add(activeValuesBean);
        }

        initializationOutputDTO.setCharacteristicList(characteristicListBeans);
        initializationOutputDTO.setActiveValues(activeValuesBeans);
        initializationOutputDTO.setSelectedValues(null);

    }

    /**
     * @param preVerifyInputDTO 前置验证输入参数
     * @return PreVerifyOutputDTO
     */
    public PreVerifyOutputDTO preVerify(PreVerifyInputDTO preVerifyInputDTO) {

        PreVerifyOutputDTO preVerifyOutputDTO = null;

        //从redis获取全部的配置信息和已选的配置信息
        String redisTotalCharacteristic = redisHelper.get(RedisKey.getTotalCharacteristicKey(preVerifyInputDTO.getSessionId()));
        String redisSelectedCharacteristic = redisHelper.get(RedisKey.getSelectedCharacteristicKey(preVerifyInputDTO.getSessionId()));
        if(StringHelper.isNullOrEmpty(redisTotalCharacteristic))
        {
            //todo 处理返回值 zjw修改新增返回
            preVerifyOutputDTO = new PreVerifyOutputDTO();
            preVerifyOutputDTO.setMessage("");
            preVerifyOutputDTO.setResult(true);
            return preVerifyOutputDTO;

        }

        List<InitializationInputDTO.CharacteristicListBean> totalCharacteristicList = JSON.parseObject(redisTotalCharacteristic,
                new TypeReference<List<InitializationInputDTO.CharacteristicListBean>>(){});

        HashMap<String, String> selectedCharacteristicValueMap = JSON.parseObject(redisSelectedCharacteristic,
                new TypeReference<HashMap<String, String>>(){});

        preVerifyOutputDTO = variantTableService.preVerify(totalCharacteristicList,
                Objects.isNull(selectedCharacteristicValueMap)?new HashMap<>(0):selectedCharacteristicValueMap,
                preVerifyInputDTO);

        return preVerifyOutputDTO;
    }

    public PostVerifyOutputDTO postVerify(PostVerifyInputDTO postVerifyInputDTO) {

        HashMap<String, String> selectedCharacteristicValueMap = postVerifyInputDTO.getSelectedCharacteristicList().stream().collect(HashMap::new,
                (map, selectedCharacteristicListBean) ->{
                    map.put(selectedCharacteristicListBean.getCharacteristicName(),
                            selectedCharacteristicListBean.getCharacteristicValueName());
                }, HashMap::putAll);

        List<String> characteristicList = variantTableService.verifyVariantTable(
                postVerifyInputDTO.getMaterialCode(),
                postVerifyInputDTO.getProductGroupCode(),
                selectedCharacteristicValueMap);

        PostVerifyOutputDTO postVerifyOutputDTO = new PostVerifyOutputDTO();

        if (characteristicList != null && characteristicList.size() > 0) {
            postVerifyOutputDTO.setResult(false);
            postVerifyOutputDTO.setCharacteristicList(characteristicList);
            //todo zjw修改 新增返回message为 list.toString
            postVerifyOutputDTO.setMessage(characteristicList.toString());
        } else {
            postVerifyOutputDTO.setResult(true);
            //todo zjw修改 新增返回message
            postVerifyOutputDTO.setMessage("验证通过");
        }

        return postVerifyOutputDTO;
    }

    /**
     * 根据已有配置生成新的配置
     * @param copyConfigurationInputDTO 已有配置
     * @return 新配置
     */
    public CopyConfigurationOutputDTO copyConfiguration(CopyConfigurationInputDTO copyConfigurationInputDTO) {

        CopyConfigurationOutputDTO copyConfigurationOutputDTO = new CopyConfigurationOutputDTO();

        List<ConfigurationBasisPO> configurationBasisPOList = configurationBasisRepository.findAllById(
                copyConfigurationInputDTO.getConfigIds().stream().map(Long::valueOf).collect(Collectors.toList()));

        List<ConfigurationBasisPO> configurationBasisPONewList = new ArrayList<>(configurationBasisPOList.size());
        List<CopyConfigurationOutputDTO.ConfigIdsBean> configIdsBeanList = new ArrayList<>(configurationBasisPOList.size());

        for(ConfigurationBasisPO configurationBasisPO : configurationBasisPOList) {
            BuildConfigurationInputDTO buildConfigurationInputDTO = new BuildConfigurationInputDTO();

            buildConfigurationInputDTO.setOperator(copyConfigurationInputDTO.getOperator());
            buildConfigurationInputDTO.setMaterialCode(configurationBasisPO.getMaterialCode());
            buildConfigurationInputDTO.setProductGroupCode(configurationBasisPO.getProductGroupCode());
            buildConfigurationInputDTO.setSelectedCharacteristicList(configurationBasisPO.getConfigurationCharacteristicValuePOList()
                    .stream().map(configurationCharacteristicValuePO -> {
                        BuildConfigurationInputDTO.SelectedCharacteristicListBean selectedCharacteristicListBean = new BuildConfigurationInputDTO.SelectedCharacteristicListBean();

                        selectedCharacteristicListBean.setCharacteristicName(configurationCharacteristicValuePO.getCharacteristicName());
                        selectedCharacteristicListBean.setCharacteristicValueName(configurationCharacteristicValuePO.getCharacteristicValueName());
                        //todo zjw修改 新增备注、数量
                        selectedCharacteristicListBean.setQuantity(configurationCharacteristicValuePO.getCharacteristicValueQuantity());
                        selectedCharacteristicListBean.setDesc(configurationCharacteristicValuePO.getCharacteristicValueDesc());

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

            ConfigurationBasisPO configurationBasisNew = buildConfigurationBasis(buildConfigurationInputDTO);
            configurationBasisPONewList.add(configurationBasisNew);

            CopyConfigurationOutputDTO.ConfigIdsBean configIdsBean = new CopyConfigurationOutputDTO.ConfigIdsBean();

            configIdsBean.setConfigId(configurationBasisPO.getConfigId().toString());
            configIdsBean.setNewConfigId(configurationBasisNew.getConfigId().toString());

            configIdsBeanList.add(configIdsBean);
        }

        configurationBasisRepository.saveAll(configurationBasisPONewList);

        copyConfigurationOutputDTO.setConfigIds(configIdsBeanList);

        return copyConfigurationOutputDTO;
    }

    public List<GetConfigurationOutputDTO> getConfigurations(List<String> configIds) {

        List<GetConfigurationOutputDTO> getConfigurationOutputDTOList = new ArrayList<>();

        List<ConfigurationBasisPO> configurationBasisPOList = configurationBasisRepository.findAllById(
                configIds.stream().map(Long::valueOf).collect(Collectors.toList()));

        for(ConfigurationBasisPO configurationBasisPO : configurationBasisPOList)
        {
            GetConfigurationOutputDTO getConfigurationOutputDTO = new GetConfigurationOutputDTO();

            getConfigurationOutputDTO.setConfigId(configurationBasisPO.getConfigId().toString());
            //todo zjw修改 新增物料编码返回
            getConfigurationOutputDTO.setMaterialCode(configurationBasisPO.getMaterialCode());
            getConfigurationOutputDTO.setSelectedCharacteristicList(configurationBasisPO.getConfigurationCharacteristicValuePOList()
                    .stream().map(configurationCharacteristicValuePO -> {
                        GetConfigurationOutputDTO.SelectedCharacteristicListBean selectedCharacteristicListBean = new GetConfigurationOutputDTO.SelectedCharacteristicListBean();

                        selectedCharacteristicListBean.setCharacteristicName(configurationCharacteristicValuePO.getCharacteristicName());
                        selectedCharacteristicListBean.setCharacteristicValueName(configurationCharacteristicValuePO.getCharacteristicValueName());
                        //todo zjw修改 新增备注、数量C值
                        selectedCharacteristicListBean.setQuantity(configurationCharacteristicValuePO.getCharacteristicValueQuantity());
                        selectedCharacteristicListBean.setDesc(configurationCharacteristicValuePO.getCharacteristicValueDesc());

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

            getConfigurationOutputDTOList.add(getConfigurationOutputDTO);
        }

        return getConfigurationOutputDTOList;
    }

    public ConflictAnalysisOutputDTO conflictAnalysis(ConflictAnalysisInputDTO conflictAnalysisInputDTO) {

        ConflictAnalysisOutputDTO conflictAnalysisOutputDTO = new ConflictAnalysisOutputDTO();

        String materialCode = conflictAnalysisInputDTO.getMaterialCode();
        String characteristicName = conflictAnalysisInputDTO.getCharacteristicName();
        String characteristicValueName = conflictAnalysisInputDTO.getCharacteristicValueName();
        String productGroupCode = conflictAnalysisInputDTO.getProductGroupCode();

        //从redis获取全部的配置信息和已选的配置信息
        String redisTotalCharacteristic = redisHelper.get(RedisKey.getTotalCharacteristicKey(conflictAnalysisInputDTO.getSessionId()));
        String redisSelectedCharacteristic = redisHelper.get(RedisKey.getSelectedCharacteristicKey(conflictAnalysisInputDTO.getSessionId()));
        if(StringHelper.isNullOrEmpty(redisTotalCharacteristic))
        {
            //todo 处理返回值
        }

        List<InitializationInputDTO.CharacteristicListBean> totalCharacteristicList = JSON.parseObject(redisTotalCharacteristic,
                new TypeReference<List<InitializationInputDTO.CharacteristicListBean>>(){});

        HashMap<String, List<String>> totalCharacteristicMap = new HashMap<>(totalCharacteristicList.size());
        HashMap<String, String> selectedCharacteristicMap = new HashMap<>(conflictAnalysisInputDTO.getSelectedCharacteristicList().size());

        conflictAnalysisInputDTO.getSelectedCharacteristicList().forEach(selectedCharacteristicListBean ->
                selectedCharacteristicMap.put(selectedCharacteristicListBean.getCharacteristicName(),
                        selectedCharacteristicListBean.getCharacteristicValueName()));

        if(Objects.nonNull(conflictAnalysisInputDTO.getSelectedCharacteristicList())
                && conflictAnalysisInputDTO.getSelectedCharacteristicList().size() > 0){
            redisHelper.set(RedisKey.getSelectedCharacteristicKey(conflictAnalysisInputDTO.getSessionId()),
                    JSON.toJSONString(selectedCharacteristicMap), sessionTimeout);
        }

        selectedCharacteristicMap.put(characteristicName, characteristicValueName);

        Map<Integer, VariantTableDO> variantTableDOMap = variantTableService.getVariantTable(system, productGroupCode, materialCode);

        Map<Integer, Map<String, List<String>>> resultMap = variantTableService.initialConflictAnalysis(characteristicName,
                selectedCharacteristicMap,
                variantTableDOMap);

        List<String> conflictCharacteristicList = new ArrayList<>();

        //先把本身也加进去
        conflictCharacteristicList.add(conflictAnalysisInputDTO.getCharacteristicName());

        for (Integer key : resultMap.keySet()
        ) {
            conflictCharacteristicList.removeAll(resultMap.get(key).keySet());
            conflictCharacteristicList.addAll(resultMap.get(key).keySet());
        }

        //深度排查可选，入参为aryData, aryResult, r3Code, r3VCode, cvDty
        List<String> deepConflictCharacteristics = variantTableService.deepConflictAnalysis(variantTableDOMap,
                resultMap, characteristicName, characteristicValueName, selectedCharacteristicMap, conflictCharacteristicList);

        conflictCharacteristicList.removeAll(deepConflictCharacteristics);
        conflictCharacteristicList.addAll(deepConflictCharacteristics);

        deepConflictCharacteristics = variantTableService.deepConflictAnalysis(variantTableDOMap,
                resultMap, characteristicName, characteristicValueName, selectedCharacteristicMap, conflictCharacteristicList);

        conflictCharacteristicList.removeAll(deepConflictCharacteristics);
        conflictCharacteristicList.addAll(deepConflictCharacteristics);

        conflictAnalysisOutputDTO.setMustSelectionResult(true);
        conflictAnalysisOutputDTO.setConflictCharacteristicList(conflictCharacteristicList.stream().distinct().collect(Collectors.toList()));
        conflictAnalysisOutputDTO.setSelectedCharacteristicList(conflictAnalysisInputDTO.getSelectedCharacteristicList().stream().map(
                inputSelectedCharacteristicListBean -> {
                    ConflictAnalysisOutputDTO.SelectedCharacteristicListBean outputSelectedCharacteristicListBean = new ConflictAnalysisOutputDTO.SelectedCharacteristicListBean();

                    outputSelectedCharacteristicListBean.setCharacteristicName(inputSelectedCharacteristicListBean.getCharacteristicName());
                    outputSelectedCharacteristicListBean.setCharacteristicValueName(inputSelectedCharacteristicListBean.getCharacteristicValueName());
                    //todo zjw修改 新增备注、数量C值
                    outputSelectedCharacteristicListBean.setQuantity(inputSelectedCharacteristicListBean.getQuantity());
                    outputSelectedCharacteristicListBean.setDesc(inputSelectedCharacteristicListBean.getDesc());

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

        if (conflictAnalysisInputDTO.getMustSelection()) {
            //移除冲突的特征
            conflictAnalysisOutputDTO.getSelectedCharacteristicList().removeIf(selectedCharacteristicListBean ->
                    conflictCharacteristicList.contains(selectedCharacteristicListBean.getCharacteristicName())
                    || selectedCharacteristicListBean.getCharacteristicName().equals(conflictAnalysisInputDTO.getCharacteristicName()));

            selectedCharacteristicMap.clear();

            //从头开始选一下，降低强选失败的概率
            PreVerifyOutputDTO preVerifyOutputDTO = variantTableService.preVerify(totalCharacteristicList,
                    selectedCharacteristicMap,
                    buildPreVerifyInputDTO(conflictAnalysisInputDTO.getProductGroupCode(),
                            conflictAnalysisInputDTO.getMaterialCode(),
                            conflictAnalysisInputDTO.getOperator(),
                            conflictAnalysisInputDTO.getCharacteristicName(),
                            conflictAnalysisInputDTO.getCharacteristicValueName(),
                            conflictAnalysisInputDTO.getSessionId(),
                            new ArrayList<>()
                    ));

            //todo 检查为空的特征，将其参与的vt的特征都重置，并且把捆绑的宿主特征也重置
            /*removeRelationCharacteristicByEmptyActiveCharacteristic(token, bomCode, division,
                    tellMeWhyOutputDTO.getSelectedCharacteristicList(),
                    preValidationOutputV2DTO.getActiveValues(), dataSourceFlag);*/

            //
            Map<String, List<String>> activeCharacteristicValues = preVerifyOutputDTO.getActiveValues().stream().collect(Collectors.toMap(
                    PreVerifyOutputDTO.ActiveValuesBean::getCharacteristicName, PreVerifyOutputDTO.ActiveValuesBean::getValues
            ));

            conflictAnalysisOutputDTO.getSelectedCharacteristicList().removeIf(selectedCharacteristicListBean ->
                    activeCharacteristicValues.containsKey(selectedCharacteristicListBean.getCharacteristicName())
                            && !activeCharacteristicValues.get(selectedCharacteristicListBean.getCharacteristicName()).contains(selectedCharacteristicListBean.getCharacteristicValueName())
            );

            List<PreVerifyInputDTO.SelectedCharacteristicListBean> selectedCharacteristicListBeans = conflictAnalysisOutputDTO.getSelectedCharacteristicList().stream().map(
                    loopSelectedCharacteristicListBean -> {
                        PreVerifyInputDTO.SelectedCharacteristicListBean selectedCharacteristicListBean = new PreVerifyInputDTO.SelectedCharacteristicListBean();

                        selectedCharacteristicListBean.setCharacteristicName(loopSelectedCharacteristicListBean.getCharacteristicName());
                        selectedCharacteristicListBean.setCharacteristicValueName(loopSelectedCharacteristicListBean.getCharacteristicValueName());
                        //todo zjw修改 新增备注、数量C值
                        selectedCharacteristicListBean.setQuantity(loopSelectedCharacteristicListBean.getQuantity());
                        selectedCharacteristicListBean.setDesc(loopSelectedCharacteristicListBean.getDesc());

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

            conflictAnalysisOutputDTO.getSelectedCharacteristicList().forEach(selectedCharacteristicListBean ->
                    selectedCharacteristicMap.put(selectedCharacteristicListBean.getCharacteristicName(),
                            selectedCharacteristicListBean.getCharacteristicValueName()));

            preVerifyOutputDTO = variantTableService.preVerify(totalCharacteristicList,
                    selectedCharacteristicMap,
                    buildPreVerifyInputDTO(conflictAnalysisInputDTO.getProductGroupCode(),
                            conflictAnalysisInputDTO.getMaterialCode(),
                            conflictAnalysisInputDTO.getOperator(),
                            conflictAnalysisInputDTO.getCharacteristicName(),
                            conflictAnalysisInputDTO.getCharacteristicValueName(),
                            conflictAnalysisInputDTO.getSessionId(),
                            selectedCharacteristicListBeans
                    ));

            conflictAnalysisOutputDTO.setActiveValues(preVerifyOutputDTO.getActiveValues().stream().map(loopActiveValuesBean -> {
                ConflictAnalysisOutputDTO.ActiveValuesBean activeValuesBean = new ConflictAnalysisOutputDTO.ActiveValuesBean();

                activeValuesBean.setCharacteristicName(loopActiveValuesBean.getCharacteristicName());
                activeValuesBean.setValues(loopActiveValuesBean.getValues());

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

            conflictAnalysisOutputDTO.setMustSelectionResult(preVerifyOutputDTO.getResult());

            //假如不通过，进一步做间接关联验证
            if(!preVerifyOutputDTO.getResult())
            {
                List<String> deepIndirectConflictCharacteristics = variantTableService.deepIndirectConflictAnalysis(variantTableDOMap, preVerifyOutputDTO.getConflictingCharacteristicList(), 1);
                List<String> finalDeepIndirectConflictCharacteristics = deepIndirectConflictCharacteristics.stream().distinct().collect(Collectors.toList());

                //移除冲突的特征
                conflictAnalysisOutputDTO.getSelectedCharacteristicList().removeIf(selectedCharacteristicListBean ->
                        finalDeepIndirectConflictCharacteristics.contains(selectedCharacteristicListBean.getCharacteristicName()));

                selectedCharacteristicMap.clear();
                conflictAnalysisOutputDTO.getSelectedCharacteristicList().forEach(selectedCharacteristicListBean ->
                        selectedCharacteristicMap.put(selectedCharacteristicListBean.getCharacteristicName(),
                                selectedCharacteristicListBean.getCharacteristicValueName()));

                preVerifyOutputDTO = variantTableService.preVerify(totalCharacteristicList,
                        selectedCharacteristicMap,
                        buildPreVerifyInputDTO(conflictAnalysisInputDTO.getProductGroupCode(),
                                conflictAnalysisInputDTO.getMaterialCode(),
                                conflictAnalysisInputDTO.getOperator(),
                                conflictAnalysisInputDTO.getCharacteristicName(),
                                conflictAnalysisInputDTO.getCharacteristicValueName(),
                                conflictAnalysisInputDTO.getSessionId(),
                                selectedCharacteristicListBeans
                        ));

                conflictAnalysisOutputDTO.setActiveValues(preVerifyOutputDTO.getActiveValues().stream().map(loopActiveValuesBean -> {
                    ConflictAnalysisOutputDTO.ActiveValuesBean activeValuesBean = new ConflictAnalysisOutputDTO.ActiveValuesBean();

                    activeValuesBean.setCharacteristicName(loopActiveValuesBean.getCharacteristicName());
                    activeValuesBean.setValues(loopActiveValuesBean.getValues());

                    return activeValuesBean;
                }).collect(Collectors.toList()));
                conflictAnalysisOutputDTO.setMustSelectionResult(preVerifyOutputDTO.getResult());
            }
        }

        return conflictAnalysisOutputDTO;
    }
}
