package com.bailuntec.job;

import com.bailuntec.domain.constant.CommonConstant;
import com.bailuntec.domain.entity.*;
import com.bailuntec.domain.example.DcBaseCostFirstExample;
import com.bailuntec.domain.example.DcBaseSkuExample;
import com.bailuntec.domain.example.DcMidCostFirstExample;
import com.bailuntec.domain.example.DcMidCostFirstOrderExample;
import com.bailuntec.mapper.*;
import com.bailuntec.support.PointJob;
import com.bailuntec.utils.SessionUtil;
import com.dangdang.ddframe.job.api.ShardingContext;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CalculateCostFirstJob extends PointJob {

    @Override
    public void executeJob(ShardingContext shardingContext, JobPointLog jobPointLog) {
        int countChannelOrder;
        try {
            DcBaseCostFirstMapper dcBaseCostFirstMapper = SessionUtil.getSession().getMapper(DcBaseCostFirstMapper.class);
            countChannelOrder = dcBaseCostFirstMapper.countChannelOrder();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("MYBATIS操作DB失败", e);
        } finally {
            SessionUtil.closeSession();
        }
        int totalPage = getChannelOrderPage(countChannelOrder,jobPointLog);
        do {
            try {
                DcBaseCostFirstMapper dcBaseCostFirstMapper = SessionUtil.getSession().getMapper(DcBaseCostFirstMapper.class);
                //拿到物流单号, 将物流单中每个SKU的费用算出来
                List<String> channelOrderIdList = dcBaseCostFirstMapper.listChannelOrderId(jobPointLog.getPageIndex() * jobPointLog.getPageSize(), jobPointLog.getPageSize());
                if (channelOrderIdList != null && channelOrderIdList.size() > 0) {
                    for (String channelOrderId : channelOrderIdList) {
                        DcBaseCostFirstMapper dcBaseCostFirstMapperFor = SessionUtil.getSession().getMapper(DcBaseCostFirstMapper.class);
                        List<DcBaseCostFirst> dcBaseCostFirsts = dcBaseCostFirstMapperFor.selectByExample(DcBaseCostFirstExample.newAndCreateCriteria().andChannelOrderIdEqualTo(channelOrderId).example());
                        handleChannelOrderSku(dcBaseCostFirsts);
                    }
                }
                JobPointLogMapper jobPointLogMapper = SessionUtil.getSession().getMapper(JobPointLogMapper.class);
                if (jobPointLog.getPageIndex() % 5 == 0) {
                    jobPointLogMapper.upsertSelective(jobPointLog);
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("MYBATIS操作DB失败", e);
            } finally {
                SessionUtil.closeSession();
            }
            jobPointLog.setPageIndex(jobPointLog.getPageIndex() + 1);
        } while (jobPointLog.getPageIndex().intValue() <= totalPage);
        jobPointLog.setPageIndex(0);
    }

    public void handleChannelOrderSku(List<DcBaseCostFirst> dcBaseCostFirsts) {
        //这个MAP用来放一个物流单, 每个SKU的数据
        HashMap<String, DcBaseCostFirst> map = new HashMap<>();
        //物流单的总重量
        BigDecimal totalWeight = BigDecimal.ZERO;
        for (DcBaseCostFirst dcBaseCostFirst : dcBaseCostFirsts) {
            DcBaseSku dcBaseSku = null;
            try {
                DcBaseSkuMapper dcBaseSkuMapper = SessionUtil.getSession().getMapper(DcBaseSkuMapper.class);
                dcBaseSku = dcBaseSkuMapper.selectOneByExample(DcBaseSkuExample.newAndCreateCriteria().andBailunSkuEqualTo(dcBaseCostFirst.getBailunSku()).example());
            } catch (Exception e) {
               throw new RuntimeException("MYBATIS操作DB失败");
            } finally {
                SessionUtil.closeSession();
            }
            //物流单内单位SKU多个quantity的总重量
            BigDecimal skuTotalWeight = dcBaseSku.getWeight().multiply(BigDecimal.valueOf(dcBaseCostFirst.getQuantity()));
            totalWeight = totalWeight.add(skuTotalWeight);
            DcBaseCostFirst dcBaseCostFirstInMap = map.get(dcBaseSku.getBailunSku());
            if (dcBaseCostFirstInMap == null) {
                dcBaseCostFirst.setSkuWeight(skuTotalWeight);
                dcBaseCostFirst.setQuantity(dcBaseCostFirst.getQuantity());
            } else {
                dcBaseCostFirst.setSkuWeight(dcBaseCostFirstInMap.getSkuWeight().add(skuTotalWeight));
                dcBaseCostFirst.setQuantity(dcBaseCostFirstInMap.getQuantity() + dcBaseCostFirst.getQuantity());
            }
            map.put(dcBaseSku.getBailunSku(), dcBaseCostFirst);
        }

        /*
         * 用物流单内SKU的费用 (由重量比计算)
         * 除以数量 得出该物流单单个SKU的头程费
         */
        DcMidCostFirstOrder dcMidCostFirstOrder = new DcMidCostFirstOrder();
        for (Map.Entry<String, DcBaseCostFirst> entry : map.entrySet()) {
            DcBaseCostFirst dcBaseCostFirst = entry.getValue();
            BigDecimal skuWeightRatio = dcBaseCostFirst.getSkuWeight().divide(totalWeight, 3, RoundingMode.HALF_EVEN);
            BigDecimal skuCostFirst = dcBaseCostFirst.getCostFirst().multiply(skuWeightRatio).setScale(3, RoundingMode.HALF_EVEN);
            dcMidCostFirstOrder.setBailunSku(dcBaseCostFirst.getBailunSku());
            dcMidCostFirstOrder.setWarehouseCode(dcBaseCostFirst.getWarehouseCode());
            dcMidCostFirstOrder.setChannelOrderId(dcBaseCostFirst.getChannelOrderId());
            dcMidCostFirstOrder.setQuantity(dcBaseCostFirst.getQuantity());
            dcMidCostFirstOrder.setWeightRatio(skuWeightRatio);
            //将费用算到单个SKU上
            dcMidCostFirstOrder.setCostFirst(skuCostFirst.divide(BigDecimal.valueOf(dcBaseCostFirst.getQuantity()), 3, RoundingMode.HALF_EVEN));
            try {
                DcMidCostFirstOrderMapper dcMidCostFirstOrderMapper = SessionUtil.getSession().getMapper(DcMidCostFirstOrderMapper.class);
                int i = dcMidCostFirstOrderMapper.updateByExampleSelective(dcMidCostFirstOrder, DcMidCostFirstOrderExample.newAndCreateCriteria().andBailunSkuEqualTo(dcMidCostFirstOrder.getBailunSku()).andChannelOrderIdEqualTo(dcMidCostFirstOrder.getChannelOrderId()).example());
                if (i == 0) {
                    dcMidCostFirstOrderMapper.insertSelective(dcMidCostFirstOrder);
                }
            } catch (Exception e) {
                throw new RuntimeException("MYBATIS操作DB失败");
            } finally {
                SessionUtil.closeSession();
            }
        }
    }

    private int getChannelOrderPage(int countChannelOrder, JobPointLog jobPointLog) {
        if (countChannelOrder % jobPointLog.getPageSize() == 0) {
            return countChannelOrder / jobPointLog.getPageSize();
        }
        return countChannelOrder / jobPointLog.getPageSize() + 1;
    }
}
