package excel.costfirst;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.bailuntec.domain.entity.DcBaseSku;
import com.bailuntec.domain.entity.DcMidCostFirst;
import com.bailuntec.domain.example.DcBaseSkuExample;
import com.bailuntec.mapper.DcBaseSkuMapper;
import com.bailuntec.mapper.DcBaseStockMapper;
import com.bailuntec.mapper.DcMidCostFirstMapper;
import com.bailuntec.utils.SessionUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 *
 * </p>
 *
 * @author robbendev
 * @since 2020/9/1 4:46 下午
 */
@Slf4j
public class CostFirstListener extends AnalysisEventListener<CostFirst> {

    private static final Logger LOGGER = LoggerFactory.getLogger(CostFirstListener.class);

    /**
     * 每隔5条存储数据库，实际使用中可以3000条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 1000;

    List<CostFirst> list = new ArrayList<>();


    @Override
    public void invoke(CostFirst data, AnalysisContext context) {
        LOGGER.info("解析到一条数据:{}", JSON.toJSONString(data));
        list.add(data);
        if (list.size() >= BATCH_COUNT) {
            syncData();
            list.clear();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        syncData();
        LOGGER.info("所有数据解析完成！");
    }


    /**
     * 加上存储数据库
     */
    private void syncData() {
        LOGGER.info("{}条数据，开始存储数据库！", list.size());
        SqlSession sqlSession = SessionUtil.getFactory().openSession(true);
        try {
            DcMidCostFirstMapper dcMidCostFirstMapper = sqlSession.getMapper(DcMidCostFirstMapper.class);
            DcBaseStockMapper dcBaseStockMapper = sqlSession.getMapper(DcBaseStockMapper.class);
            DcBaseSkuMapper dcBaseSkuMapper = sqlSession.getMapper(DcBaseSkuMapper.class);

            List<String> skuList = list.stream().map(CostFirst::getBailunSku).collect(Collectors.toList());

            Map<String, DcBaseSku> skuMap = dcBaseSkuMapper.selectByExample(DcBaseSkuExample.newAndCreateCriteria()
                    .andBailunSkuIn(skuList)
                    .example()).stream().collect(Collectors.toMap(dcBaseSku -> dcBaseSku.getBailunSku().toLowerCase(), dcBaseSku -> dcBaseSku));

            List<DcMidCostFirst> dcMidCostFirstList =
                    list.stream().map(costFirst -> {
                        DcMidCostFirst dcMidCostFirst = new DcMidCostFirst();
                        dcMidCostFirst.setHasConfig(false);
                        dcMidCostFirst.setCompanyId(0);
                        if (Lists.newArrayList(1, 5).contains(CostFirst.map.get(costFirst.getType()))) {
                            dcMidCostFirst.setHasCalculation(true);
                        } else {
                            dcMidCostFirst.setHasCalculation(false);
                        }
                        dcMidCostFirst.setCostCount(0);
                        dcMidCostFirst.setWarehouseCode(costFirst.getWarehouseCode());
                        dcMidCostFirst.setBailunSku(costFirst.getBailunSku());
                        dcMidCostFirst.setCostFirst(costFirst.getCost());
                        DcBaseSku dcBaseSku = skuMap.get(dcMidCostFirst.getBailunSku().toLowerCase());

                        if (dcBaseSku == null) {
                            log.error("sku:{}为null", dcMidCostFirst.getBailunSku());
                            return null;
                        }
                        dcMidCostFirst.setCostFirst(costFirst.getCost());
                        return dcMidCostFirst;
                    })
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());

            dcMidCostFirstMapper.upsertBatch(dcMidCostFirstList);
        } finally {
            sqlSession.close();
        }

        LOGGER.info("存储数据库成功！");
    }
}
