package com.cf.imes.module.plan.service.orderImport.factory;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cf.imes.framework.common.enums.OrderPlateTypeEnum;
import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.id.core.util.SnowflakeIdWorker3rd;
import com.cf.imes.framework.mybatis.core.generator.SnowFlakeGenerator;
import com.cf.imes.framework.mybatis.core.injector.BaseBatchMapper;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.cf.imes.framework.mybatis.core.query.LambdaUpdateWrapperX;
import com.cf.imes.module.executor.enums.DictTypeConstants;
import com.cf.imes.module.executor.enums.OrderImportConstants;
import com.cf.imes.module.executor.enums.OrderImportStatusEnum;
import com.cf.imes.module.executor.enums.OrderImportTmpDataTypeEnum;
import com.cf.imes.module.executor.enums.OrderItemTypeEnum;
import com.cf.imes.module.plan.controller.admin.orderImport.vo.OrderImportTempDataReqVO;
import com.cf.imes.module.plan.controller.admin.orderImport.vo.OrderPlateImportExcelVO;
import com.cf.imes.module.plan.dal.dataobject.goods.GoodsDO;
import com.cf.imes.module.plan.dal.dataobject.order.OrderDO;
import com.cf.imes.module.plan.dal.dataobject.orderBody.OrderBodyDO;
import com.cf.imes.module.plan.dal.dataobject.orderGroup.OrderGroupDO;
import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTaskDO;
import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataDO;
import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataGoodsGroupDO;
import com.cf.imes.module.plan.dal.dataobject.orderImport.OrderImportTempDataGoodsIdGroupDO;
import com.cf.imes.module.plan.dal.dataobject.orderItem.OrderItemDO;
import com.cf.imes.module.plan.dal.dataobject.orderParts.OrderPartsDO;
import com.cf.imes.module.plan.dal.dataobject.ordermodel.OrderModelDO;
import com.cf.imes.module.plan.dal.dataobject.plate.PlateDO;
import com.cf.imes.module.plan.dal.dataobject.plate.PlateGoodDO;
import com.cf.imes.module.plan.dal.dataobject.rawgoods.RawGoodsDO;
import com.cf.imes.module.plan.dal.elasticsearch.OrderPartsRemark;
import com.cf.imes.module.plan.dal.mysql.goods.GoodsMapper;
import com.cf.imes.module.plan.dal.mysql.orderBody.OrderBodyMapper;
import com.cf.imes.module.plan.dal.mysql.orderGroup.OrderGroupMapper;
import com.cf.imes.module.plan.dal.mysql.orderImport.OrderImportTaskMapper;
import com.cf.imes.module.plan.dal.mysql.orderImport.OrderImportTempDataMapper;
import com.cf.imes.module.plan.dal.mysql.orderItem.OrderItemMapper;
import com.cf.imes.module.plan.dal.mysql.orderParts.OrderPartsMapper;
import com.cf.imes.module.plan.dal.mysql.orderParts.PartsMapper;
import com.cf.imes.module.plan.dal.mysql.plate.PlateGoodMapper;
import com.cf.imes.module.plan.dal.mysql.plate.PlateMapper;
import com.cf.imes.module.plan.dal.mysql.rawgoods.RawGoodsMapper;
import com.cf.imes.module.plan.service.customplateno.CustomPlateNoGenerateService;
import com.cf.imes.module.plan.service.customplateno.vo.CustomPlateNoGenerateConfigVO;
import com.cf.imes.module.plan.service.order.OrderInputProcessor;
import com.cf.imes.module.system.api.dict.DictDataApi;
import com.cf.imes.module.system.api.dict.dto.DictDataRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static com.cf.imes.module.plan.enums.ErrorCodeConstants.ORDER_IMPORT_PLATE_GOODS_NOMATCH_ERROR;
import static com.cf.imes.module.plan.enums.ErrorCodeConstants.ORDER_IMPORT_PLATE_GOODS_NOT_EXISTS;
import static com.cf.imes.module.plan.service.order.OrderInputProcessor.ORDER_PARTS_REMARK_MODEL;
import static com.cf.imes.module.plan.service.order.OrderInputProcessor.ORDER_PLATE_MODEL;

/**
 * 默认excel导入生产单工厂服务
 *
 * @author Gqr
 * @since 2025/2/11 16:03
 */
@Slf4j
public class DefaultExcelOrderImportFactory {
    /**
     * 分组中做分页的阈值，如：总数100以上就边分组边分页，否则一次性查出来
     */
    private static final int BATCH_THRESHOLD_NUMBER = 100;

    private Long organId;

    // 批次id
    private Long batchId;

    private Long orderId;

    private Long taskId;

    private OrderDO orderDO;

    private CustomPlateNoGenerateConfigVO plateNoGenerateConfigVO;

    // 是否入库的第一块板件
    private boolean isFirstPlate;

    private List<RawGoodsDO> rawGoodsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
    private List<GoodsDO> goodsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
    private List<OrderPartsDO> orderPartsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
    private List<OrderBodyDO> orderBodyDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
    private List<OrderGroupDO> orderGroupDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
    private List<PlateDO> plateDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
    private List<OrderItemDO> orderItemDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
    private List<PlateGoodDO> plateGoodDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
    private List<OrderModelDO> orderModelDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
    private List<OrderPartsRemark> orderPartsRemarks = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
//    private List<PartsDO> partsDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);

    private static final String EMPTY_STRING = new String();
    private static final BigDecimal BIG_ZERO = new BigDecimal(0);

    private static final int PLATE_TYPE = OrderImportTmpDataTypeEnum.PLATE.getType();
    private static final int PART_TYPE = OrderImportTmpDataTypeEnum.PART.getType();

    private SnowFlakeGenerator snowFlakeGenerator;

    private SnowflakeIdWorker3rd idWorker;

    private OrderImportTaskMapper orderImportTaskMapper;

    private OrderImportTempDataMapper orderImportTempDataMapper;

    private DictDataApi dictDataApi;

    private GoodsMapper goodsMapper;

    private RawGoodsMapper rawGoodsMapper;

    private OrderPartsMapper orderPartsMapper;

    private OrderBodyMapper orderBodyMapper;

    private OrderGroupMapper orderGroupMapper;

    private PlateMapper plateMapper;

    private OrderItemMapper orderItemMapper;

    private PlateGoodMapper plateGoodMapper;

    private OrderInputProcessor orderInputProcessor;

    private PartsMapper partsMapper;

    private String operatorName;

    private CustomPlateNoGenerateService customPlateNoGenerateService;

    public DefaultExcelOrderImportFactory(Long taskId,
                                          OrderDO orderDO,
                                          Long organId,
                                          String operatorName,
                                          SnowFlakeGenerator snowFlakeGenerator,
                                          SnowflakeIdWorker3rd idWorker,
                                          OrderImportTaskMapper orderImportTaskMapper,
                                          OrderImportTempDataMapper orderImportTempDataMapper,
                                          DictDataApi dictDataApi,
                                          GoodsMapper goodsMapper,
                                          RawGoodsMapper rawGoodsMapper,
                                          OrderPartsMapper orderPartsMapper,
                                          OrderBodyMapper orderBodyMapper,
                                          OrderGroupMapper orderGroupMapper,
                                          PlateMapper plateMapper,
                                          OrderItemMapper orderItemMapper,
                                          PlateGoodMapper plateGoodMapper,
                                          OrderInputProcessor orderInputProcessor,
                                          PartsMapper partsMapper,
                                          CustomPlateNoGenerateService customPlateNoGenerateService) {
        this.taskId = taskId;
        this.orderDO = orderDO;
        this.orderId = orderDO.getId();
        this.organId = organId;
        this.operatorName = operatorName;
        this.snowFlakeGenerator = snowFlakeGenerator;
        this.idWorker = idWorker;
        this.orderImportTaskMapper = orderImportTaskMapper;
        this.orderImportTempDataMapper = orderImportTempDataMapper;
        this.dictDataApi = dictDataApi;
        this.goodsMapper = goodsMapper;
        this.rawGoodsMapper = rawGoodsMapper;
        this.orderPartsMapper = orderPartsMapper;
        this.orderBodyMapper = orderBodyMapper;
        this.orderGroupMapper = orderGroupMapper;
        this.plateMapper = plateMapper;
        this.orderItemMapper = orderItemMapper;
        this.plateGoodMapper = plateGoodMapper;
        this.orderInputProcessor = orderInputProcessor;
        this.partsMapper = partsMapper;
        this.customPlateNoGenerateService = customPlateNoGenerateService;
        batchId = (Long) snowFlakeGenerator.nextId(null);
    }

