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

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ruoyi.common.enums.ValueType;
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.helper.PriceFormTableInfoHelper;
import com.ruoyi.common.importExcel.excel.tempInfo.PriceFormBasicInfoHelper;
import com.ruoyi.common.importExcel.excel.tempInfo.PriceFormOptionInfoHelper;
import com.ruoyi.common.importExcel.utils.ExcelUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.business.domain.*;
import com.ruoyi.project.business.enums.DelFlagEnum;
import com.ruoyi.project.business.enums.JEPFuncEnum;
import com.ruoyi.project.business.enums.JEPLogicEnum;
import com.ruoyi.project.business.mapper.TpAreaBasicPriceMapper;
import com.ruoyi.project.business.service.*;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import com.ruoyi.project.system.domain.SysDictData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import static com.ruoyi.common.utils.StringUtils.parseDecimal;
import static com.ruoyi.common.utils.StringUtils.parseLong;
import static java.lang.Long.valueOf;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.lang3.StringUtils.*;

/**
 * 【请填写功能名称】Service业务层处理
 *
 * @author ruoyi
 * @date 2024-05-20
 */
@Service
@Slf4j
public class TpAreaBasicPriceServiceImpl extends ServiceImpl<TpAreaBasicPriceMapper, TpAreaBasicPrice> implements
    ITpAreaBasicPriceService {

    @Resource
    private TpAreaBasicPriceMapper tpAreaBasicPriceMapper;

    @Resource
    private ITpAreaOptionalParaService tpAreaOptionalParaService;

    @Resource
    private ITpAreaOptionalParaPriceService tpAreaOptionalParaPriceService;

    @Resource
    private ITpParaLibraryService tpParaLibraryService;

    @Resource
    private ITpAreaElevatorModelParaService tpAreaElevatorModelParaService;

    @Resource
    private ITpAreaBasicPriceRelatedParaService tpAreaBasicPriceRelatedParaService;

    /**
     * 查询【请填写功能名称】
     *
     * @param id 【请填写功能名称】主键
     * @return 【请填写功能名称】
     */
    @Override
    public TpAreaBasicPrice selectTpAreaBasicPriceById(Long id) {
        return tpAreaBasicPriceMapper.selectById(id);
    }

    /**
     * 查询【请填写功能名称】列表
     *
     * @param tpAreaBasicPrice 【请填写功能名称】
     * @return 【请填写功能名称】
     */
    @Override
    public List<TpAreaBasicPrice> selectTpAreaBasicPriceList(TpAreaBasicPrice tpAreaBasicPrice) {
        List<TpAreaBasicPrice> list = tpAreaBasicPriceMapper.selectList(Wrappers.<TpAreaBasicPrice>lambdaQuery()
                .eq(TpAreaBasicPrice::getDelFlag, DelFlagEnum.NORMAL.getValue())
                .eq(TpAreaBasicPrice::getElevatorModelId, tpAreaBasicPrice.getElevatorModelId())
                .orderByAsc(TpAreaBasicPrice::getSortNumber));

        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean setParams(TpAreaBasicPrice tpAreaBasicPrice) {
        check(tpAreaBasicPrice);
        TpAreaBasicPriceRelatedPara relatedPara = new TpAreaBasicPriceRelatedPara();
        BeanUtils.copyProperties(tpAreaBasicPrice, relatedPara);
        tpAreaBasicPriceRelatedParaService.remove(Wrappers.<TpAreaBasicPriceRelatedPara>lambdaQuery()
                .eq(TpAreaBasicPriceRelatedPara::getElevatorModelId, tpAreaBasicPrice.getElevatorModelId()));

        return tpAreaBasicPriceRelatedParaService.save(relatedPara);
    }

    @Override
    public TpAreaBasicPriceRelatedPara getParams(Long elevatorId) {
        return  tpAreaBasicPriceRelatedParaService.getOne(Wrappers.<TpAreaBasicPriceRelatedPara>lambdaQuery()
                .eq(TpAreaBasicPriceRelatedPara::getElevatorModelId, elevatorId));
    }

    /**
     * 新增【请填写功能名称】
     *
     * @param tpAreaBasicPrice 【请填写功能名称】
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertTpAreaBasicPrice(TpAreaBasicPrice tpAreaBasicPrice) {
        tpAreaBasicPrice.setId(null);
        tpAreaBasicPrice.setCreateTime(DateUtils.getNowDate());
        return tpAreaBasicPriceMapper.insert(tpAreaBasicPrice);
    }

    private void check(TpAreaBasicPrice it) {
        List<String> params = Lists.newArrayList(it.getRelatedParaCode1(), it.getRelatedParaCode2(), it.getRelatedParaCode3(),
                it.getRelatedParaCode4(), it.getRelatedParaCode5()).stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
        if ((params.size() > params.stream().distinct().count())) {
            throw new ServiceException("关联参数不能重复");
        }
        if (Objects.isNull(it.getElevatorModelId())) {
            throw new ServiceException("关联梯型不能为空");
        }
    }

    /**
     * 修改【请填写功能名称】
     *
     * @param tpAreaBasicPrice 【请填写功能名称】
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateTpAreaBasicPrice(TpAreaBasicPrice tpAreaBasicPrice) {
        tpAreaBasicPrice.setUpdateTime(DateUtils.getNowDate());
        return tpAreaBasicPriceMapper.updateById(tpAreaBasicPrice);
    }

    /**
     * 批量删除【请填写功能名称】
     *
     * @param ids 需要删除的【请填写功能名称】主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteTpAreaBasicPriceByIds(Long[] ids) {
        if (CollectionUtils.isEmpty(listByIds(Arrays.asList(ids)))) {
            throw new ServiceException("数据不存在或已被删除，请刷新后重试");
        }
        return tpAreaBasicPriceMapper.deleteTpAreaBasicPriceByIds(ids);
    }

    /**
     * 删除【请填写功能名称】信息
     *
     * @param id 【请填写功能名称】主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteTpAreaBasicPriceById(Long id) {
        if (Objects.isNull(getById(id))) {
            throw new ServiceException("数据不存在或已被删除，请刷新后重试");
        }
        return tpAreaBasicPriceMapper.deleteById(id);
    }

    @Override
    public List<List<? extends BasicExcelHelper>> getPriceForm(Long elevatorModelId) {
        if (Objects.isNull(elevatorModelId)){
            throw new ServiceException("梯型不能为空");
        }
        List<List<? extends BasicExcelHelper>> result = Lists.newArrayList();

        List<TpParaLibrary> list = tpParaLibraryService.selectTpParaLibraryList(new TpParaLibrary());
        Map<String, String> codeNameMap = list.stream().collect(Collectors.toMap(TpParaLibrary::getParaCode, TpParaLibrary::getParaName));

        // 1. 获取基价配置信息
        TpAreaBasicPrice tpAreaBasicPriceParam = new  TpAreaBasicPrice();
        tpAreaBasicPriceParam.setElevatorModelId(elevatorModelId);
        List<TpAreaBasicPrice> basicList = selectTpAreaBasicPriceList(tpAreaBasicPriceParam);
        List<PriceFormBasicInfoHelper> basicResult = basicList.stream().map(item -> {
            PriceFormBasicInfoHelper helper = new PriceFormBasicInfoHelper();
            BeanUtils.copyProperties(item, helper);
            helper.setStandardDoorWidth(StringUtils.toStringFormat(item.getStandardDoorWidth()));
            helper.setStandardDoorHeight(StringUtils.toStringFormat(item.getStandardDoorHeight()));
            helper.setMaxLiftingHeight(StringUtils.toStringFormat(item.getMaxLiftingHeight()));
            helper.setStandardFloors(StringUtils.toStringFormat(item.getStandardFloors()));
            helper.setBasicPrice(StringUtils.toStringFormat(item.getBasicPrice()));
            helper.setAddOnefloorPrice(StringUtils.toStringFormat(item.getAddOnefloorPrice()));
            helper.setSubtractOnefloorPrice(StringUtils.toStringFormat(item.getSubtractOnefloorPrice()));
            return helper;
        }).collect(Collectors.toList());
        // 1.2 基价选配关联参数
        TpAreaBasicPriceRelatedPara relatedPara = getParams(elevatorModelId);
        PriceFormBasicInfoHelper relatedParaRow = new PriceFormBasicInfoHelper();
        relatedParaRow.setRelatedPara1(codeNameMap.get(relatedPara.getRelatedParaCode1()));
        relatedParaRow.setRelatedPara2(codeNameMap.get(relatedPara.getRelatedParaCode2()));
        relatedParaRow.setRelatedPara3(codeNameMap.get(relatedPara.getRelatedParaCode3()));
        relatedParaRow.setRelatedPara4(codeNameMap.get(relatedPara.getRelatedParaCode4()));
        relatedParaRow.setRelatedPara5(codeNameMap.get(relatedPara.getRelatedParaCode5()));
        basicResult.add(0, relatedParaRow);
        result.add(basicResult);

        Map<String, String> statusMap = DictUtils.getDictCache("status_switch").stream()
                .collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        Map<String, String> valueMap = DictUtils.getDictCache("value_type").stream()
                .collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        // 2. 获取选配信息
        TpAreaOptionalPara tpAreaOptionalParaParam = new TpAreaOptionalPara();
        tpAreaOptionalParaParam.setElevatorModelId(elevatorModelId);
        List<TpAreaOptionalPara> optionList = tpAreaOptionalParaService.selectTpAreaOptionalParaList(tpAreaOptionalParaParam);
        optionList.forEach(item -> {
            item.setParaCode(codeNameMap.get(item.getParaCode()));
            item.setRelatedParaCode1(codeNameMap.get(item.getRelatedParaCode1()));
            item.setRelatedParaCode2(codeNameMap.get(item.getRelatedParaCode2()));
            item.setRelatedParaCode3(codeNameMap.get(item.getRelatedParaCode3()));
            item.setRelatedParaCode4(codeNameMap.get(item.getRelatedParaCode4()));
            item.setRelatedParaCode5(codeNameMap.get(item.getRelatedParaCode5()));
            item.setRelatedParaCode6(codeNameMap.get(item.getRelatedParaCode6()));
            item.setRelatedParaCode7(codeNameMap.get(item.getRelatedParaCode7()));
            item.setRelatedParaCode8(codeNameMap.get(item.getRelatedParaCode8()));
            item.setRelatedParaCode9(codeNameMap.get(item.getRelatedParaCode9()));
            item.setRelatedParaCode10(codeNameMap.get(item.getRelatedParaCode10()));
            item.setStatus(statusMap.get(item.getStatus()));
        });

        // 3. 获取选配明细
        TpAreaOptionalParaPrice tpAreaOptionalParaPriceParam = new TpAreaOptionalParaPrice();
        tpAreaOptionalParaPriceParam.setElevatorModelId(elevatorModelId);
        List<TpAreaOptionalParaPrice> optionDetailList = tpAreaOptionalParaPriceService.selectTpAreaOptionalParaPriceList(tpAreaOptionalParaPriceParam);
        Map<Long, List<TpAreaOptionalParaPrice>> optionDetailMap = optionDetailList.stream().collect(Collectors.groupingBy(TpAreaOptionalParaPrice::getMarkupId));

        // 4. 合并选配明细信息
        for (int i=0; i<optionList.size(); i++) {
            List<TpAreaOptionalParaPrice> detailList = optionDetailMap.get(optionList.get(i).getId());
            if (CollectionUtils.isEmpty(detailList)) continue;

            for (TpAreaOptionalParaPrice item: detailList) {
                TpAreaOptionalPara optionalPara = new TpAreaOptionalPara();
                optionalPara.setParaCode(item.getParaCode());
                optionalPara.setRelatedParaCode1(item.getRelatedParaValue1());
                optionalPara.setRelatedParaCode2(item.getRelatedParaValue2());
                optionalPara.setRelatedParaCode3(item.getRelatedParaValue3());
                optionalPara.setRelatedParaCode4(item.getRelatedParaValue4());
                optionalPara.setRelatedParaCode5(item.getRelatedParaValue5());
                optionalPara.setRelatedParaCode6(item.getRelatedParaValue6());
                optionalPara.setRelatedParaCode7(item.getRelatedParaValue7());
                optionalPara.setRelatedParaCode8(item.getRelatedParaValue8());
                optionalPara.setRelatedParaCode9(item.getRelatedParaValue9());
                optionalPara.setRelatedParaCode10(item.getRelatedParaValue10());
                optionalPara.setQuantityType(valueMap.get(item.getQuantityType()));
                optionalPara.setQuantity(ValueType.VALUE.getCode().equals(item.getQuantityType()) ? String.valueOf(item.getQuantity()): item.getQuantityFormulaTxt());
                optionalPara.setQuantityUnit(item.getQuantityUnit());
                optionalPara.setPriceType(valueMap.get(item.getPriceType()));
                optionalPara.setPrice(ValueType.VALUE.getCode().equals(item.getPriceType()) ? String.valueOf(item.getPrice()): item.getPriceFormulaTxt());
                optionalPara.setRemark(item.getRemark());
                optionalPara.setStatus(valueMap.get(item.getStatus()));

                optionList.add(++i, optionalPara);
            }

        }

        result.add(optionList.stream().map(item -> {
            PriceFormOptionInfoHelper helper = new PriceFormOptionInfoHelper();
            BeanUtils.copyProperties(item, helper);
            return helper;
        }).collect(Collectors.toList()));

        return result;
    }

    @Override
    public ExcelUtils.UploadResult<PriceFormBasicInfoHelper> checkBasicInfo(PriceFormTableInfoHelper tableInfoHelper, List<PriceFormBasicInfoHelper> list) {
        return ExcelUtils.checkData(list, it -> {
            List<String> businessErrors = Lists.newArrayList();

            // 关联参数的判断
            boolean isHeader = it.equals(list.get(0));
            List<String> params = Lists.newArrayList(it.getRelatedPara1(), it.getRelatedPara2(), it.getRelatedPara3(),
                    it.getRelatedPara4(), it.getRelatedPara5()).stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
            if (isHeader && (params.size() > params.stream().distinct().count())) {
                businessErrors.add("关联参数不能重复");
            }

            if (!isHeader && isBlank(it.getStandardDoorWidth())){
                businessErrors.add("开门宽不能为空");
            }
            if (!isHeader && isBlank(it.getStandardDoorHeight())){
                businessErrors.add("开门高不能为空");
            }
            if (!isHeader && isBlank(it.getMaxLiftingHeight())){
                businessErrors.add("最大提升高度不能为空");
            }
            if (!isHeader && isBlank(it.getStandardFloors())){
                businessErrors.add("标准层站数不能为空");
            }
            if (!isHeader && isBlank(it.getBasicPrice())){
                businessErrors.add("基础价格不能为空");
            }
            if (!isHeader && isBlank(it.getAddOnefloorPrice())){
                businessErrors.add("层站加价不能为空");
            }
            if (!isHeader && isBlank(it.getSubtractOnefloorPrice())){
                businessErrors.add("层站减价不能为空");
            }

            return businessErrors;
        });
    }

    @Override
    public ExcelUtils.UploadResult<PriceFormOptionInfoHelper> checkOptionInfo(PriceFormTableInfoHelper tableInfoHelper, List<PriceFormOptionInfoHelper> list) {
        // 1 取得梯型相关的参数
        TpAreaElevatorModelPara param = new TpAreaElevatorModelPara();
        param.setElevatorModelId(Long.valueOf(tableInfoHelper.getElevatorModelId()));
        List<TpAreaElevatorModelPara> paramList = tpAreaElevatorModelParaService.selectTpAreaElevatorModelParaList(param);

        List<TpParaLibrary> libraryList;
        if (CollectionUtils.isNotEmpty(paramList)) {
            TpParaLibrary library = new TpParaLibrary();
            library.setIds(paramList.stream().map(TpAreaElevatorModelPara::getParaId).collect(Collectors.toList()));
            libraryList = tpParaLibraryService.selectTpParaLibraryList(library).stream()
                    .sorted(Comparator.comparing(item -> -item.getParaName().length())).collect(Collectors.toList());
        } else {
            libraryList = Lists.newArrayList();
        }
        Map<String, String> paraMap = libraryList.stream().collect(Collectors.toMap(TpParaLibrary::getParaName, TpParaLibrary::getParaCode));


        Map<String, String> valueMap = DictUtils.getDictCache("value_type").stream()
                .collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));

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

            // 参数值
            if (StringUtils.isBlank(it.getMarkupName())){
                if (isBlank(it.getQuantityType())) {
                    businessErrors.add("数量类型不能为空");
                } else if (isBlank(valueMap.get(it.getQuantityType()))) {
                    businessErrors.add("数量类型不存在");
                }
                if (isBlank(it.getQuantity())) {
                    businessErrors.add("数量不能为空");
                }

                if (ValueType.VALUE.getInfo().equals(it.getQuantityType())) {
                    try{
                        StringUtils.parseLong(it.getQuantity());
                    } catch (Exception e){
                        businessErrors.add("数量必须为有效数字");
                    }
                }


                if (isBlank(it.getQuantityUnit())) {
                    businessErrors.add("单位不能为空");
                }
                if (isBlank(it.getPriceType())) {
                    businessErrors.add("价格类型不能为空");
                } else if (isBlank(valueMap.get(it.getPriceType()))) {
                    businessErrors.add("价格类型不存在");
                }
                if (ValueType.VALUE.getInfo().equals(it.getPriceType())) {
                    try{
                        StringUtils.parseDecimal(it.getPrice());
                    } catch (Exception e){
                        businessErrors.add("价格必须为有效数字");
                    }
                }
                if (isBlank(it.getPrice())) {
                    businessErrors.add("价格不能为空");
                }

                return businessErrors;
            }


            if (StringUtils.isBlank(it.getParaCode())) {
                businessErrors.add("选配关联参数不能为空");
            }
            List<String> params = Lists.newArrayList(it.getParaCode(), it.getRelatedParaCode1(), it.getRelatedParaCode2(), it.getRelatedParaCode3(),
                    it.getRelatedParaCode4(), it.getRelatedParaCode5(), it.getRelatedParaCode6(),
                    it.getRelatedParaCode7(), it.getRelatedParaCode8(), it.getRelatedParaCode9(),
                    it.getRelatedParaCode10()).stream().filter(StringUtils::isNotBlank).collect(Collectors.toList());
            if ((params.size() > params.stream().distinct().count())) {
                businessErrors.add("选配关联参数及其他关联参数不能重复");
            }
            if (isNotBlank(it.getParaCode()) && isBlank(paraMap.get(it.getParaCode()))) {
                businessErrors.add("选配关联参数不存在");
            }
            if (isNotBlank(it.getRelatedParaCode1()) && isBlank(paraMap.get(it.getRelatedParaCode1()))) {
                businessErrors.add("其他关联参数1不存在");
            }
            if (isNotBlank(it.getRelatedParaCode2()) && isBlank(paraMap.get(it.getRelatedParaCode2()))) {
                businessErrors.add("其他关联参数2不存在");
            }
            if (isNotBlank(it.getRelatedParaCode3()) && isBlank(paraMap.get(it.getRelatedParaCode3()))) {
                businessErrors.add("其他关联参数3不存在");
            }
            if (isNotBlank(it.getRelatedParaCode4()) && isBlank(paraMap.get(it.getRelatedParaCode4()))) {
                businessErrors.add("其他关联参数4不存在");
            }
            if (isNotBlank(it.getRelatedParaCode5()) && isBlank(paraMap.get(it.getRelatedParaCode5()))) {
                businessErrors.add("其他关联参数5不存在");
            }
            if (isNotBlank(it.getRelatedParaCode6()) && isBlank(paraMap.get(it.getRelatedParaCode6()))) {
                businessErrors.add("其他关联参数6不存在");
            }
            if (isNotBlank(it.getRelatedParaCode7()) && isBlank(paraMap.get(it.getRelatedParaCode7()))) {
                businessErrors.add("其他关联参数7不存在");
            }
            if (isNotBlank(it.getRelatedParaCode8()) && isBlank(paraMap.get(it.getRelatedParaCode8()))) {
                businessErrors.add("其他关联参数8不存在");
            }
            if (isNotBlank(it.getRelatedParaCode9()) && isBlank(paraMap.get(it.getRelatedParaCode9()))) {
                businessErrors.add("其他关联参数9不存在");
            }
            if (isNotBlank(it.getRelatedParaCode10()) && isBlank(paraMap.get(it.getRelatedParaCode10()))) {
                businessErrors.add("其他关联参数10不存在");
            }


            return businessErrors;
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> insertPriceFormImportExcel(BasicTableInfoHelper basicTableInfoHelper, String elevatorModelId, List<HashMap> dataList) {
        long start = System.currentTimeMillis();

        if (StringUtils.isBlank(elevatorModelId)) {
            throw new ServiceException("梯型信息不能为空");
        }
        Long id = Long.parseLong(elevatorModelId);
        if (CollectionUtils.isEmpty(dataList)){
            throw new ServiceException("导入数据不能为空");
        }

        // 1 取得梯型相关的参数
        TpAreaElevatorModelPara param = new TpAreaElevatorModelPara();
        param.setElevatorModelId(id);
        List<TpAreaElevatorModelPara> paramList = tpAreaElevatorModelParaService.selectTpAreaElevatorModelParaList(param);

        List<TpParaLibrary> libraryList;
        if (CollectionUtils.isNotEmpty(paramList)) {
            TpParaLibrary library = new TpParaLibrary();
            library.setIds(paramList.stream().map(TpAreaElevatorModelPara::getParaId).collect(Collectors.toList()));
            libraryList = tpParaLibraryService.selectTpParaLibraryList(library).stream()
                    .sorted(Comparator.comparing(item -> -item.getParaName().length())).collect(Collectors.toList());
        } else {
            libraryList = Lists.newArrayList();
        }
        Map<String, String> paraMap = libraryList.stream().collect(Collectors.toMap(TpParaLibrary::getParaName, TpParaLibrary::getParaCode));

        Map<String, List<HashMap>> map = dataList.stream().collect(Collectors.groupingBy(item -> (String)item.get("sheetName")));
        Map<String, String> valueMap = DictUtils.getDictCache("value_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));

        log.info("获取配置数据耗时：{}", System.currentTimeMillis() - start);

        // 1. 基价信息导入
        List<PriceFormBasicInfoHelper> basicList = transform(map.get("基价信息"), PriceFormBasicInfoHelper.class);
        int sort = 0;
        List<TpAreaBasicPrice> basicPriceList = Lists.newArrayList();
        TpAreaBasicPrice relatedPara = new TpAreaBasicPrice();
        for (PriceFormBasicInfoHelper item: basicList) {
            if (sort == 0){
                relatedPara.setElevatorModelId(id);
                relatedPara.setRelatedParaCode1(paraMap.get(item.getRelatedPara1()));
                relatedPara.setRelatedParaCode2(paraMap.get(item.getRelatedPara2()));
                relatedPara.setRelatedParaCode3(paraMap.get(item.getRelatedPara3()));
                relatedPara.setRelatedParaCode4(paraMap.get(item.getRelatedPara4()));
                relatedPara.setRelatedParaCode5(paraMap.get(item.getRelatedPara5()));
                sort++;
                continue;
            }
            TpAreaBasicPrice tpAreaBasicPrice = new TpAreaBasicPrice();
            tpAreaBasicPrice.setElevatorModelId(id);
            tpAreaBasicPrice.setRelatedPara1(item.getRelatedPara1());
            tpAreaBasicPrice.setRelatedPara2(item.getRelatedPara2());
            tpAreaBasicPrice.setRelatedPara3(item.getRelatedPara3());
            tpAreaBasicPrice.setRelatedPara4(item.getRelatedPara4());
            tpAreaBasicPrice.setRelatedPara5(item.getRelatedPara5());

            tpAreaBasicPrice.setStandardDoorWidth(parseLong(item.getStandardDoorWidth()));
            tpAreaBasicPrice.setStandardDoorHeight(parseLong(item.getStandardDoorHeight()));
            tpAreaBasicPrice.setMaxLiftingHeight(parseLong(item.getMaxLiftingHeight()));
            tpAreaBasicPrice.setStandardFloors(parseLong(item.getStandardFloors()));
            tpAreaBasicPrice.setBasicPrice(parseLong(item.getBasicPrice()));
            tpAreaBasicPrice.setAddOnefloorPrice(parseLong(item.getAddOnefloorPrice()));
            tpAreaBasicPrice.setSubtractOnefloorPrice(parseLong(item.getSubtractOnefloorPrice()));
            tpAreaBasicPrice.setRemark(item.getRemark());
            tpAreaBasicPrice.setSortNumber(sort++);
            basicPriceList.add(tpAreaBasicPrice);
        }
        log.info("处理基价数据耗时：{}", System.currentTimeMillis() - start);
        tpAreaBasicPriceMapper.delete(Wrappers.<TpAreaBasicPrice>lambdaQuery().eq(TpAreaBasicPrice::getElevatorModelId, id));
        if (CollectionUtils.isNotEmpty(basicPriceList)) {
            saveBatch(basicPriceList);
        }
        setParams(relatedPara);

        log.info("导入基价数据耗时：{}", System.currentTimeMillis() - start);

        // 2. 选配信息导入
        List<PriceFormOptionInfoHelper> optionList = transform(map.get("选配项目"), PriceFormOptionInfoHelper.class);
        List<TpAreaOptionalPara> optionalParaList = Lists.newArrayList();
        List<TpAreaOptionalParaPrice> optionalParaPriceList = Lists.newArrayList();

        // 用于公式替换
        BiFunction<String, List<TpAreaOptionalPara>, String> replaceNames = (formula, paraList) -> {
            if (org.apache.commons.lang3.StringUtils.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() + "$_$"));
            }

            // 4. 替换其他加价项
            for (TpAreaOptionalPara item: paraList){
                if (formula.indexOf(item.getMarkupName()) == -1) {
                    continue;
                }
                formula = formula.replaceAll(StringUtils.initWordRegpx(item.getMarkupName()), Matcher.quoteReplacement("$_$" + item.getMarkupName() + "$_$"));
            }

            return formula;
        };

        // 2.2 区分导入数据为选配项还是明细
        PriceFormOptionInfoHelper currentPara = null;
        sort = 1;
        for (PriceFormOptionInfoHelper option: optionList){
            if (isNotBlank(option.getMarkupName())) {
                currentPara = option;
                TpAreaOptionalPara tpAreaOptionalPara = new TpAreaOptionalPara();
                tpAreaOptionalPara.setElevatorModelId(id);
                tpAreaOptionalPara.setMarkupName(option.getMarkupName());
                tpAreaOptionalPara.setRemark(option.getRemark());
                // 把中文参数名转为对应code
                tpAreaOptionalPara.setParaCode(paraMap.get(option.getParaCode()));
                tpAreaOptionalPara.setRelatedParaCode1(paraMap.get(option.getRelatedParaCode1()));
                tpAreaOptionalPara.setRelatedParaCode2(paraMap.get(option.getRelatedParaCode2()));
                tpAreaOptionalPara.setRelatedParaCode3(paraMap.get(option.getRelatedParaCode3()));
                tpAreaOptionalPara.setRelatedParaCode4(paraMap.get(option.getRelatedParaCode4()));
                tpAreaOptionalPara.setRelatedParaCode5(paraMap.get(option.getRelatedParaCode5()));
                tpAreaOptionalPara.setRelatedParaCode6(paraMap.get(option.getRelatedParaCode6()));
                tpAreaOptionalPara.setRelatedParaCode7(paraMap.get(option.getRelatedParaCode7()));
                tpAreaOptionalPara.setRelatedParaCode8(paraMap.get(option.getRelatedParaCode8()));
                tpAreaOptionalPara.setRelatedParaCode9(paraMap.get(option.getRelatedParaCode9()));
                tpAreaOptionalPara.setRelatedParaCode10(paraMap.get(option.getRelatedParaCode10()));
                tpAreaOptionalPara.setStatus(StringUtils.isNotBlank(option.getStatus()) ? statusMap.get(option.getStatus()): "0");
                tpAreaOptionalPara.setSortIndex(sort++);
                optionalParaList.add(tpAreaOptionalPara);
            } else {
                if (Objects.isNull(currentPara)){
                    throw new ServiceException("选配信息不能为空");
                }
                TpAreaOptionalParaPrice tpAreaOptionalParaPrice = new TpAreaOptionalParaPrice();
                tpAreaOptionalParaPrice.setElevatorModelId(id);
                tpAreaOptionalParaPrice.setMarkupName(currentPara.getMarkupName());
                tpAreaOptionalParaPrice.setParaCode(option.getParaCode());
                tpAreaOptionalParaPrice.setRelatedParaValue1(option.getRelatedParaCode1());
                tpAreaOptionalParaPrice.setRelatedParaValue2(option.getRelatedParaCode2());
                tpAreaOptionalParaPrice.setRelatedParaValue3(option.getRelatedParaCode3());
                tpAreaOptionalParaPrice.setRelatedParaValue4(option.getRelatedParaCode4());
                tpAreaOptionalParaPrice.setRelatedParaValue5(option.getRelatedParaCode5());
                tpAreaOptionalParaPrice.setRelatedParaValue6(option.getRelatedParaCode6());
                tpAreaOptionalParaPrice.setRelatedParaValue7(option.getRelatedParaCode7());
                tpAreaOptionalParaPrice.setRelatedParaValue8(option.getRelatedParaCode8());
                tpAreaOptionalParaPrice.setRelatedParaValue9(option.getRelatedParaCode9());
                tpAreaOptionalParaPrice.setRelatedParaValue10(option.getRelatedParaCode10());
                tpAreaOptionalParaPrice.setQuantityType(valueMap.get(option.getQuantityType()));
                if (ValueType.FORMULA.getCode().equals(tpAreaOptionalParaPrice.getQuantityType())) {
                    tpAreaOptionalParaPrice.setQuantityFormulaTxt(option.getQuantity());
                    tpAreaOptionalParaPrice.setQuantityFormula(replaceNames.apply(tpAreaOptionalParaPrice.getQuantityFormulaTxt(), optionalParaList));
                } else {
                    tpAreaOptionalParaPrice.setQuantity(StringUtils.parseLong(option.getQuantity()));
                }
                tpAreaOptionalParaPrice.setQuantityUnit(option.getQuantityUnit());
                tpAreaOptionalParaPrice.setPriceType(valueMap.get(option.getPriceType()));
                if (ValueType.FORMULA.getCode().equals(tpAreaOptionalParaPrice.getPriceType())) {
                    tpAreaOptionalParaPrice.setPriceFormulaTxt(option.getPrice());
                    tpAreaOptionalParaPrice.setPriceFormula(replaceNames.apply(tpAreaOptionalParaPrice.getPriceFormulaTxt(), optionalParaList));
                } else {
                    tpAreaOptionalParaPrice.setPrice(StringUtils.parseDecimal(option.getPrice()));
                }
                optionalParaPriceList.add(tpAreaOptionalParaPrice);
            }
        }
        log.info("处理选配数据耗时：{}", System.currentTimeMillis() - start);

        // 2.3 保存处理结果
        tpAreaOptionalParaService.deleteTpAreaOptionalParaByElevatorModelId(id);
        if (CollectionUtils.isNotEmpty(optionalParaList)){
            tpAreaOptionalParaService.saveBatch(optionalParaList);
        }
        Map<String, Long> idMap = optionalParaList.stream().collect(Collectors.toMap(TpAreaOptionalPara::getMarkupName, TpAreaOptionalPara::getId));
        optionalParaPriceList.forEach(item -> item.setMarkupId(idMap.get(item.getMarkupName())));
        tpAreaOptionalParaPriceService.deleteTpAreaOptionalParaPriceByElevatorModelId(id);
        if (CollectionUtils.isNotEmpty(optionalParaPriceList)) {
            tpAreaOptionalParaPriceService.saveBatch(optionalParaPriceList);
        }

        log.info("导入选配数据耗时：{}", System.currentTimeMillis() - start);

        return Lists.newArrayList();
    }

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