package excel.costfirstfba;

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.DcBaseWarehouse;
import com.bailuntec.domain.entity.DcMidCostFirst;
import com.bailuntec.domain.example.DcBaseSkuExample;
import com.bailuntec.domain.example.DcBaseWarehouseExample;
import com.bailuntec.mapper.DcBaseSkuMapper;
import com.bailuntec.mapper.DcBaseWarehouseMapper;
import com.bailuntec.mapper.DcMidCostFirstMapper;
import com.bailuntec.utils.SessionUtil;
import excel.costfirst.CostFirstListener;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
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 5:37 下午
 */
@Slf4j
public class CostFirstFbaListener extends AnalysisEventListener<CostFirstFba> {

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

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

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


    @Override
    public void invoke(CostFirstFba 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);
            DcBaseWarehouseMapper dcBaseWarehouseMapper = sqlSession.getMapper(DcBaseWarehouseMapper.class);
            DcBaseSkuMapper dcBaseSkuMapper = sqlSession.getMapper(DcBaseSkuMapper.class);

            List<String> warehouseNames = list.stream().map(CostFirstFba::getWarehouseName).distinct().collect(Collectors.toList());

            if (warehouseNames.contains("美国FBA-04")) {
                warehouseNames.add("美国FBA-04仓");
            }

            List<DcBaseWarehouse> dcBaseWarehouseList = dcBaseWarehouseMapper.selectByExample(DcBaseWarehouseExample.newAndCreateCriteria()
                    .andWarehouseNameIn(warehouseNames)
                    .example());


            Map<String, DcBaseWarehouse> map = dcBaseWarehouseList.stream().collect(Collectors.toMap(DcBaseWarehouse::getWarehouseName, dcBaseWarehouse -> dcBaseWarehouse));


            List<String> skuList = list.stream().map(CostFirstFba::getSku).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(costFirstFba -> {
                        try {
                            DcMidCostFirst dcMidCostFirst = new DcMidCostFirst();
                            dcMidCostFirst.setHasConfig(true);
                            dcMidCostFirst.setCompanyId(0);
                            dcMidCostFirst.setHasCalculation(true);
                            dcMidCostFirst.setCostCount(0);
                            dcMidCostFirst.setWarehouseCode(map.get(costFirstFba.getWarehouseName()).getWarehouseCode());
                            dcMidCostFirst.setBailunSku(costFirstFba.getSku());

                            DcBaseSku dcBaseSku = skuMap.get(dcMidCostFirst.getBailunSku().toLowerCase());
                            if (dcBaseSku == null) {
                                log.error("sku:{}为null", dcMidCostFirst.getBailunSku());
                                return null;
                            }
                            dcMidCostFirst.setCostFirst(costFirstFba.getInitValue().multiply(dcBaseSku.getWeight()).divide(new BigDecimal(1000), 6, RoundingMode.HALF_DOWN));
                            return dcMidCostFirst;
                        } catch (Exception e) {
                            LOGGER.error(costFirstFba.getWarehouseName());
                            return null;
                        }
                    })
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());

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

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