    /**
     * 解析临时表数据
     */
    public void analyzeTempData() {
        try {
            // 获取自定义板编号配置
            plateNoGenerateConfigVO = customPlateNoGenerateService.getPlateNoGenerateConfig(orderId);

            log.info("====================【生产单默认xml导入处理商品开始】====================");
            // 解析商品数据
            analyzeGoods();
            log.info("====================【生产单默认xml导入处理商品结束】====================");

            log.info("====================【生产单默认xml导入处理配件商品开始】====================");
            // 解析配件数据
            analyzePartsGoods();
            log.info("====================【生产单默认xml导入处理配件商品结束】====================");

            log.info("====================【生产单默认xml导入处理小板/配件开始】====================");
            // 解析小板/配件项
            analyzeRooms();
            log.info("====================【生产单默认xml导入处理小板/配件结束】====================");
            // 所有自定义板编号生成完成后更新配置到生产单
            customPlateNoGenerateService.updateCustomPlateNoGenerateConfig(plateNoGenerateConfigVO, orderDO);

            // 删除临时数据
            deleteTempData();
            // 完成所有流程后更新任务为导入成功
            updateTaskSuccess();
        } catch (Exception e) {
            // 数据库数据回滚，此时删除 ES 里的数据
            orderInputProcessor.deleteByOrderIdBatch(orderId, batchId, ORDER_PLATE_MODEL);
            orderInputProcessor.deleteByOrderIdBatch(orderId, batchId, ORDER_PARTS_REMARK_MODEL);
            throw e;
        } finally {
            // 解析结束后清理所有list
            clearAll();
        }
    }

    /**
     * 解析商品
     */
    private void analyzeGoods() {
        // 基于物料编码分组的总数
        OrderImportTempDataReqVO goodsIdGroupCountReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(PLATE_TYPE).build();
        Integer goodsIdGroupCount = orderImportTempDataMapper.selectCountGoodsIdGroup(goodsIdGroupCountReqVO);
        if (NumberUtil.compare(goodsIdGroupCount, 0) > 0) {
            // 在阈值之下就不分组
            if (goodsIdGroupCount <= BATCH_THRESHOLD_NUMBER) {
                analyzeGoodsDetailNoPaging();
            } else {

            }
        }
    }

    /**
     * 不分页解析商品id分组列表
     */
    private void analyzeGoodsDetailNoPaging() {
        // 基于物料编码查分组
        OrderImportTempDataReqVO goodsIdGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(PLATE_TYPE).build();
        List<OrderImportTempDataGoodsIdGroupDO> goodsIdGroupList = orderImportTempDataMapper.selectGoodsIdGroup(goodsIdGroupReqVO);
        for (OrderImportTempDataGoodsIdGroupDO goodsIdGroupDO : goodsIdGroupList) {
            String outerGoodsId = goodsIdGroupDO.getOuterGoodsId();
            // 查询物料编码下的大板属性分组后的总数
            OrderImportTempDataReqVO plateGoodsGroupCountReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(PLATE_TYPE).goodsId(outerGoodsId).build();
            int plateGoodsGroupCount = orderImportTempDataMapper.selectCountPlateGoodsGroup(plateGoodsGroupCountReqVO);
            if (NumberUtil.compare(plateGoodsGroupCount, 0) > 0) {
                // 在阈值之下就不分组
                if (plateGoodsGroupCount <= BATCH_THRESHOLD_NUMBER) {
                    // 查询物料编码下的大板属性的分组
                    OrderImportTempDataReqVO goodsGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(PLATE_TYPE).goodsId(outerGoodsId).build();
                    List<OrderImportTempDataGoodsGroupDO> orderImportTempDataGoodsGroupDOS = orderImportTempDataMapper.selectPlateGoodsGroup(goodsGroupReqVO);
                    for (OrderImportTempDataGoodsGroupDO orderImportTempDataGoodsGroupDO : orderImportTempDataGoodsGroupDOS) {
                        analyzeInnerGoodsDetailNoPaging(outerGoodsId, orderImportTempDataGoodsGroupDO);
                    }
                } else {
                    // 分组分页解析

                }
            }
        }
        // 最后批量插入rawgoods、goods、plategoods一次，避免最后一页小于BATCH_THRESHOLD_NUMBER漏插入
        orderInfoBatchInsertWithinThreshold(rawGoodsMapper, rawGoodsDOS, true);
        orderInfoBatchInsertWithinThreshold(goodsMapper, goodsDOS, true);
        orderInfoBatchInsertWithinThreshold(plateGoodMapper, plateGoodDOS, true);
    }


    /**
     * 不分页解析出imes goodsdo入库
     *
     * @param outerGoodsId
     * @param orderImportTempDataGoodsGroupDO
     */
    private void analyzeInnerGoodsDetailNoPaging(String outerGoodsId, OrderImportTempDataGoodsGroupDO orderImportTempDataGoodsGroupDO) {
        // 是否有物料编码
        boolean outerGoodsIdExist = false;
        // 创建rawgoods
        RawGoodsDO rawGoodsDO = createRawGoodsDO(outerGoodsId, orderImportTempDataGoodsGroupDO);
        // 创建goods
        GoodsDO goodsDO = createGoodsDO(orderImportTempDataGoodsGroupDO).setRawGoodsId(String.valueOf(rawGoodsDO.getId()));
        // 有物料编码用物料编码设置goodsId否则rawgoodsId、goodsId设空
        if (ObjectUtil.notEqual(OrderImportConstants.DEFAULT_GOODS_ID, outerGoodsId)) {
            goodsDO.setGoodsId(rawGoodsDO.getRawGoodsId());
            outerGoodsIdExist = true;
        } else {
            rawGoodsDO.setRawGoodsId(EMPTY_STRING);
            goodsDO.setGoodsId(EMPTY_STRING);
        }
        Long innerGoodsId = goodsDO.getId();
        // 解析大板
        analyzePlateGoods(goodsDO);
        goodsDOS.add(goodsDO);
        rawGoodsDOS.add(rawGoodsDO);
        // 批量插入rawgoods、goods
        orderInfoBatchInsertWithinThreshold(rawGoodsMapper, rawGoodsDOS, false);
        orderInfoBatchInsertWithinThreshold(goodsMapper, goodsDOS, false);
        // 有物料编码用物料编码更新innerGoodsId，没有就用大板属性
        if (!outerGoodsIdExist) {
            orderImportTempDataMapper.update(new LambdaUpdateWrapperX<OrderImportTempDataDO>()
                    .eq(OrderImportTempDataDO::getTaskId, taskId)
                    .eq(OrderImportTempDataDO::getType, PLATE_TYPE)
                    .eqIfPresent(OrderImportTempDataDO::getGoodsName, orderImportTempDataGoodsGroupDO.getGoodsName())
                    .eqIfPresent(OrderImportTempDataDO::getMaterial, orderImportTempDataGoodsGroupDO.getMaterial())
                    .eqIfPresent(OrderImportTempDataDO::getColor, orderImportTempDataGoodsGroupDO.getColor())
                    .eqIfPresent(OrderImportTempDataDO::getThickness, orderImportTempDataGoodsGroupDO.getThickness())
                    .eqIfPresent(OrderImportTempDataDO::getBrand, orderImportTempDataGoodsGroupDO.getBrand())
                    .set(OrderImportTempDataDO::getInnerGoodsId, innerGoodsId));
        } else {
            orderImportTempDataMapper.update(new LambdaUpdateWrapper<OrderImportTempDataDO>()
                    .eq(OrderImportTempDataDO::getOuterGoodsId, outerGoodsId)
                    .eq(OrderImportTempDataDO::getTaskId, taskId)
                    .eq(OrderImportTempDataDO::getType, PLATE_TYPE)
                    .set(OrderImportTempDataDO::getInnerGoodsId, innerGoodsId));
        }
    }

    /**
     * 解析配件
     */
    private void analyzePartsGoods() {
        OrderImportTempDataReqVO partGoodsIdGroupCountReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(PART_TYPE).build();
        // 基于物料编码分组的总数
        Integer partGoodsIdGroupCount = orderImportTempDataMapper.selectCountGoodsIdGroup(partGoodsIdGroupCountReqVO);
        if (NumberUtil.compare(partGoodsIdGroupCount, 0) > 0) {
            // 在阈值之下就不分组
            if (partGoodsIdGroupCount <= BATCH_THRESHOLD_NUMBER) {
                analyzePartGoodsDetailNoPaging();
            } else {

            }
        }
    }

