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

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.constant.ElevatorParamCodeConstants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.QuotationUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.jep.JEPUtils;
import com.ruoyi.project.business.domain.TpAreaBasicPrice;
import com.ruoyi.project.business.domain.TpAreaBasicPriceRelatedPara;
import com.ruoyi.project.business.domain.TqPriceDetail;
import com.ruoyi.project.business.domain.bo.quotation.ElevatorAddBO;
import com.ruoyi.project.business.domain.dto.QuotationDTO;
import com.ruoyi.project.business.dto.TpAreaOptionalDTO;
import com.ruoyi.project.business.enums.AccessTypeEnum;
import com.ruoyi.project.business.enums.DelFlagEnum;
import com.ruoyi.project.business.enums.InputTypeEnum;
import com.ruoyi.project.business.enums.JEPSplitEnum;
import com.ruoyi.project.business.enums.QuotationEnum;
import com.ruoyi.project.business.enums.StatusEnum;
import com.ruoyi.project.business.enums.SystemCheckResultEnum;
import com.ruoyi.project.business.service.ITpAreaBasicPriceRelatedParaService;
import com.ruoyi.project.business.service.ITpAreaBasicPriceService;
import com.ruoyi.project.business.service.ITpAreaOptionalParaPriceService;
import com.ruoyi.project.business.service.quotation.IPriceCalcService;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

// 报价价格计算
@Service
@Slf4j
public class PriceCalcServiceImpl implements IPriceCalcService {

    public static final String ALL = "all";

    public static final String TILDE = "~";

    public static final String SPLIT = ";";

    public static final String COLON = ":";

    public static final String PAUSE = "、";

    public static final BigDecimal ILLEGAL_PRICE = new BigDecimal(-1);

    public static final String FLOORS_PRICE = "层数差价";

    public static final String LANDS_UNIT = "层";

    public static final String UNIT = "项";

    public static final String BASIC_PRICE = "基础价格";

    public static final String SPACE = " ";

    @Resource
    private ITpAreaOptionalParaPriceService tpAreaOptionalParaPriceService;

    @Resource
    private ITpAreaBasicPriceService tpAreaBasicPriceService;

    @Resource
    private ITpAreaBasicPriceRelatedParaService tpAreaBasicPriceRelatedParaService;


