package com.wms.utils.excel.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.wms.constants.enums.ConfigMapKeyEnum;
import com.wms.entity.table.*;
import com.wms.service.*;
import com.wms.utils.StringUtils;
import com.wms.utils.excel.vo.KateOrdersExcelVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.*;

import static com.wms.config.InitLocalConfig.configMap;
import static com.wms.utils.WmsUtils.generateId;

/**
 * 上传库存监听
 */
public class UploadKateOrdersListener implements ReadListener<KateOrdersExcelVo> {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 每隔5条存储数据库，实际使用中可以1000条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 1000;
    private List<KateOrdersExcelVo> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 筛选工单字符串
     */
    private final String slocFilterString = configMap.get(ConfigMapKeyEnum.SLOC_FILTER_STRING.getConfigKey());
    private final KateOrdersService kateOrdersService;// Dbs服务
    private final String uploadUser;// 用户
    private final Map<String, KateOrders> oldKateOrdersMap;// 旧的工单数据
    private final Map<String, KateOrders> newKateOrdersMap = new HashMap<>();// 新的工单数据
    public UploadKateOrdersListener(KateOrdersService kateOrdersService, Map<String, KateOrders> oldKateOrdersMap, String uploadUser) {
        this.kateOrdersService = kateOrdersService;
        this.oldKateOrdersMap = oldKateOrdersMap;
        this.uploadUser = uploadUser;
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        int rowCount = context.readRowHolder().getRowIndex() + 1;
        logger.error("处理工单数据发生异常，第{}行发生异常。", rowCount);
        throw new Exception("第" + rowCount + "行数据异常。");
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param kateOrdersExcelVo    one row value. It is same as {@link AnalysisContext#readRowHolder()}
     * @param analysisContext context
     */
    @Override
    public void invoke(KateOrdersExcelVo kateOrdersExcelVo, AnalysisContext analysisContext) {
        if (StringUtils.isNotEmpty(slocFilterString) && Objects.equals(kateOrdersExcelVo.getSortString(), slocFilterString)) {
            // 符合筛选字符串
            if (StringUtils.isNotEmpty(kateOrdersExcelVo.getWorkOrder())
            && StringUtils.isNotEmpty(kateOrdersExcelVo.getGoodsId())
            && StringUtils.isNotEmpty(kateOrdersExcelVo.getSortString())
            && StringUtils.isNotEmpty(kateOrdersExcelVo.getSupplyArea())
            && kateOrdersExcelVo.getRequirementQuantity() != null) {
                // 符合条件
                cachedDataList.add(kateOrdersExcelVo);
            }
        }
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param analysisContext context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 再做一次数据处理
        saveData();
        // 在这里统一保存数据
        insertIntoDb();
    }

    /**
     * 存储数据
     */
    private void saveData() {
        for (KateOrdersExcelVo kateOrdersExcelVo : cachedDataList) {
            String key = kateOrdersExcelVo.getWorkOrder() + kateOrdersExcelVo.getGoodsId() + kateOrdersExcelVo.getSupplyArea();
            if (newKateOrdersMap.containsKey(key)) {
                KateOrders currentOrder = newKateOrdersMap.get(key);
                // 设定数量
                currentOrder.setRequirementQuantity(currentOrder.getRequirementQuantity().add(kateOrdersExcelVo.getRequirementQuantity()));
                currentOrder.setLackQuantity(currentOrder.getLackQuantity().add(kateOrdersExcelVo.getRequirementQuantity()));
                newKateOrdersMap.replace(key, currentOrder);
                continue;
            }
            // 查询数据库是否存在重复数据
            if (!oldKateOrdersMap.containsKey(key)) {
                // 之前没存在过
                KateOrders newKateOrders = new KateOrders();
                newKateOrders.setOrderId(generateId("ORDER_"));
                newKateOrders.setWorkOrder(kateOrdersExcelVo.getWorkOrder());
                newKateOrders.setGoodsId(kateOrdersExcelVo.getGoodsId());
                newKateOrders.setItem(kateOrdersExcelVo.getItem());
                newKateOrders.setDescription(kateOrdersExcelVo.getDescription());
                newKateOrders.setSLoc(kateOrdersExcelVo.getSLoc());
                newKateOrders.setType(kateOrdersExcelVo.getType());
                newKateOrders.setOriginStatus(kateOrdersExcelVo.getOriginStatus());
                newKateOrders.setSupplyArea(kateOrdersExcelVo.getSupplyArea());
                newKateOrders.setSortString(kateOrdersExcelVo.getSortString());
                newKateOrders.setRequirementQuantity(kateOrdersExcelVo.getRequirementQuantity());
                newKateOrders.setGoodsUnit(kateOrdersExcelVo.getGoodsUnit());
                newKateOrders.setOrderStatus(0);
                newKateOrders.setLackQuantity(kateOrdersExcelVo.getRequirementQuantity());
                newKateOrders.setPickedQuantity(BigDecimal.ZERO);
                newKateOrders.setUserName(uploadUser);
                newKateOrdersMap.put(key, newKateOrders);
            }
        }
    }

    /**
     * 保存数据库
     */
    private void insertIntoDb() {
        logger.info("此次共导入{}条数据。", newKateOrdersMap.size());
        // 保存数据
        kateOrdersService.saveOrUpdateBatch(newKateOrdersMap.values(), BATCH_COUNT);
        logger.info("保存成功{}条数据。", newKateOrdersMap.size());
    }
}