    /**
     * 不分页解析配件
     */
    private void analyzePartGoodsDetailNoPaging() {
        // 基于物料编码查分组列表
        OrderImportTempDataReqVO partGoodsIdGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(PART_TYPE).build();
        List<OrderImportTempDataGoodsIdGroupDO> partGoodsIdGroupList = orderImportTempDataMapper.selectGoodsIdGroup(partGoodsIdGroupReqVO);
        for (OrderImportTempDataGoodsIdGroupDO partGoodsIdGroupDO : partGoodsIdGroupList) {
            String outerGoodsId = partGoodsIdGroupDO.getOuterGoodsId();
            // 查询物料编码下的配件属性分组后的总数
            OrderImportTempDataReqVO partGoodsGroupCountReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(PART_TYPE).goodsId(outerGoodsId).build();
            int plateGoodsGroupCount = orderImportTempDataMapper.selectCountPartGoodsGroup(partGoodsGroupCountReqVO);
            if (NumberUtil.compare(plateGoodsGroupCount, 0) > 0) {
                // 在阈值之下就不分组
                if (plateGoodsGroupCount <= BATCH_THRESHOLD_NUMBER) {
                    // 查询物料编码下的配件属性的分组列表
                    OrderImportTempDataReqVO goodsGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).type(PART_TYPE).goodsId(outerGoodsId).build();
                    List<OrderImportTempDataGoodsGroupDO> orderImportTempDataGoodsGroupDOS = orderImportTempDataMapper.selectPartGoodsGroup(goodsGroupReqVO);
                    for (OrderImportTempDataGoodsGroupDO orderImportTempDataGoodsGroupDO : orderImportTempDataGoodsGroupDOS) {
                        analyzeInnerPartGoodsDetailNoPaging(outerGoodsId, orderImportTempDataGoodsGroupDO);
                    }
                } else {
                    // 分组分页解析

                }
            }
        }
        // 最后批量插入orderParts一次，避免最后一页小于BATCH_THRESHOLD_NUMBER漏插入
        orderInfoBatchInsertWithinThreshold(orderPartsMapper, orderPartsDOS, true);
//        orderInfoBatchInsertWithinThreshold(partsMapper, partsDOS, true);
        // 批量插入配件备注
        orderPartsRemarksBatchInsertWithinThreshold(true);
    }

    /**
     * 不分页解析出imes order_parts入库
     *
     * @param outerGoodsId
     * @param orderImportTempDataGoodsGroupDO
     */
    private void analyzeInnerPartGoodsDetailNoPaging(String outerGoodsId, OrderImportTempDataGoodsGroupDO orderImportTempDataGoodsGroupDO) {
        // 是否有物料编码
        boolean outerGoodsIdExist = false;
        // 创建orderParts
        OrderPartsDO orderParts = createOrderParts(outerGoodsId, orderImportTempDataGoodsGroupDO);
        Long partId = orderParts.getId();
        // 有物料编码用物料编码设置goodsId否则goodsId设空
        if (ObjectUtil.notEqual(OrderImportConstants.DEFAULT_GOODS_ID, outerGoodsId)) {
            orderParts.setGoodsId(outerGoodsId);
            outerGoodsIdExist = true;
        } else {
            orderParts.setGoodsId(EMPTY_STRING);
        }
        // 解析配件商品
//        analyzePartsGoods(orderParts);
        // 批量插入orderParts
        orderPartsDOS.add(orderParts);
        orderInfoBatchInsertWithinThreshold(orderPartsMapper, orderPartsDOS, false);
        // 有物料编码用物料编码更新innerGoodsId，没有就用配件属性
        if (!outerGoodsIdExist) {
            orderImportTempDataMapper.update(new LambdaUpdateWrapperX<OrderImportTempDataDO>()
                    .eq(OrderImportTempDataDO::getTaskId, taskId)
                    .eq(OrderImportTempDataDO::getType, PART_TYPE)
                    .eqIfPresent(OrderImportTempDataDO::getGoodsName, orderImportTempDataGoodsGroupDO.getGoodsName())
                    .eqIfPresent(OrderImportTempDataDO::getMaterial, orderImportTempDataGoodsGroupDO.getMaterial())
                    .eqIfPresent(OrderImportTempDataDO::getColor, orderImportTempDataGoodsGroupDO.getColor())
                    .eqIfPresent(OrderImportTempDataDO::getIsComposite, orderImportTempDataGoodsGroupDO.getIsComposite())
                    .eqIfPresent(OrderImportTempDataDO::getCategory, orderImportTempDataGoodsGroupDO.getCategory())
                    .eqIfPresent(OrderImportTempDataDO::getType, orderImportTempDataGoodsGroupDO.getSubType())
                    .eqIfPresent(OrderImportTempDataDO::getFactory, orderImportTempDataGoodsGroupDO.getFactory())
                    .eqIfPresent(OrderImportTempDataDO::getModel, orderImportTempDataGoodsGroupDO.getModel())
                    .eqIfPresent(OrderImportTempDataDO::getSpec, orderImportTempDataGoodsGroupDO.getSpec())
                    .eqIfPresent(OrderImportTempDataDO::getHeight, orderImportTempDataGoodsGroupDO.getHeight())
                    .eqIfPresent(OrderImportTempDataDO::getWidth, orderImportTempDataGoodsGroupDO.getWidth())
                    .eqIfPresent(OrderImportTempDataDO::getThickness, orderImportTempDataGoodsGroupDO.getThickness())
                    .eqIfPresent(OrderImportTempDataDO::getBrand, orderImportTempDataGoodsGroupDO.getBrand())
                    .eqIfPresent(OrderImportTempDataDO::getUnit, orderImportTempDataGoodsGroupDO.getUnit())
                    .set(OrderImportTempDataDO::getInnerGoodsId, partId));
        } else {
            orderImportTempDataMapper.update(new LambdaUpdateWrapper<OrderImportTempDataDO>()
                    .eq(OrderImportTempDataDO::getOuterGoodsId, outerGoodsId)
                    .eq(OrderImportTempDataDO::getTaskId, taskId)
                    .eq(OrderImportTempDataDO::getType, PART_TYPE)
                    .set(OrderImportTempDataDO::getInnerGoodsId, partId));
        }
        // 解析配件备注
        analyzePartsRemark(partId);
    }

    /**
     * 解析配件备注
     *
     * @param partId
     */
    private void analyzePartsRemark(Long partId) {
        // 配件id下的临时数据列表查询
        List<OrderImportTempDataDO> orderImportTempDataDOS = orderImportTempDataMapper.selectPartList(OrderImportTempDataReqVO.builder().goodsId(String.valueOf(partId)).build());
        StringBuilder remark = new StringBuilder();
        for (OrderImportTempDataDO tempDataDO : orderImportTempDataDOS) {
            // 取明细压缩数据做解压
            String detail = JsonUtils.unzipString(tempDataDO.getDetail());
            OrderPlateImportExcelVO combination = JSON.parseObject(detail, OrderPlateImportExcelVO.class);
            String extractedRemark = remarkExtract(combination.remarkJSON());
            if (StringUtils.isNotEmpty(extractedRemark)) {
                // 累加备注
                remark.append(extractedRemark);
            }
        }

        // 配件备注信息存储
        OrderPartsRemark orderPartsRemark = OrderPartsRemark.builder()
                .partsId(partId)
                .batchId(batchId)
                .orderId(orderId)
                .remark(remark.toString())
                .build();
        orderPartsRemark.setCreator(operatorName);
        orderPartsRemark.setUpdater(operatorName);
        orderPartsRemark.setOrganId(organId);
        // 批量插入配件备注
        orderPartsRemarks.add(orderPartsRemark);
        orderPartsRemarksBatchInsertWithinThreshold(false);
    }

    /**
     * 每达到阈值就批量插入一次生产单造型数据和压缩数据
     *
     * @param isLast 是否最后一次插入，不是就需要清理list
     */
    private void orderPartsRemarksBatchInsertWithinThreshold(boolean isLast) {
        // 达到批量的阈值就做一次插入
        if (CollUtil.isNotEmpty(orderPartsRemarks) && (orderPartsRemarks.size() >= BATCH_THRESHOLD_NUMBER || isLast)) {
            orderInputProcessor.batchSaveOrderPartsModel(orderPartsRemarks);
            if (!isLast) {
                // 存储完成清理 list
                orderPartsRemarks.clear();
            }
        }
    }

    /**
     * 解析房间
     */
    private void analyzeRooms() {
        // 基于roomName分组的总数
        Integer roomGroupCount = orderImportTempDataMapper.selectCountRoomGroup(taskId);
        if (NumberUtil.compare(roomGroupCount, 0) > 0) {
            // 在阈值之下就不分组
            if (roomGroupCount <= BATCH_THRESHOLD_NUMBER) {
                analyzeRoomNoPaing();
            } else {

            }
        }
        // 最后批量插入一次，避免最后一页小于BATCH_THRESHOLD_NUMBER漏插入
        orderInfoBatchInsertWithinThreshold(orderBodyMapper, orderBodyDOS, true);
        orderInfoBatchInsertWithinThreshold(orderGroupMapper, orderGroupDOS, true);
        orderInfoBatchInsertWithinThreshold(plateMapper, plateDOS, true);
        orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, true);
        // 批量插入造型数据
        orderModelsBatchInsertWithinThreshold(true);
    }

    /**
     * 不分页解析房间
     */
    private void analyzeRoomNoPaing() {
        // 查询基于roomName的分组
        OrderImportTempDataReqVO roomNameGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).build();
        List<OrderImportTempDataGoodsGroupDO> roomNameGroup = orderImportTempDataMapper.selectRoomGroup(roomNameGroupReqVO);
        for (OrderImportTempDataGoodsGroupDO roomNameGroupDO : roomNameGroup) {
            analyzeRoomBody(roomNameGroupDO.getRoomName());
        }
    }

    /**
     * 解析房间下柜体
     *
     * @param roomName
     */
    private void analyzeRoomBody(String roomName) {
        // 基于bodyName分组的总数
        OrderImportTempDataReqVO countBodyNameGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).roomName(roomName).build();
        Integer bodyGroupCount = orderImportTempDataMapper.selectCountBodyGroup(countBodyNameGroupReqVO);
        if (NumberUtil.compare(bodyGroupCount, 0) > 0) {
            // 在阈值之下就不分组
            if (bodyGroupCount <= BATCH_THRESHOLD_NUMBER) {
                analyzeBodyNoPaing(roomName);
            } else {

            }
        }
    }

    /**
     * 不分页解析房间下柜体
     *
     * @param roomName
     */
    private void analyzeBodyNoPaing(String roomName) {
        // 基于房间下bodyName查询分组和板数量（只有plate计入数量）
        OrderImportTempDataReqVO bodyNameGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).roomName(roomName).build();
        List<OrderImportTempDataGoodsGroupDO> bodyNameGroup = orderImportTempDataMapper.selectBodyGroup(bodyNameGroupReqVO);
        // 生成房间id
        Long roomId = (Long) snowFlakeGenerator.nextId(null);
        for (OrderImportTempDataGoodsGroupDO bodyNameGroupDO : bodyNameGroup) {
            // 创建orderBodyDO
            OrderBodyDO orderBodyDO = createOrderBodyDO(roomName, roomId, bodyNameGroupDO);
            // 批量插入orderBody
            orderBodyDOS.add(orderBodyDO);
            orderInfoBatchInsertWithinThreshold(orderBodyMapper, orderBodyDOS, false);
            // 解析房间、柜体下的加工组类型名称
            analyzeBodyGroupTypeName(orderBodyDO);
        }
    }

    /**
     * 解析房间、柜体下的加工组类型名称
     *
     * @param orderBodyDO
     */
    private void analyzeBodyGroupTypeName(OrderBodyDO orderBodyDO) {
        OrderImportTempDataReqVO countGroupTypeGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).roomName(orderBodyDO.getRoomName()).bodyName(orderBodyDO.getName()).build();
        // 基于groupTypeName分组的总数
        Integer countGroupTypeGroup = orderImportTempDataMapper.selectCountGroupTypeNameGroup(countGroupTypeGroupReqVO);
        if (NumberUtil.compare(countGroupTypeGroup, 0) > 0) {
            // 在阈值之下就不分组
            if (countGroupTypeGroup <= BATCH_THRESHOLD_NUMBER) {
                analyzeGroupTypeNameNoPaing(orderBodyDO);
            } else {

            }
        }
    }

    /**
     * 不分组解析房间、柜体下的加工组类型名称
     *
     * @param orderBodyDO
     */
    private void analyzeGroupTypeNameNoPaing(OrderBodyDO orderBodyDO) {
        // 基于房间、柜体下加工组类型名称分组
        OrderImportTempDataReqVO groupTypeNameGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).roomName(orderBodyDO.getRoomName()).bodyName(orderBodyDO.getName()).build();
        List<OrderImportTempDataGoodsGroupDO> groupTypeNameGroup = orderImportTempDataMapper.selectGroupTypeNameGroup(groupTypeNameGroupReqVO);
        // 生成加工组类型id
        Long groupTypeId = (Long) snowFlakeGenerator.nextId(null);
        for (OrderImportTempDataGoodsGroupDO groupTypeNameGroupDO : groupTypeNameGroup) {
            // 解析房间、柜体、加工组类型名称下的加工组名称
            analyzeGroupName(orderBodyDO, groupTypeNameGroupDO.getGroupTypeName(), groupTypeId);
        }
    }

    /**
     * 解析房间、柜体、加工组类型名称下的加工组名称
     *
     * @param orderBodyDO
     * @param groupTypeName
     * @param groupTypeId
     */
    private void analyzeGroupName(OrderBodyDO orderBodyDO, String groupTypeName, Long groupTypeId) {
        // 基于groupName分组的总数
        OrderImportTempDataReqVO countGroupNameGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).roomName(orderBodyDO.getRoomName()).bodyName(orderBodyDO.getName()).groupTypeName(groupTypeName).build();
        Integer countGroupNameGroup = orderImportTempDataMapper.selectCountGroupNameGroup(countGroupNameGroupReqVO);
        if (NumberUtil.compare(countGroupNameGroup, 0) > 0) {
            // 在阈值之下就不分组
            if (countGroupNameGroup <= BATCH_THRESHOLD_NUMBER) {
                analyzeGroupNameNoPaing(orderBodyDO, groupTypeName, groupTypeId);
            } else {

            }
        }
    }

    /**
     * 不分组解析房间、柜体、加工组类型名称下的加工组名称
     *
     * @param orderBodyDO
     * @param groupTypeName
     * @param groupTypeId
     */
    private void analyzeGroupNameNoPaing(OrderBodyDO orderBodyDO, String groupTypeName, Long groupTypeId) {
        // 基于groupName分组和数量（只有plate计入数量）
        OrderImportTempDataReqVO groupNameGroupReqVO = OrderImportTempDataReqVO.builder().taskId(taskId).roomName(orderBodyDO.getRoomName()).bodyName(orderBodyDO.getName()).groupTypeName(groupTypeName).build();
        List<OrderImportTempDataGoodsGroupDO> groupNameGroup = orderImportTempDataMapper.selectGroupNameGroup(groupNameGroupReqVO);
        for (OrderImportTempDataGoodsGroupDO groupNameGroupDO : groupNameGroup) {
            String groupName = groupNameGroupDO.getGroupName();
            Long groupId = 0L;
            if (StringUtils.isNotEmpty(groupName)) {
                // 创建orderGroupDO
                OrderGroupDO orderGroupDO = createOrderGroupDO(orderBodyDO.getId(), groupTypeName, groupTypeId, groupNameGroupDO);
                groupId = orderGroupDO.getId();
                // 生成orderGroup
                orderGroupDOS.add(orderGroupDO);
                // 批量插入orderGroup
                orderInfoBatchInsertWithinThreshold(orderGroupMapper, orderGroupDOS, false);
            }
            // 根据数量生成相应的item
            analyzeItem(orderBodyDO, groupTypeName, groupName, groupId);
            // 根据数量生成相应的配件
            analyzePart(orderBodyDO, groupTypeName, groupName, groupId);
        }
    }

    /**
     * 分页解析小板orderPlate、orderItem
     *
     * @param orderBodyDO
     * @param groupTypeName
     * @param groupName
     * @param groupId
     */
    private void analyzeItem(OrderBodyDO orderBodyDO, String groupTypeName, String groupName, Long groupId) {
        String roomName = orderBodyDO.getRoomName();
        String bodyName = orderBodyDO.getName();

        Page<OrderImportTempDataDO> page = new Page<>(1, BATCH_THRESHOLD_NUMBER);
        orderImportTempDataMapper.selectList(page, new LambdaQueryWrapperX<OrderImportTempDataDO>()
                .eq(OrderImportTempDataDO::getTaskId, taskId)
                .eq(OrderImportTempDataDO::getType, PLATE_TYPE)
                .eq(OrderImportTempDataDO::getRoomName, roomName)
                .eq(OrderImportTempDataDO::getBodyName, bodyName)
                .eqIfPresent(OrderImportTempDataDO::getGroupTypeName, groupTypeName)
                .eqIfPresent(OrderImportTempDataDO::getGroupName, groupName)
                .eq(OrderImportTempDataDO::getOrganId, organId), new ResultHandler<>() {
            int count = 0;

            @Override
            public void handleResult(ResultContext<? extends OrderImportTempDataDO> resultContext) {
                OrderImportTempDataDO tempDataDO = resultContext.getResultObject();

                int num = tempDataDO.getNum().intValue();
                String detail = JsonUtils.unzipString(tempDataDO.getDetail());
                OrderPlateImportExcelVO combination = JSON.parseObject(detail, OrderPlateImportExcelVO.class);
                // 根据数量生成num个小板数据
                for (int i = 0; i < num; i++) {
                    long plateNo = idWorker.nextId();
                    long obtainingTime = idWorker.obtainingTime();
                    long goodsId = Long.parseLong(tempDataDO.getInnerGoodsId());
                    // 成品宽
                    String width = combination.getWidth();
                    // 成品长
                    String height = combination.getHeight();
                    // 计算面积
                    BigDecimal area = BigDecimal.valueOf(Double.parseDouble(width))
                            .multiply(BigDecimal.valueOf(Double.parseDouble(height)))
                            .movePointLeft(6)
                            .setScale(2, RoundingMode.HALF_UP);
                    Long plateId = (Long) snowFlakeGenerator.nextId(null);
                    // 排版面 纹路 开门方向转换
                    DictDataRespDTO typographyDTO = dictDataApi.parseDictData(DictTypeConstants.TYPOGRAPHY_TYPE, combination.getTypographicFace()).getData();// 排版面
                    DictDataRespDTO grainDTO = dictDataApi.parseDictData(DictTypeConstants.GRAIN_TYPE, combination.getTexture()).getData();// 纹路
                    DictDataRespDTO doorDTO = dictDataApi.parseDictData(DictTypeConstants.DOOR_OPENING_DIRECTIONS, combination.getOpenDoorType()).getData();

                    PlateDO plateDO = PlateDO.builder()
                            .id(plateId)
                            .orderId(orderId)
                            .name(combination.getName())
                            .plateNo(combination.getPlateNo())
                            .type(OrderPlateTypeEnum.LAYERBOARD.getType())
                            .goodsId(goodsId)
                            .width(BigDecimal.valueOf(Double.parseDouble(width)))
                            .plateNo(((obtainingTime) + Long.toString(plateNo).substring(2)))
                            .height(BigDecimal.valueOf(Double.parseDouble(height)))
                            .thickness(BigDecimal.valueOf(Double.parseDouble(combination.getThickness())))
                            .splitWidth(BigDecimal.valueOf(NumberUtil.parseDouble(combination.getSplitWidth())))
                            .splitHeight(BigDecimal.valueOf(NumberUtil.parseDouble(combination.getSplitHeight())))
                            .splitThickness(BigDecimal.valueOf(Double.parseDouble(tempDataDO.getThickness())))
                            .sealLeft(BigDecimal.valueOf(Double.parseDouble(combination.getSealLeft())))
                            .sealRight(BigDecimal.valueOf(Double.parseDouble(combination.getSealRight())))
                            .sealUp(BigDecimal.valueOf(Double.parseDouble(combination.getSealUp())))
                            .sealDown(BigDecimal.valueOf(Double.parseDouble(combination.getSealDown())))
                            .holeFace(Integer.valueOf(typographyDTO.getValue()))
                            .texture(Integer.valueOf(grainDTO.getValue()))
                            .area(area)
                            .openDoorType(Integer.valueOf(doorDTO.getValue()))
                            .isSpecialShaped(false)
                            .isSculpt(false)
                            .remark(remarkExtract(combination.remarkJSON()))
                            .roomName(roomName)
                            .bodyName(bodyName)
                            .customPlateNoBuilder(new StringBuilder())
                            .organId(organId)
                            .holeArrange(0)
                            .holeFace(0)
                            .unregularPointCount(0)
                            .frontHoleCount(0)
                            .backHoleCount(0)
                            .sideHoleCount(0)
                            .frontModelCount(0)
                            .backModelCount(0)
                            .isDoor(false)
                            .offsetX(BIG_ZERO)
                            .offsetY(BIG_ZERO)
                            .isArcAcross(false)
                            .moduleTypeId(0L)
                            .isRowHole(false)
                            .isOptimized(false)
                            .isCutted(0)
                            .isCancel(false)
                            .filterType(EMPTY_STRING)
                            .deleted(false)
                            .build();
                    plateDO.setCreator(operatorName);
                    plateDO.setUpdater(operatorName);
                    LocalDateTime now = LocalDateTime.now();
                    plateDO.setCreateTime(now);
                    plateDO.setUpdateTime(now);

                    // 生成自定义板编号
                    generateCustomPlateNo(plateDO);

                    // 批量插入order_plate
                    plateDOS.add(plateDO);
                    orderInfoBatchInsertWithinThreshold(plateMapper, plateDOS, false);

                    OrderItemDO orderItemDO = OrderItemDO.builder()
                            .orderId(orderId)
                            .type(OrderItemTypeEnum.PLATE_ITEM.getStatus())
                            .roomId(orderBodyDO.getRoomId())
                            .bodyId(orderBodyDO.getId())
                            .plateId(plateId)
                            .num(1.0)
                            .groupId(StringUtils.isNotEmpty(groupTypeName) ? groupId : 0L)
                            .organId(organId)
                            .packageId(0L)
                            .partsId(0L)
                            .build();
                    // 批量插入order_item
                    orderItemDOS.add(orderItemDO);
                    orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, false);

                    // 批量插入CAD板件信息
                    OrderModelDO orderModelDO = OrderModelDO.builder()
                            .orderId(orderId)
                            .batchId(batchId)
                            .plateId(plateId)
                            .typographicFace(Integer.valueOf(typographyDTO.getValue()))
                            .texture(plateDO.getTexture())
                            .openDoorType(plateDO.getOpenDoorType())
                            .build();

                    // 查询大板id用于小板轮廓goodsId
                    GoodsDO goodsDO = goodsMapper.selectById(goodsId);
                    if (ObjectUtil.isNull(goodsDO)) {
                        throw ServiceExceptionUtil.exception(ORDER_IMPORT_PLATE_GOODS_NOT_EXISTS, orderId, goodsId);
                    }
                    orderModelDO.setGoodsId(goodsDO.getGoodsId());
                    orderModelDO.setPlateGoodsId(goodsId);
                    orderModelDO.setOrganId(organId);
                    orderModelDO.setCreator(operatorName);
                    orderModelDO.setUpdater(operatorName);
                    orderModelDOS.add(orderModelDO);

                    // 批量插入造型数据
                    orderModelsBatchInsertWithinThreshold(false);
                }
            }
        });