    @Override
    public Long calculateBasicPrice(ElevatorAddBO elevator, List<TqPriceDetail> tqPriceDetailList) {
        Long basicPrice;
        QuotationDTO quotationData = QuotationUtil.getQuotationData();
        Map<String, String> paramMap = quotationData.getParamCodeValueMap();
        Map<String, String> codeLabel = quotationData.getParamCodeLabelMap();
        Map<String, String> codeValue = quotationData.getParamCodeValueMap();

        TpAreaBasicPrice tpAreaBasicPrice = null;

        // 获取基价配置参数
        List<TpAreaBasicPriceRelatedPara> configList = tpAreaBasicPriceRelatedParaService.list(
            Wrappers.<TpAreaBasicPriceRelatedPara>lambdaQuery()
                .eq(TpAreaBasicPriceRelatedPara::getElevatorModelId, elevator.getElevatorModelId())
                .eq(TpAreaBasicPriceRelatedPara::getDelFlag, DelFlagEnum.NORMAL.getValue()));
        if (CollUtil.isEmpty(configList)) {
            throw new ServiceException("基价配置参数不存在");
        }
        TpAreaBasicPriceRelatedPara config = configList.get(0);

        // 获取基价配置参数值
        List<TpAreaBasicPrice> valueList = tpAreaBasicPriceService.list(
            Wrappers.<TpAreaBasicPrice>lambdaQuery()
                .eq(TpAreaBasicPrice::getElevatorModelId, elevator.getElevatorModelId())
                // 删除标记
                .eq(TpAreaBasicPrice::getDelFlag, DelFlagEnum.NORMAL.getValue()));

        log.info("基价配置 [{}] 配置CODE [{}] [{}] [{}] [{}] [{}]",
            config.getId(), config.getRelatedParaCode1(),
            config.getRelatedParaCode2(), config.getRelatedParaCode3(),
            config.getRelatedParaCode4(), config.getRelatedParaCode5());
        log.info("基价配置 [{}] 参数名称 [{}] [{}] [{}] [{}] [{}]", config.getId(),
            codeLabel.get(config.getRelatedParaCode1()),
            codeLabel.get(config.getRelatedParaCode2()),
            codeLabel.get(config.getRelatedParaCode3()),
            codeLabel.get(config.getRelatedParaCode4()),
            codeLabel.get(config.getRelatedParaCode5()));
        log.info("基价配置 [{}] 页面参数 [{}] [{}] [{}] [{}] [{}]", config.getId(),
            codeValue.get(config.getRelatedParaCode1()),
            codeValue.get(config.getRelatedParaCode2()),
            codeValue.get(config.getRelatedParaCode3()),
            codeValue.get(config.getRelatedParaCode4()),
            codeValue.get(config.getRelatedParaCode5()));

        for (TpAreaBasicPrice value : valueList) {
            boolean para1Valid = compareParamValue(value.getRelatedPara1(), config.getRelatedParaCode1(), codeValue);
            boolean para2Valid = compareParamValue(value.getRelatedPara2(), config.getRelatedParaCode2(), codeValue);
            boolean para3Valid = compareParamValue(value.getRelatedPara3(), config.getRelatedParaCode3(), codeValue);
            boolean para4Valid = compareParamValue(value.getRelatedPara4(), config.getRelatedParaCode4(), codeValue);
            boolean para5Valid = compareParamValue(value.getRelatedPara5(), config.getRelatedParaCode5(), codeValue);
            log.info("基价配置 [{}] 配置结果 [{}] [{}] [{}] [{}] [{}]", value.getId(), value.getRelatedPara1(),
                value.getRelatedPara2(), value.getRelatedPara3(),
                value.getRelatedPara4(), value.getRelatedPara5());
            log.info("基价配置 [{}] 结果参数 [{}] [{}] [{}] [{}] [{}]", value.getId(), para1Valid, para2Valid,
                para3Valid,
                para4Valid, para5Valid);
            if (para1Valid && para2Valid && para3Valid && para4Valid && para5Valid) {
                tpAreaBasicPrice = value;
                break;
            }
        }

        if (Objects.isNull(tpAreaBasicPrice)) {
            throw new ServiceException("基价配置参数值不存在");
        }

        basicPrice = tpAreaBasicPrice.getBasicPrice();
        // 根据层数加/减价
        Long actualFloors = Long.valueOf(paramMap.get(ElevatorParamCodeConstants.LANDS));
        Long diffFloors = actualFloors - tpAreaBasicPrice.getStandardFloors();
        // 基础价格放到价格明细
        TqPriceDetail basicPriceDetail = new TqPriceDetail();
        basicPriceDetail.setMarkupName(BASIC_PRICE);
        basicPriceDetail.setRelatedParaInfo(getBasicInfo(paramMap, codeLabel, config));
        basicPriceDetail.setUnit(UNIT);
        basicPriceDetail.setQuantity(new BigDecimal(1L));
        basicPriceDetail.setPrice(new BigDecimal(basicPrice));
        basicPriceDetail.setTotal(new BigDecimal(basicPrice));
        basicPriceDetail.setSystemCheckResult(SystemCheckResultEnum.STANDARD.getCode());
        basicPriceDetail.setDelFlag(DelFlagEnum.NORMAL.getValue());
        basicPriceDetail.setCreateBy(SecurityUtils.getStrUserId());
        basicPriceDetail.setCreateTime(DateUtils.getNowDate());
        basicPriceDetail.setUpdateBy(SecurityUtils.getStrUserId());
        basicPriceDetail.setUpdateTime(DateUtils.getNowDate());
        tqPriceDetailList.add(basicPriceDetail);

        // 计算层站数差价
        if (diffFloors != 0) {
            TqPriceDetail priceDetail = new TqPriceDetail();
            priceDetail.setMarkupName(FLOORS_PRICE);
            String info = codeLabel.getOrDefault(ElevatorParamCodeConstants.LANDS, "")
                + COLON
                + actualFloors;
            priceDetail.setRelatedParaInfo(info);
            priceDetail.setUnit(LANDS_UNIT);
            // 获取数量
            priceDetail.setQuantity(new BigDecimal(diffFloors));
            // 获取单价
            if (diffFloors > 0) {
                priceDetail.setPrice(new BigDecimal(tpAreaBasicPrice.getAddOnefloorPrice()));
            } else {
                priceDetail.setPrice(new BigDecimal(tpAreaBasicPrice.getSubtractOnefloorPrice()));
            }
            priceDetail.setTotal(priceDetail.getPrice().multiply(priceDetail.getQuantity()));
            priceDetail.setSystemCheckResult(SystemCheckResultEnum.STANDARD.getCode());
            priceDetail.setDelFlag(DelFlagEnum.NORMAL.getValue());
            priceDetail.setCreateBy(SecurityUtils.getStrUserId());
            priceDetail.setCreateTime(DateUtils.getNowDate());
            priceDetail.setUpdateBy(SecurityUtils.getStrUserId());
            priceDetail.setUpdateTime(DateUtils.getNowDate());
            tqPriceDetailList.add(priceDetail);
        }
        return basicPrice;
    }


