package com.bailuntec.job;

import com.bailuntec.domain.constant.Constant;
import com.bailuntec.domain.entity.*;
import com.bailuntec.domain.example.*;
import com.bailuntec.domain.pojo.CostFirstOrder;
import com.bailuntec.domain.pojo.MidCostFirst;
import com.bailuntec.mapper.*;
import com.bailuntec.support.PointJob;
import com.bailuntec.utils.SessionUtil;
import com.dangdang.ddframe.job.api.ShardingContext;
import lombok.extern.slf4j.Slf4j;

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

@Slf4j
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 {
            List<CostFirstOrder> channelOrderIdList = null;
            try {
                DcBaseCostFirstMapper dcBaseCostFirstMapper = SessionUtil.getSession().getMapper(DcBaseCostFirstMapper.class);
                //拿到物流单号,调拨单号, 将物流单-调拨单中每个SKU的费用算出来
                channelOrderIdList = dcBaseCostFirstMapper.listChannelOrderId(jobPointLog.getPageIndex() * jobPointLog.getPageSize(), jobPointLog.getPageSize());
                /*JobPointLogMapper jobPointLogMapper = SessionUtil.getSession().getMapper(JobPointLogMapper.class);
                if (jobPointLog.getPageIndex() % 5 == 0) {
                    jobPointLogMapper.upsertSelective(jobPointLog);
                }*/
            } catch (Exception e) {
                throw new RuntimeException("MYBATIS操作DB分页失败", e);
            } finally {
                SessionUtil.closeSession();
            }
            if (channelOrderIdList != null && channelOrderIdList.size() > 0) {
                for (CostFirstOrder costFirstOrder : channelOrderIdList) {
                    DcBaseCostFirstMapper dcBaseCostFirstMapperFor = SessionUtil.getSession().getMapper(DcBaseCostFirstMapper.class);
                    List<DcBaseCostFirst> dcBaseCostFirsts = dcBaseCostFirstMapperFor.selectByExample(DcBaseCostFirstExample.newAndCreateCriteria().andChannelOrderIdEqualTo(costFirstOrder.getChannelOrderId()).andTransferOrderIdEqualTo(costFirstOrder.getTransferOrderId()).andBoxIdEqualTo(costFirstOrder.getBoxId()).andWarehouseCodeEqualTo(costFirstOrder.getWarehouseCode()).andHasCalculationEqualTo(false).example());
                    handleChannelOrderSku(dcBaseCostFirsts);
                    dcBaseCostFirstMapperFor = SessionUtil.getSession().getMapper(DcBaseCostFirstMapper.class);
                    dcBaseCostFirstMapperFor.updateHasCalculation(costFirstOrder);
                }
            }
            jobPointLog.setPageIndex(jobPointLog.getPageIndex() + 1);
        } while (jobPointLog.getPageIndex().intValue() <= totalPage);
        jobPointLog.setPageIndex(0);

        try {
            DcMidCostFirstOrderMapper dcMidCostFirstOrderMapper = SessionUtil.getSession().getMapper(DcMidCostFirstOrderMapper.class);
         //   DcMidCostFirstConfigMapper dcMidCostFirstConfigMapper = SessionUtil.getSession().getMapper(DcMidCostFirstConfigMapper.class);
            DcMidCostFirstMapper dcMidCostFirsMapper = SessionUtil.getSession().getMapper(DcMidCostFirstMapper.class);
            DcBaseStockMapper dcBaseStockMapper = SessionUtil.getSession().getMapper(DcBaseStockMapper.class);
            int countSkuWarehouse = dcMidCostFirstOrderMapper.countSkuWarehouse();
            int skuWarehouseTotalPage = getSkuWarehouseTotalPage(countSkuWarehouse);
            int index = 0;
            do {
                List<MidCostFirst> midCostFirstList = dcMidCostFirstOrderMapper.listSkuWarehouse(index * Constant.PAGE_SIZE,Constant.PAGE_SIZE);
                if (midCostFirstList != null && midCostFirstList.size() > 0) {
                    DcMidCostFirst dcMidCostFirst = new DcMidCostFirst();
                    for (MidCostFirst midCostFirst : midCostFirstList) {
                        DcBaseStock dcBaseStock = dcBaseStockMapper.selectOneByExample(DcBaseStockExample.newAndCreateCriteria().andBailunSkuEqualTo(midCostFirst.getBailunSku()).andWarehouseCodeEqualTo(midCostFirst.getWarehouseCode()).example());
                        DcMidCostFirst dcMidCostFirst1 = dcMidCostFirsMapper.selectOneByExample(DcMidCostFirstExample.newAndCreateCriteria().andBailunSkuEqualTo(midCostFirst.getBailunSku()).andWarehouseCodeEqualTo(midCostFirst.getWarehouseCode()).example());
                        dcMidCostFirst.setBailunSku(midCostFirst.getBailunSku());
                        dcMidCostFirst.setWarehouseCode(midCostFirst.getWarehouseCode());
                        BigDecimal costFirst = BigDecimal.ZERO;
                        if(dcMidCostFirst1 != null) {
                            costFirst = (midCostFirst.getTotalCostFirst().add(dcMidCostFirst1.getCostFirst().multiply(BigDecimal.valueOf(dcMidCostFirst1.getCostCount())))).divide(BigDecimal.valueOf(midCostFirst.getTotalCount()).add(BigDecimal.valueOf(dcMidCostFirst1.getCostCount())), 3 , RoundingMode.HALF_EVEN);
                        }else {
                            costFirst = midCostFirst.getTotalCostFirst().divide(BigDecimal.valueOf(midCostFirst.getTotalCount()), 3 , RoundingMode.HALF_EVEN);
                        }

                        dcMidCostFirst.setCostFirst(costFirst);
                        if(dcBaseStock != null) {
                            dcMidCostFirst.setCostCount(dcBaseStock.getUsableStock() + dcBaseStock.getOccupyStock());
                        }else {
                            dcMidCostFirst.setCostCount(midCostFirst.getTotalCount());
                        }
                        /*if (dcMidCostFirstConfig != null) {
                            //  头程费 = (调拨计算头程费+配置头程费)/2  平均值
                            dcMidCostFirst.setCostFirst((costFirst.add(dcMidCostFirstConfig.getCostFirstConfig())).divide(BigDecimal.valueOf(2), 3, RoundingMode.HALF_EVEN));
                        }*/
                        int i = dcMidCostFirsMapper.updateByExampleSelective(dcMidCostFirst, DcMidCostFirstExample.newAndCreateCriteria().andBailunSkuEqualTo(dcMidCostFirst.getBailunSku()).andWarehouseCodeEqualTo(dcMidCostFirst.getWarehouseCode()).example());
                        if (i == 0) {
                            dcMidCostFirsMapper.insertSelective(dcMidCostFirst);
                        }
                  //      dcMidCostFirstOrderMapper.deleteByExample(DcMidCostFirstOrderExample.newAndCreateCriteria().andBailunSkuEqualTo(midCostFirst.getBailunSku()).andWarehouseCodeEqualTo(midCostFirst.getWarehouseCode()).example());
                        dcMidCostFirstOrderMapper.updateHasCalculation(midCostFirst);
                    }

                }
                index++;
            } while (index < skuWarehouseTotalPage);
        } catch (Exception e) {
            throw new RuntimeException("在计算头程费到DcMidCostFirst时失败", e);
        } finally {
            SessionUtil.closeSession();
        }
    }

    public void handleChannelOrderSku(List<DcBaseCostFirst> dcBaseCostFirsts) {
        //这个MAP用来放一个物流单, 每个SKU的数据
        HashMap<String, DcBaseCostFirst> map = new HashMap<>();
        //物流单的总重量
        BigDecimal totalWeight = BigDecimal.ZERO;
        for (DcBaseCostFirst dcBaseCostFirst : dcBaseCostFirsts) {
            log.warn(dcBaseCostFirst.getBailunSku()+"---" +dcBaseCostFirst.getChannelOrderId()+"---" +dcBaseCostFirst.getTransferOrderId()+"---"+dcBaseCostFirst.getBoxId()+"---"+dcBaseCostFirst.getWarehouseCode());
            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查询SKU失败");
            } finally {
                SessionUtil.closeSession();
            }
            //物流单内单位SKU多个quantity的总重量
            BigDecimal skuTotalWeight = (dcBaseSku != null?dcBaseSku.getWeight() : BigDecimal.ZERO).multiply(BigDecimal.valueOf(dcBaseCostFirst.getQuantity()));
            totalWeight = totalWeight.add(skuTotalWeight);
            DcBaseCostFirst dcBaseCostFirstInMap = map.get(dcBaseCostFirst.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(dcBaseCostFirst.getBailunSku(), dcBaseCostFirst);
        }

        /*
         * 用物流单内SKU的费用 (由重量比计算)
         * 除以数量 得出该物流单单个SKU的头程费
         */
        DcMidCostFirstOrder dcMidCostFirstOrder = new DcMidCostFirstOrder();
        for (Map.Entry<String, DcBaseCostFirst> entry : map.entrySet()) {
            DcBaseCostFirst dcBaseCostFirst = entry.getValue();
            BigDecimal skuWeightRatio = BigDecimal.ONE;
            if (totalWeight.compareTo(BigDecimal.ZERO) == 1) {
                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.setTransferOrderId(dcBaseCostFirst.getTransferOrderId());
            dcMidCostFirstOrder.setQuantity(dcBaseCostFirst.getQuantity());
            dcMidCostFirstOrder.setBoxId(dcBaseCostFirst.getBoxId());
            dcMidCostFirstOrder.setWeightRatio(skuWeightRatio);
            //将费用放到SKU上
            dcMidCostFirstOrder.setCostFirst(skuCostFirst);
            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;
    }

    private int getSkuWarehouseTotalPage(int countSkuWarehouse) {
        if (countSkuWarehouse % Constant.PAGE_SIZE == 0) {
            return countSkuWarehouse / Constant.PAGE_SIZE;
        }
        return countSkuWarehouse / Constant.PAGE_SIZE + 1;
    }
}