//        OrderImportTempDataReqVO groupNameListReqVO = OrderImportTempDataReqVO.builder().type(PLATE_TYPE).taskId(taskId).roomName(roomName).bodyName(orderBodyDO.getName()).groupTypeName(groupTypeName).groupName(groupName).build();
//        // 查询房间、柜体、加工组类型名称、加工组名称下的数量
//        int countGroupName = orderImportTempDataMapper.selectCountGroupName(groupNameListReqVO);
//        // 计算页码
//        int pageNum = PageUtil.totalPage(countGroupName, BATCH_THRESHOLD_NUMBER);
//        // 分页查询临时表
//        for (int page = 1; page <= pageNum; page++) {
//            OrderImportTempDataReqVO groupNamePageReqVO = groupNameListReqVO.setDoPaging(true).setOffset((page - 1) * BATCH_THRESHOLD_NUMBER).setSize(BATCH_THRESHOLD_NUMBER);
//            List<OrderImportTempDataDO> groupNameList = orderImportTempDataMapper.selectGroupNameList(groupNamePageReqVO);
//            for (OrderImportTempDataDO tempDataDO : groupNameList) {
//                int num = tempDataDO.getNum().intValue();
//                String detail = JsonUtils.unzipString(tempDataDO.getDetail());
//                OrderPlateImportExcelVO combination = JSON.parseObject(detail, OrderPlateImportExcelVO.class);
//                // 根据数量生成num个小板数据
//                for (int i = 0; i < num; i++) {
//                    long plateNo = idWorker.nextId();
//                    long obtainingTime = idWorker.obtainingTime();
//                    long goodsId = Long.parseLong(tempDataDO.getInnerGoodsId());
//                    // 成品宽
//                    String width = combination.getWidth();
//                    // 成品长
//                    String height = combination.getHeight();
//                    // 计算面积
//                    BigDecimal area = BigDecimal.valueOf(Double.parseDouble(width))
//                            .multiply(BigDecimal.valueOf(Double.parseDouble(height)))
//                            .movePointLeft(6)
//                            .setScale(2, RoundingMode.HALF_UP);
//                    Long plateId = (Long) snowFlakeGenerator.nextId(null);
//                    // 排版面 纹路 开门方向转换
//                    DictDataRespDTO typographyDTO = dictDataApi.parseDictData(DictTypeConstants.TYPOGRAPHY_TYPE, combination.getTypographicFace()).getData();// 排版面
//                    DictDataRespDTO grainDTO = dictDataApi.parseDictData(DictTypeConstants.GRAIN_TYPE, combination.getTexture()).getData();// 纹路
//                    DictDataRespDTO doorDTO = dictDataApi.parseDictData(DictTypeConstants.DOOR_OPENING_DIRECTIONS, combination.getOpenDoorType()).getData();
//
//                    PlateDO plateDO = PlateDO.builder()
//                            .id(plateId)
//                            .orderId(orderId)
//                            .name(combination.getName())
//                            .plateNo(combination.getPlateNo())
//                            .type(OrderPlateTypeEnum.LAYERBOARD.getType())
//                            .goodsId(goodsId)
//                            .width(BigDecimal.valueOf(Double.parseDouble(width)))
//                            .plateNo(((obtainingTime) + Long.toString(plateNo).substring(2)))
//                            .height(BigDecimal.valueOf(Double.parseDouble(height)))
//                            .thickness(BigDecimal.valueOf(Double.parseDouble(combination.getThickness())))
//                            .splitWidth(BigDecimal.valueOf(NumberUtil.parseDouble(combination.getSplitWidth())))
//                            .splitHeight(BigDecimal.valueOf(NumberUtil.parseDouble(combination.getSplitHeight())))
//                            .splitThickness(BigDecimal.valueOf(Double.parseDouble(tempDataDO.getThickness())))
//                            .sealLeft(BigDecimal.valueOf(Double.parseDouble(combination.getSealLeft())))
//                            .sealRight(BigDecimal.valueOf(Double.parseDouble(combination.getSealRight())))
//                            .sealUp(BigDecimal.valueOf(Double.parseDouble(combination.getSealUp())))
//                            .sealDown(BigDecimal.valueOf(Double.parseDouble(combination.getSealDown())))
//                            .holeFace(Integer.valueOf(typographyDTO.getValue()))
//                            .texture(Integer.valueOf(grainDTO.getValue()))
//                            .area(area)
//                            .openDoorType(Integer.valueOf(doorDTO.getValue()))
//                            .isSpecialShaped(false)
//                            .isSculpt(false)
//                            .remark(remarkExtract(combination.remarkJSON()))
//                            .roomName(roomName)
//                            .bodyName(bodyName)
//                            .customPlateNoBuilder(new StringBuilder())
//                            .organId(organId)
//                            .holeArrange(0)
//                            .holeFace(0)
//                            .unregularPointCount(0)
//                            .frontHoleCount(0)
//                            .backHoleCount(0)
//                            .sideHoleCount(0)
//                            .frontModelCount(0)
//                            .backModelCount(0)
//                            .isDoor(false)
//                            .offsetX(BIG_ZERO)
//                            .offsetY(BIG_ZERO)
//                            .isArcAcross(false)
//                            .moduleTypeId(0L)
//                            .isRowHole(false)
//                            .isOptimized(false)
//                            .isCutted(0)
//                            .isCancel(false)
//                            .filterType(EMPTY_STRING)
//                            .deleted(false)
//                            .build();
//                    plateDO.setCreator(operatorName);
//                    plateDO.setUpdater(operatorName);
//                    LocalDateTime now = LocalDateTime.now();
//                    plateDO.setCreateTime(now);
//                    plateDO.setUpdateTime(now);
//
//                    // 生成自定义板编号
//                    generateCustomPlateNo(plateDO);
//
//                    // 批量插入order_plate
//                    plateDOS.add(plateDO);
//                    orderInfoBatchInsertWithinThreshold(plateMapper, plateDOS, false);
//
//                    OrderItemDO orderItemDO = OrderItemDO.builder()
//                            .orderId(orderId)
//                            .type(OrderItemTypeEnum.PLATE_ITEM.getStatus())
//                            .roomId(orderBodyDO.getRoomId())
//                            .bodyId(orderBodyDO.getId())
//                            .plateId(plateId)
//                            .num(1.0)
//                            .groupId(StringUtils.isNotEmpty(groupTypeName) ? groupId : 0L)
//                            .organId(organId)
//                            .packageId(0L)
//                            .partsId(0L)
//                            .build();
//                    // 批量插入order_item
//                    orderItemDOS.add(orderItemDO);
//                    orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, false);
//
//                    // 批量插入CAD板件信息
//                    OrderModelDO orderModelDO = OrderModelDO.builder()
//                            .orderId(orderId)
//                            .plateId(plateId)
//                            .typographicFace(Integer.valueOf(typographyDTO.getValue()))
//                            .texture(plateDO.getTexture())
//                            .openDoorType(plateDO.getOpenDoorType())
//                            .build();
//
//                    // 查询大板id用于小板轮廓goodsId
//                    GoodsDO goodsDO = goodsMapper.selectById(goodsId);
//                    if (ObjectUtil.isNull(goodsDO)) {
//                        throw ServiceExceptionUtil.exception(ORDER_IMPORT_PLATE_GOODS_NOT_EXISTS, orderId, goodsId);
//                    }
//                    orderModelDO.setGoodsId(goodsDO.getGoodsId());
//                    orderModelDO.setPlateGoodsId(goodsId);
//                    orderModelDO.setOrganId(organId);
//                    orderModelDO.setCreator(operatorName);
//                    orderModelDO.setUpdater(operatorName);
//                    orderModelDOS.add(orderModelDO);
//
//                    // 批量插入造型数据
//                    orderModelsBatchInsertWithinThreshold(false);
//                }
//            }
//        }
    }

    /**
     * 生成自定义板编号
     *
     * @param plateDO
     */
    private void generateCustomPlateNo(PlateDO plateDO) {
        if (!isFirstPlate) {
            isFirstPlate = true;
        }
        // 配置不为空时，生成自定义板编号
        if (ObjectUtil.isNotNull(plateNoGenerateConfigVO)) {
            customPlateNoGenerateService.generateCustomPlateNo(orderId, plateDO, plateNoGenerateConfigVO, isFirstPlate);
        }
    }

    /**
     * 每达到阈值就批量插入一次生产单造型数据和压缩数据
     *
     * @param isLast 是否最后一次插入，不是就需要清理list
     */
    private void orderModelsBatchInsertWithinThreshold(boolean isLast) {
        // 达到批量的阈值就做一次插入
        if (CollUtil.isNotEmpty(orderModelDOS) && (orderModelDOS.size() >= BATCH_THRESHOLD_NUMBER || isLast)) {
            // 保存生产单造型数据
            orderInputProcessor.batchSaveModel(orderModelDOS);
            if (!isLast) {
                // 存储完成清理 list
                orderModelDOS = ListUtils.newArrayListWithExpectedSize(BATCH_THRESHOLD_NUMBER);
            }
        }
    }

    /**
     * 分页解析配件orderItem
     *
     * @param orderBodyDO
     * @param groupTypeName
     * @param groupName
     * @param groupId
     */
    private void analyzePart(OrderBodyDO orderBodyDO, String groupTypeName, String groupName, Long groupId) {
        String roomName = orderBodyDO.getRoomName();
        String bodyName = orderBodyDO.getName();
        Long itemGroupId = StringUtils.isNotEmpty(groupTypeName) ? groupId : 0L;
        Long roomId = StringUtils.isNotEmpty(roomName) ? orderBodyDO.getRoomId() : 0L;
        Long bodyId = StringUtils.isNotEmpty(bodyName) ? orderBodyDO.getId() : 0L;
        OrderImportTempDataReqVO groupNameListReqVO = OrderImportTempDataReqVO.builder().type(PART_TYPE).taskId(taskId).roomName(roomName).bodyName(bodyName).groupTypeName(groupTypeName).groupName(groupName).build();
        // 查询房间、柜体、加工组类型名称、加工组名称下的数量
        int countGroupName = orderImportTempDataMapper.selectCountGroupName(groupNameListReqVO);
        // 计算页码
        int pageNum = PageUtil.totalPage(countGroupName, BATCH_THRESHOLD_NUMBER);
        // 分页查询临时表
        for (int page = 1; page <= pageNum; page++) {
            OrderImportTempDataReqVO groupNamePageReqVO = groupNameListReqVO.setDoPaging(true).setOffset((page - 1) * BATCH_THRESHOLD_NUMBER).setSize(BATCH_THRESHOLD_NUMBER);
            List<OrderImportTempDataDO> groupNameList = orderImportTempDataMapper.selectGroupNameList(groupNamePageReqVO);
            for (OrderImportTempDataDO tempDataDO : groupNameList) {
                String detail = JsonUtils.unzipString(tempDataDO.getDetail());
                OrderPlateImportExcelVO combination = JSON.parseObject(detail, OrderPlateImportExcelVO.class);
                OrderItemDO orderItemDO = OrderItemDO.builder().orderId(orderId)
                        .type(OrderItemTypeEnum.PARTS_ITEM.getStatus())
                        .roomId(roomId)
                        .bodyId(bodyId)
                        .partsId(Long.parseLong(tempDataDO.getInnerGoodsId()))
                        .groupId(itemGroupId)
                        .num(Double.valueOf(combination.getGoodsNumber()))
                        .organId(organId)
                        .packageId(0L)
                        .plateId(0L)
                        .build();
                // 批量插入order_item
                orderItemDOS.add(orderItemDO);
                orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, false);
            }
        }
    }

    /**
     * 每达到阈值就批量插入一次
     *
     * @param baseBatchMapper
     * @param list
     * @param isLast          是否最后一次插入，不是就需要清理list
     */
    private void orderInfoBatchInsertWithinThreshold(BaseBatchMapper baseBatchMapper, List list, boolean isLast) {
        // 达到批量的阈值就做一次插入
        if (CollUtil.isNotEmpty(list) && (list.size() >= BATCH_THRESHOLD_NUMBER || isLast)) {
            baseBatchMapper.insertBatchSomeColumn(list);
            if (!isLast) {
                // 存储完成清理 list
                list.clear();
            }
        }
    }

    /**
     * 创建生产单柜体orderBody
     *
     * @param roomName
     * @param roomId
     * @param groupDO
     * @return
     */
    private OrderBodyDO createOrderBodyDO(String roomName, Long roomId, OrderImportTempDataGoodsGroupDO groupDO) {
        OrderBodyDO orderBodyDO = OrderBodyDO.builder()
                .id((Long) snowFlakeGenerator.nextId(null))
                .orderId(orderId)
                .roomId(roomId)
                .roomName(roomName)
                .name(groupDO.getBodyName())
                .width(0.0)
                .height(0.0)
                .depth(0.0)
                .multiNum(0)
                .unregularNum(0)
                .filename("无")
                .remark("无")
                .organId(organId)
                .plateNum(groupDO.getBodyPlateNum())
                .deleted(false)
                .build();
        orderBodyDO.setCreator(operatorName);
        orderBodyDO.setUpdater(operatorName);
        LocalDateTime now = LocalDateTime.now();
        orderBodyDO.setCreateTime(now);
        orderBodyDO.setUpdateTime(now);
        return orderBodyDO;
    }

    /**
     * 创建生产单加工组orderGroup
     *
     * @param bodyId
     * @param groupTypeName
     * @param groupTypeId
     * @param groupDO
     * @return
     */
    private OrderGroupDO createOrderGroupDO(Long bodyId, String groupTypeName, Long groupTypeId, OrderImportTempDataGoodsGroupDO groupDO) {
        String groupName = groupDO.getGroupName();
        OrderGroupDO orderGroupDO = OrderGroupDO.builder()
                .id((Long) snowFlakeGenerator.nextId(null))
                .orderId(orderId)
                .organId(organId)
                .bodyId(bodyId)
                .groupTypeId(groupTypeId)
                .groupTypeName(groupTypeName)
                .name(StringUtils.isNotEmpty(groupName) ? groupName : groupTypeName)
                .width(0.0)
                .height(0.0)
                .depth(0.0)
                .multiNum(0)
                .plateNum(groupDO.getGroupNameNum())
                .unregularNum(0)
                .filename("无")
                .remark("无")
                .deleted(false)
                .build();
        orderGroupDO.setCreator(operatorName);
        orderGroupDO.setUpdater(operatorName);
        LocalDateTime now = LocalDateTime.now();
        orderGroupDO.setCreateTime(now);
        orderGroupDO.setUpdateTime(now);
        return orderGroupDO;
    }

    /**
     * 创建生产单设计商品orderRawGoods
     *
     * @param goodsId
     * @param groupDO
     * @return
     */
    private RawGoodsDO createRawGoodsDO(String goodsId, OrderImportTempDataGoodsGroupDO groupDO) {
        RawGoodsDO rawGoodsDO = RawGoodsDO.builder()
                .id((Long) snowFlakeGenerator.nextId(null))
                .orderId(orderId)
                .organId(organId)
                .rawGoodsId(goodsId)
                .goodsName(groupDO.getGoodsName())
                .material(groupDO.getMaterial())
                .texture(Boolean.valueOf(groupDO.getWave()))
                .color(groupDO.getColor())
                .colorBlack(EMPTY_STRING)
                .price(0.00)
                .thickness(Double.valueOf(groupDO.getThickness()))
                .spec(StringUtils.isNotEmpty(groupDO.getSpec()) ? groupDO.getSpec() : EMPTY_STRING)
                .brand(StringUtils.isNotEmpty(groupDO.getBrand()) ? groupDO.getBrand() : EMPTY_STRING)
                .deleted(false)
                .build();
        rawGoodsDO.setCreator(operatorName);
        rawGoodsDO.setUpdater(operatorName);
        LocalDateTime now = LocalDateTime.now();
        rawGoodsDO.setCreateTime(now);
        rawGoodsDO.setUpdateTime(now);
        return rawGoodsDO;
    }

    /**
     * 创建生产单商品orderGoods
     *
     * @param groupDO
     * @return
     */
    private GoodsDO createGoodsDO(OrderImportTempDataGoodsGroupDO groupDO) {
        GoodsDO goodsDO = GoodsDO.builder()
                .id((Long) snowFlakeGenerator.nextId(null))
                .orderId(orderId)
                .organId(organId)
                .goodsName(groupDO.getGoodsName())
                .material(groupDO.getMaterial())
                .texture(Boolean.valueOf(groupDO.getWave()))
                .color(groupDO.getColor())
                .width(BigDecimal.valueOf(NumberUtil.parseDouble(groupDO.getWidth())))
                .height(BigDecimal.valueOf(NumberUtil.parseDouble(groupDO.getHeight())))
                .thickness(BigDecimal.valueOf(Double.valueOf(groupDO.getThickness())))
                .spec(StringUtils.isNotEmpty(groupDO.getSpec()) ? groupDO.getSpec() : EMPTY_STRING)
                .brand(StringUtils.isNotEmpty(groupDO.getBrand()) ? groupDO.getBrand() : EMPTY_STRING)
                .planId(0L)
                .colorBlack(EMPTY_STRING)
                .price(0.00)
                .remark(EMPTY_STRING)
                .deleted(false)
                .build();
        goodsDO.setCreator(operatorName);
        goodsDO.setUpdater(operatorName);
        LocalDateTime now = LocalDateTime.now();
        goodsDO.setCreateTime(now);
        goodsDO.setUpdateTime(now);
        return goodsDO;
    }

    /**
     * 创建生产单配件orderParts
     *
     * @param goodsId
     * @param groupDO
     * @return
     */
    private OrderPartsDO createOrderParts(String goodsId, OrderImportTempDataGoodsGroupDO groupDO) {
        String remark = EMPTY_STRING;
        // 查询配件下第一项，构建备注
        OrderImportTempDataDO orderPartTempData = orderImportTempDataMapper.selectOne(new LambdaQueryWrapperX<OrderImportTempDataDO>()
                .eq(OrderImportTempDataDO::getTaskId, taskId)
                .eq(OrderImportTempDataDO::getType, PART_TYPE)
                .eqIfPresent(OrderImportTempDataDO::getOuterGoodsId, goodsId)
                .eqIfPresent(OrderImportTempDataDO::getGoodsName, groupDO.getGoodsName())
                .eqIfPresent(OrderImportTempDataDO::getMaterial, groupDO.getMaterial())
                .eqIfPresent(OrderImportTempDataDO::getColor, groupDO.getColor())
                .eqIfPresent(OrderImportTempDataDO::getIsComposite, groupDO.getIsComposite())
                .eqIfPresent(OrderImportTempDataDO::getCategory, groupDO.getCategory())
                .eqIfPresent(OrderImportTempDataDO::getSubType, groupDO.getSubType())
                .eqIfPresent(OrderImportTempDataDO::getFactory, groupDO.getFactory())
                .eqIfPresent(OrderImportTempDataDO::getModel, groupDO.getModel())
                .eqIfPresent(OrderImportTempDataDO::getSpec, groupDO.getSpec())
                .eqIfPresent(OrderImportTempDataDO::getHeight, groupDO.getHeight())
                .eqIfPresent(OrderImportTempDataDO::getWidth, groupDO.getWidth())
                .eqIfPresent(OrderImportTempDataDO::getThickness, groupDO.getThickness())
                .eqIfPresent(OrderImportTempDataDO::getUnit, groupDO.getUnit())
                .eqIfPresent(OrderImportTempDataDO::getSort, groupDO.getSortn()));
        if (ObjectUtil.isNotNull(orderPartTempData)) {
            String detail = orderPartTempData.getDetail();
            if (StringUtils.isNotEmpty(detail)) {
                OrderPlateImportExcelVO combination = JSON.parseObject(JsonUtils.unzipString(detail), OrderPlateImportExcelVO.class);
                remark = remarkExtract(combination.remarkJSON());
            }
        }
        OrderPartsDO orderPartsDO = OrderPartsDO.builder()
                .id((Long) snowFlakeGenerator.nextId(null))
                .orderId(orderId)
                .color(groupDO.getColor())
                .category(groupDO.getCategory())
                .type(StringUtils.isEmpty(groupDO.getSubType()) ? EMPTY_STRING : groupDO.getSubType())
                .goodsId(goodsId)
                .length(Double.valueOf(StringUtils.isEmpty(groupDO.getHeight()) ? "0" : groupDO.getHeight()))
                .width(Double.valueOf(StringUtils.isEmpty(groupDO.getWidth()) ? "0" : groupDO.getWidth()))
                .thickness(Double.valueOf(StringUtils.isEmpty(groupDO.getThickness()) ? "0" : groupDO.getThickness()))
                .isComposite(Boolean.valueOf(groupDO.getIsComposite()))
                .name(groupDO.getGoodsName())
                .material(groupDO.getMaterial())
                .model(StringUtils.isNotEmpty(groupDO.getModel()) ? groupDO.getModel() : EMPTY_STRING)
                .spec(StringUtils.isNotEmpty(groupDO.getSpec()) ? groupDO.getSpec() : EMPTY_STRING)
                .brand(StringUtils.isNotEmpty(groupDO.getBrand()) ? groupDO.getBrand() : EMPTY_STRING)
                .factory(StringUtils.isNotEmpty(groupDO.getFactory()) ? groupDO.getFactory() : EMPTY_STRING)
                .unit(groupDO.getUnit()).price(0.0)
                .subparts(EMPTY_STRING)
                .remark(remark)
                .deleted(false).organId(organId)
                .build();
        orderPartsDO.setCreator(operatorName);
        orderPartsDO.setUpdater(operatorName);
        LocalDateTime now = LocalDateTime.now();
        orderPartsDO.setCreateTime(now);
        orderPartsDO.setUpdateTime(now);
        return orderPartsDO;
    }

    /**
     * 生成备注
     *
     * @param remark
     * @return
     */
    private String remarkExtract(String remark) {
        JSONObject jsonObject = new JSONObject(remark);
        List<Object> nonNullValues = new ArrayList<>();

        for (String key : jsonObject.keySet()) {
            Object value = jsonObject.get(key);
            if (value != null && !value.toString().trim().isEmpty()) {
                nonNullValues.add(value);
            }

        }

        return nonNullValues.size() == 0 ? "" : nonNullValues.toString().replace("[", "").replace("]", "");
    }

    /**
     * 解析大板
     * 大板库没有新增，有就赋值goodsId
     *
     * @param goodsDO
     */
    private void analyzePlateGoods(GoodsDO goodsDO) {
        PlateGoodDO plateGoodDO = null;
        List<PlateGoodDO> existPlateGoodDOS = new ArrayList<>();
        String goodsId = goodsDO.getGoodsId();
        String goodsName = goodsDO.getGoodsName();
        String material = goodsDO.getMaterial();
        String color = goodsDO.getColor();
        BigDecimal thickness = goodsDO.getThickness();
        String brand = goodsDO.getBrand();

        if (StringUtils.isNotEmpty(goodsId)) {
            // goodsId查询是否存在大板
            plateGoodDO = getPlateGood(goodsId);
        } else {
            // 没有goodsId，大板属性匹配大板
            existPlateGoodDOS = plateGoodMapper.selectList(new LambdaQueryWrapperX<PlateGoodDO>()
                    .eq(PlateGoodDO::getGoodsName, goodsName)
                    .eq(PlateGoodDO::getMaterial, material)
                    .eq(PlateGoodDO::getColor, color)
                    .eq(PlateGoodDO::getThickness, thickness)
                    .eqIfPresent(PlateGoodDO::getBrand, brand)
                    .eq(PlateGoodDO::getDeleted, 0)
                    .eq(PlateGoodDO::getOrganId, organId));
        }

        if (CollUtil.isNotEmpty(existPlateGoodDOS)) {
            // 存在大板
            goodsDO.setGoodsId(existPlateGoodDOS.get(0).getGoodsId());
        } else if (plateGoodDO != null) {
            // 存在大板
            goodsDO.setGoodsId(plateGoodDO.getGoodsId());
        } else {
            throw ServiceExceptionUtil.exception(ORDER_IMPORT_PLATE_GOODS_NOMATCH_ERROR, goodsId, goodsName, material, color, thickness, brand);
        }
    }

    /**
     * 查询大板信息
     *
     * @param goodsId
     * @return
     */
    private PlateGoodDO getPlateGood(String goodsId) {
        List<PlateGoodDO> plateGoodDOs = plateGoodMapper.selectGoodOne(goodsId, organId);
        if (!plateGoodDOs.isEmpty()) {
            return plateGoodDOs.get(0);
        }
        return null;
    }


    /**
     * 解析配件
     * 配件库没有新增，有就赋值goodsId
     *
     * @param partsDO
     * @return
     */