    private boolean compareParamValue(String configValue, String configCode, Map<String, String> paramMap) {
        if (StringUtils.isBlank(configCode)) {
            return true;
        }
        String paramValue = paramMap.get(configCode);
        // 配置参数为空
        if (StringUtils.isAnyBlank(configValue, paramValue)) {
            return false;
        }
        // case 1：配置为all，则返回true
        if (ALL.equalsIgnoreCase(configValue)) {
            return true;
        }
        // case 2：配置有 ~ ，判断是否在区间内
        if (configValue.contains(TILDE)) {
            try {
                String[] configValueArray = configValue.split(TILDE);
                BigDecimal leftValue = new BigDecimal(configValueArray[0]);
                BigDecimal rightValue = new BigDecimal(configValueArray[1]);
                BigDecimal cValue = new BigDecimal(paramValue);
                return leftValue.compareTo(cValue) <= 0 && rightValue.compareTo(cValue) >= 0;
            } catch (Exception e) {
                log.info("选配加价区间比较失败 配置参数[{}] 页面参数[{}]", configValue, paramValue);
                return false;
            }
        }
        // case 2：配置有 ; ，判断是否等于单个元素
        if (configValue.contains(SPLIT)) {
            return Arrays.stream(configValue.split(SPLIT)).anyMatch(item -> item.equals(paramValue));
        }
        return configValue.equals(paramValue);
    }

    private static String getBasicInfo(Map<String, String> paramMap, Map<String, String> paramCodeLabelMap,
        TpAreaBasicPriceRelatedPara config) {
        StringBuilder info = new StringBuilder();
        if (StringUtils.isNotBlank(config.getRelatedParaCode1())) {
            info.append(paramCodeLabelMap.getOrDefault(config.getRelatedParaCode1(), ""));
            info.append(COLON);
            info.append(paramMap.getOrDefault(config.getRelatedParaCode1(), ""));
        }
        if (StringUtils.isNotBlank(config.getRelatedParaCode2())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.getOrDefault(config.getRelatedParaCode2(), ""));
            info.append(COLON);
            info.append(paramMap.getOrDefault(config.getRelatedParaCode2(), ""));
        }
        if (StringUtils.isNotBlank(config.getRelatedParaCode3())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.getOrDefault(config.getRelatedParaCode3(), ""));
            info.append(COLON);
            info.append(paramMap.getOrDefault(config.getRelatedParaCode3(), ""));
        }
        if (StringUtils.isNotBlank(config.getRelatedParaCode4())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.getOrDefault(config.getRelatedParaCode4(), ""));
            info.append(COLON);
            info.append(paramMap.getOrDefault(config.getRelatedParaCode4(), ""));
        }
        if (StringUtils.isNotBlank(config.getRelatedParaCode5())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.getOrDefault(config.getRelatedParaCode5(), ""));
            info.append(COLON);
            info.append(paramMap.getOrDefault(config.getRelatedParaCode5(), ""));
        }
        return info.toString();
    }

    @Override
    public void statisticsOptionalPrice(ElevatorAddBO elevator, List<TqPriceDetail> result) {
        QuotationDTO quotationData = QuotationUtil.getQuotationData();
        Map<String, String> paramCodeValueMap = quotationData.getParamCodeValueMap();
        Map<String, Object> paramCodeCalculateValueMap = quotationData.getParamCodeCalculateValueMap();
        Map<String, String> paramCodeInputTypeMap = quotationData.getParamCodeInputTypeMap();
        Map<String, String> paramCodeLabelMap = quotationData.getParamCodeLabelMap();

        Long elevatorModelId = elevator.getElevatorModelId();
        // 查询所有选配价格
        List<TpAreaOptionalDTO> tpAreaOptionalDTOS = tpAreaOptionalParaPriceService
            .listAllOptionParamInfoByElevatorModelId(elevatorModelId);
        if (CollUtil.isEmpty(tpAreaOptionalDTOS)) {
            return;
        }
        // 按顺序获取加价项目
        List<String> markupNameList = tpAreaOptionalDTOS.stream().map(TpAreaOptionalDTO::getMarkupName).distinct()
            .collect(Collectors.toList());
        Map<String, List<TpAreaOptionalDTO>> optionMap = tpAreaOptionalDTOS.stream()
            .collect(Collectors.groupingBy(TpAreaOptionalDTO::getMarkupName));
        TpAreaOptionalDTO nonstandardOption = null;
        for (String markupName : markupNameList) {
            // 之前的加价项目，当做参数(设置默认值)
            paramCodeCalculateValueMap.put(
                JEPSplitEnum.PARAM_SPLIT_FLAG.getFuncKey()
                    + markupName
                    + JEPSplitEnum.PARAM_SPLIT_FLAG.getFuncKey(),
                BigDecimal.ZERO.toPlainString());
            paramCodeInputTypeMap.put(JEPSplitEnum.PARAM_SPLIT_FLAG.getFuncKey()
                + markupName
                + JEPSplitEnum.PARAM_SPLIT_FLAG.getFuncKey(), InputTypeEnum.INPUT_NUMBER.getCode());

            List<TpAreaOptionalDTO> itemOptionList = optionMap.getOrDefault(markupName, new ArrayList<>());
            BigDecimal quantity = BigDecimal.ONE;
            // 理由
            String reason = "价格表不存在";
            // 是否非标
            boolean isNonstandard = true;
            // 是否跳过加价项目
            boolean isSkip = false;
            // 匹配每个加价项目
            for (TpAreaOptionalDTO tpAreaOptionalDTO : itemOptionList) {

                String configCode = tpAreaOptionalDTO.getParaCode();
                String configValue = tpAreaOptionalDTO.getParaValue();
                nonstandardOption = tpAreaOptionalDTO;

                if (StatusEnum.DISABLE.getCode().equals(tpAreaOptionalDTO.getOptionStatus())) {
                    isSkip = true;
                }

                boolean paramResult = compareParamValue(configValue, configCode, paramCodeValueMap);
                if (!paramResult) {
                    if (StringUtils.isNotBlank(configCode) && StringUtils.isBlank(paramCodeValueMap.get(configCode))) {
                        isSkip = true;
                        break;
                    }
                    // 选配关联参数都不对，不用看其他关联参数
                    continue;
                }

                // 配置1不匹配
                if (!compareParamValue(
                    tpAreaOptionalDTO.getRelatedParaValue1(), tpAreaOptionalDTO.getRelatedParaCode1(),
                    paramCodeValueMap)) {
                    if (StringUtils.isNotBlank(tpAreaOptionalDTO.getRelatedParaCode1())
                        && StringUtils.isBlank(paramCodeValueMap.get(tpAreaOptionalDTO.getRelatedParaCode1()))) {
                        isSkip = true;
                        break;
                    }
                    continue;
                }
                // 配置2不匹配
                if (!compareParamValue(
                    tpAreaOptionalDTO.getRelatedParaValue2(), tpAreaOptionalDTO.getRelatedParaCode2(),
                    paramCodeValueMap)) {
                    if (StringUtils.isNotBlank(tpAreaOptionalDTO.getRelatedParaCode2())
                        && StringUtils.isBlank(paramCodeValueMap.get(tpAreaOptionalDTO.getRelatedParaCode2()))) {
                        isSkip = true;
                        break;
                    }
                    continue;
                }
                // 配置3不匹配
                if (!compareParamValue(
                    tpAreaOptionalDTO.getRelatedParaValue3(), tpAreaOptionalDTO.getRelatedParaCode3(),
                    paramCodeValueMap)) {
                    if (StringUtils.isNotBlank(tpAreaOptionalDTO.getRelatedParaCode3())
                        && StringUtils.isBlank(paramCodeValueMap.get(tpAreaOptionalDTO.getRelatedParaCode3()))) {
                        isSkip = true;
                        break;
                    }
                    continue;
                }
                // 配置4不匹配
                if (!compareParamValue(
                    tpAreaOptionalDTO.getRelatedParaValue4(), tpAreaOptionalDTO.getRelatedParaCode4(),
                    paramCodeValueMap)) {
                    if (StringUtils.isNotBlank(tpAreaOptionalDTO.getRelatedParaCode4())
                        && StringUtils.isBlank(paramCodeValueMap.get(tpAreaOptionalDTO.getRelatedParaCode4()))) {
                        isSkip = true;
                        break;
                    }
                    continue;
                }
                // 配置5不匹配
                if (!compareParamValue(
                    tpAreaOptionalDTO.getRelatedParaValue5(), tpAreaOptionalDTO.getRelatedParaCode5(),
                    paramCodeValueMap)) {
                    if (StringUtils.isNotBlank(tpAreaOptionalDTO.getRelatedParaCode5())
                        && StringUtils.isBlank(paramCodeValueMap.get(tpAreaOptionalDTO.getRelatedParaCode5()))) {
                        isSkip = true;
                        break;
                    }
                    continue;
                }
                // 配置6不匹配
                if (!compareParamValue(
                    tpAreaOptionalDTO.getRelatedParaValue6(), tpAreaOptionalDTO.getRelatedParaCode6(),
                    paramCodeValueMap)) {
                    if (StringUtils.isNotBlank(tpAreaOptionalDTO.getRelatedParaCode6())
                        && StringUtils.isBlank(paramCodeValueMap.get(tpAreaOptionalDTO.getRelatedParaCode6()))) {
                        isSkip = true;
                        break;
                    }
                    continue;
                }
                // 配置7不匹配
                if (!compareParamValue(
                    tpAreaOptionalDTO.getRelatedParaValue7(), tpAreaOptionalDTO.getRelatedParaCode7(),
                    paramCodeValueMap)) {
                    if (StringUtils.isNotBlank(tpAreaOptionalDTO.getRelatedParaCode7())
                        && StringUtils.isBlank(paramCodeValueMap.get(tpAreaOptionalDTO.getRelatedParaCode7()))) {
                        isSkip = true;
                        break;
                    }
                    continue;
                }
                // 配置8不匹配
                if (!compareParamValue(
                    tpAreaOptionalDTO.getRelatedParaValue8(), tpAreaOptionalDTO.getRelatedParaCode8(),
                    paramCodeValueMap)) {
                    if (StringUtils.isNotBlank(tpAreaOptionalDTO.getRelatedParaCode8())
                        && StringUtils.isBlank(paramCodeValueMap.get(tpAreaOptionalDTO.getRelatedParaCode8()))) {
                        isSkip = true;
                        break;
                    }
                    continue;
                }
                // 配置9不匹配
                if (!compareParamValue(
                    tpAreaOptionalDTO.getRelatedParaValue9(), tpAreaOptionalDTO.getRelatedParaCode9(),
                    paramCodeValueMap)) {
                    if (StringUtils.isNotBlank(tpAreaOptionalDTO.getRelatedParaCode9())
                        && StringUtils.isBlank(paramCodeValueMap.get(tpAreaOptionalDTO.getRelatedParaCode9()))) {
                        isSkip = true;
                        break;
                    }
                    continue;
                }
                // 配置10不匹配
                if (!compareParamValue(
                    tpAreaOptionalDTO.getRelatedParaValue10(), tpAreaOptionalDTO.getRelatedParaCode10(),
                    paramCodeValueMap)) {
                    if (StringUtils.isNotBlank(tpAreaOptionalDTO.getRelatedParaCode10())
                        && StringUtils.isBlank(paramCodeValueMap.get(tpAreaOptionalDTO.getRelatedParaCode10()))) {
                        isSkip = true;
                        break;
                    }
                    continue;
                }

                isNonstandard = false;
                // 标准加价明细
                TqPriceDetail priceDetail = new TqPriceDetail();
                priceDetail.setMarkupKey(tpAreaOptionalDTO.getMarkupKey());
                priceDetail.setMarkupName(tpAreaOptionalDTO.getMarkupName());
                priceDetail.setRelatedParaInfo(
                    getRelatedParaInfo(tpAreaOptionalDTO, paramCodeLabelMap, paramCodeValueMap));
                priceDetail.setUnit(tpAreaOptionalDTO.getQuantityUnit());
                StringBuilder errorInfo = new StringBuilder();
                // 获取数量
                if (AccessTypeEnum.FIXED.getCode().equals(tpAreaOptionalDTO.getQuantityType())) {
                    priceDetail.setQuantity(tpAreaOptionalDTO.getQuantity());
                } else {
                    try {
                        String quantityFormula = tpAreaOptionalDTO.getQuantityFormula();
                        Map<String, Object> calculate = JEPUtils.calculate(quantityFormula,
                            paramCodeCalculateValueMap, paramCodeInputTypeMap, true);
                        String calculateValue = String.valueOf(calculate.get(JEPUtils.CALCULATE_VALUE));
                        priceDetail.setQuantity(new BigDecimal(calculateValue));
                    } catch (Exception e) {
                        // throw new ServiceException(
                        //     MessageUtils.message("quotation.quantity.formula.error", quantityFormulaTxt));
                        log.info("电梯型号 [{}] 加价项目 [{}] 数量公式计算异常 [{}]", elevator.getElevatorModel(),
                            tpAreaOptionalDTO.getMarkupName(), tpAreaOptionalDTO.getQuantityFormulaTxt());
                        log.error("", e);
                        errorInfo.append("数量公式计算异常");
                    }
                }
                quantity = priceDetail.getQuantity();
                // 获取单价
                if (AccessTypeEnum.FIXED.getCode().equals(tpAreaOptionalDTO.getPriceType())) {
                    priceDetail.setPrice(tpAreaOptionalDTO.getPrice());
                } else {
                    try {
                        String priceFormula = tpAreaOptionalDTO.getPriceFormula();
                        Map<String, Object> calculate = JEPUtils.calculate(priceFormula,
                            paramCodeCalculateValueMap, paramCodeInputTypeMap, true);
                        String calculateValue = String.valueOf(calculate.get(JEPUtils.CALCULATE_VALUE));
                        // 单价取整
                        BigDecimal decimal = new BigDecimal(calculateValue).setScale(0, RoundingMode.DOWN);
                        priceDetail.setPrice(decimal);
                    } catch (Exception e) {
                        // throw new ServiceException(
                        //     MessageUtils.message("quotation.price.formula.error", priceFormulaTxt));
                        log.info("电梯型号 [{}] 加价项目 [{}] 价格公式计算异常 [{}]", elevator.getElevatorModel(),
                            tpAreaOptionalDTO.getMarkupName(), tpAreaOptionalDTO.getPriceFormulaTxt());
                        log.error("", e);
                        errorInfo.append("价格公式计算异常");
                    }
                }

                // 之前的加价项目，当做参数
                BigDecimal price = Optional.ofNullable(priceDetail.getPrice()).orElse(BigDecimal.ZERO);
                paramCodeCalculateValueMap.put(
                    JEPSplitEnum.PARAM_SPLIT_FLAG.getFuncKey()
                        + tpAreaOptionalDTO.getMarkupName()
                        + JEPSplitEnum.PARAM_SPLIT_FLAG.getFuncKey(),
                    price.toPlainString());
                paramCodeInputTypeMap.put(JEPSplitEnum.PARAM_SPLIT_FLAG.getFuncKey()
                    + tpAreaOptionalDTO.getMarkupName()
                    + JEPSplitEnum.PARAM_SPLIT_FLAG.getFuncKey(), InputTypeEnum.INPUT_NUMBER.getCode());

                // 非法价格固定值或者公式计算結果是 -1 为非标价格
                if (Objects.isNull(priceDetail.getPrice())
                    || Objects.isNull(priceDetail.getQuantity())
                    || ILLEGAL_PRICE.compareTo(priceDetail.getPrice()) == 0) {
                    reason = "非标价格";
                    if (errorInfo.length() > 0) {
                        reason += " ,";
                        reason += errorInfo;
                    }
                    isNonstandard = true;
                    break;
                }
                BigDecimal total = priceDetail.getPrice().multiply(priceDetail.getQuantity());
                priceDetail.setTotal(total.setScale(0, RoundingMode.DOWN));
                priceDetail.setSystemCheckResult(SystemCheckResultEnum.STANDARD.getCode());
                priceDetail.setDelFlag(DelFlagEnum.NORMAL.getValue());
                priceDetail.setCreateBy(SecurityUtils.getStrUserId());
                priceDetail.setCreateTime(DateUtils.getNowDate());
                priceDetail.setUpdateBy(SecurityUtils.getStrUserId());
                priceDetail.setUpdateTime(DateUtils.getNowDate());
                if (StatusEnum.ENABLE.getCode().equals(tpAreaOptionalDTO.getOptionStatus())) {
                    result.add(priceDetail);
                } else {
                    isSkip = true;
                }
                break;
            }
            // 跳过加价项目
            if (isSkip) {
                continue;
            }
            // 非标加价明细
            if (isNonstandard) {
                TqPriceDetail priceDetail = new TqPriceDetail();
                priceDetail.setMarkupName(markupName);
                priceDetail.setNonStandardReason(reason);
                if (Objects.nonNull(nonstandardOption)) {
                    priceDetail.setRelatedParaInfo(
                        getRelatedParaInfo(nonstandardOption, paramCodeLabelMap, paramCodeValueMap));
                }
                if (Objects.nonNull(quantity) && quantity.compareTo(BigDecimal.ONE) > 0) {
                    priceDetail.setQuantity(quantity);
                } else {
                    priceDetail.setQuantity(new BigDecimal(1L));
                }
                priceDetail.setUnit(UNIT);
                priceDetail.setSystemCheckResult(SystemCheckResultEnum.OFF_STANDARD.getCode());
                priceDetail.setDelFlag(DelFlagEnum.NORMAL.getValue());
                priceDetail.setQuotationFlagMachine(QuotationEnum.NO.getValue());
                priceDetail.setQuotationFlagElectric(QuotationEnum.NO.getValue());
                priceDetail.setCreateBy(SecurityUtils.getStrUserId());
                priceDetail.setCreateTime(DateUtils.getNowDate());
                priceDetail.setUpdateBy(SecurityUtils.getStrUserId());
                priceDetail.setUpdateTime(DateUtils.getNowDate());
                result.add(priceDetail);
            }
        }
    }

    @Override
    public BigDecimal calculateAgentDiscount(ElevatorAddBO elevator, String formula) {
        QuotationDTO quotationData = QuotationUtil.getQuotationData();
        Map<String, Object> paramCodeCalculateValueMap = quotationData.getParamCodeCalculateValueMap();
        Map<String, String> paramCodeInputTypeMap = quotationData.getParamCodeInputTypeMap();

        try {
            Map<String, Object> calculate = JEPUtils.calculate(formula,
                    paramCodeCalculateValueMap, paramCodeInputTypeMap, true);
            String calculateValue = String.valueOf(calculate.get(JEPUtils.CALCULATE_VALUE));
            return new BigDecimal(calculateValue);
        } catch (Exception e) {
            log.info("代理商折率计算错误");
        }
        return null;
    }

    private String getRelatedParaInfo(TpAreaOptionalDTO tpAreaOptional, Map<String, String> paramCodeLabelMap,
                                      Map<String, String> paramCodeValueMap) {
        StringBuilder info = new StringBuilder();
        if (StringUtils.isNotBlank(tpAreaOptional.getParaCode())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getParaCode()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getParaCode())).orElse(SPACE);
            info.append(value);
        }
        if (StringUtils.isNotBlank(tpAreaOptional.getRelatedParaCode1())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getRelatedParaCode1()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getRelatedParaCode1()))
                .orElse(SPACE);
            info.append(value);
        }
        if (StringUtils.isNotBlank(tpAreaOptional.getRelatedParaCode2())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getRelatedParaCode2()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getRelatedParaCode2()))
                .orElse(SPACE);
            info.append(value);
        }
        if (StringUtils.isNotBlank(tpAreaOptional.getRelatedParaCode3())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getRelatedParaCode3()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getRelatedParaCode3()))
                .orElse(SPACE);
            info.append(value);
        }
        if (StringUtils.isNotBlank(tpAreaOptional.getRelatedParaCode4())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getRelatedParaCode4()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getRelatedParaCode4()))
                .orElse(SPACE);
            info.append(value);
        }
        if (StringUtils.isNotBlank(tpAreaOptional.getRelatedParaCode5())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getRelatedParaCode5()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getRelatedParaCode5()))
                .orElse(SPACE);
            info.append(value);
        }
        if (StringUtils.isNotBlank(tpAreaOptional.getRelatedParaCode6())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getRelatedParaCode6()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getRelatedParaCode6()))
                .orElse(SPACE);
            info.append(value);
        }
        if (StringUtils.isNotBlank(tpAreaOptional.getRelatedParaCode7())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getRelatedParaCode7()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getRelatedParaCode7()))
                .orElse(SPACE);
            info.append(value);
        }
        if (StringUtils.isNotBlank(tpAreaOptional.getRelatedParaCode8())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getRelatedParaCode8()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getRelatedParaCode8()))
                .orElse(SPACE);
            info.append(value);
        }
        if (StringUtils.isNotBlank(tpAreaOptional.getRelatedParaCode9())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getRelatedParaCode9()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getRelatedParaCode9()))
                .orElse(SPACE);
            info.append(value);
        }
        if (StringUtils.isNotBlank(tpAreaOptional.getRelatedParaCode10())) {
            info.append(info.length() > 0 ? PAUSE : "");
            info.append(paramCodeLabelMap.get(tpAreaOptional.getRelatedParaCode10()));
            info.append(COLON);
            String value = Optional.ofNullable(paramCodeValueMap.get(tpAreaOptional.getRelatedParaCode10()))
                .orElse(SPACE);
            info.append(value);
        }
        return info.toString();
    }
}