//    private void analyzePartsGoods(OrderPartsDO partsDO) {
//        if (partsDO.getGoodsId() != null && !partsDO.getGoodsId().isEmpty()) { // 有goodsId
//            PartsDO parts = partsMapper.selectByGoodID(partsDO.getGoodsId(), OrganContextHolder.getOrganId());
//            if (ObjectUtil.isNull(parts)) { // 不存在记录，存入数据库
//                // 批量插入parts
//                partsDOS.add(BeanUtils.toBean(partsDO, PartsDO.class).setOrganId(organId));
//                orderInfoBatchInsertWithinThreshold(partsMapper, partsDOS, false);
//            }
//        }
//    }

    /**
     * 清空所有列表
     */
    private void clearAll() {
        rawGoodsDOS.clear();
        goodsDOS.clear();
        orderPartsDOS.clear();
        orderBodyDOS.clear();
        orderGroupDOS.clear();
        plateDOS.clear();
        orderItemDOS.clear();
        plateGoodDOS.clear();
        orderModelDOS.clear();
        orderPartsRemarks.clear();
//        partsDOS.clear();
    }

    /**
     * 移除taskId下所有临时数据
     */
    private void deleteTempData() {
        orderImportTempDataMapper.delete(new LambdaQueryWrapper<OrderImportTempDataDO>().eq(OrderImportTempDataDO::getTaskId, taskId));
    }

    /**
     * 更新为导入成功
     */
    private void updateTaskSuccess() {
        orderImportTaskMapper.update(new LambdaUpdateWrapper<OrderImportTaskDO>().eq(OrderImportTaskDO::getId, taskId).set(OrderImportTaskDO::getImportStatus, OrderImportStatusEnum.IMPORT_SUCCESS.getStatus()));
    }
}
