package com.ym.mec.biz.service.impl;


import static com.ym.mec.biz.dal.enums.GroupType.GOODS_SELL;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import com.ym.mec.biz.dal.dao.GoodsDao;
import com.ym.mec.biz.dal.dao.MusicGroupDao;
import com.ym.mec.biz.dal.dao.SellOrderDao;
import com.ym.mec.biz.dal.dao.SporadicChargeInfoDao;
import com.ym.mec.biz.dal.dao.StudentPaymentOrderDao;
import com.ym.mec.biz.dal.dao.StudentPaymentOrderDetailDao;
import com.ym.mec.biz.dal.dao.StudentRepairDao;
import com.ym.mec.biz.dal.entity.Goods;
import com.ym.mec.biz.dal.entity.MusicGroup;
import com.ym.mec.biz.dal.entity.SellOrder;
import com.ym.mec.biz.dal.entity.SporadicChargeInfo;
import com.ym.mec.biz.dal.entity.StudentPaymentOrder;
import com.ym.mec.biz.dal.entity.StudentPaymentOrderDetail;
import com.ym.mec.biz.dal.entity.SysUserCashAccountLog;
import com.ym.mec.biz.dal.enums.AccountType;
import com.ym.mec.biz.dal.enums.GoodsType;
import com.ym.mec.biz.dal.enums.KitGroupPurchaseTypeEnum;
import com.ym.mec.biz.dal.enums.OrderDetailTypeEnum;
import com.ym.mec.biz.dal.enums.OrderTypeEnum;
import com.ym.mec.biz.dal.enums.PaymentChannelEnum;
import com.ym.mec.biz.dal.enums.ReturnFeeEnum;
import com.ym.mec.biz.dal.enums.SellStatus;
import com.ym.mec.biz.dal.enums.SellTypeEnum;
import com.ym.mec.biz.dal.enums.SporadicChargeTypeEnum;
import com.ym.mec.biz.service.GoodsService;
import com.ym.mec.biz.service.SellOrderService;
import com.ym.mec.biz.service.StudentPaymentOrderDetailService;
import com.ym.mec.biz.service.SysPaymentConfigService;
import com.ym.mec.biz.service.SysUserCashAccountLogService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.service.impl.BaseServiceImpl;

@Service
public class SellOrderServiceImpl extends BaseServiceImpl<Integer, SellOrder> implements SellOrderService {
    @Autowired
    private SellOrderDao sellOrderDao;
    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private SysPaymentConfigService sysPaymentConfigService;
    @Autowired
    private SysUserCashAccountLogService sysUserCashAccountLogService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private StudentPaymentOrderDetailDao studentPaymentOrderDetailDao;
    @Autowired
    private SporadicChargeInfoDao sporadicChargeInfoDao;
    @Autowired
    private StudentRepairDao studentRepairDao;
    @Autowired
    private StudentPaymentOrderDetailService studentPaymentOrderDetailService;

    @Override
    public BaseDAO<Integer, SellOrder> getDAO() {
        return sellOrderDao;
    }


    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public List<SellOrder> addSellOrder(Long orderId, String musicGroupId, List<Integer> goodsIds, BigDecimal totalAmount, BigDecimal balance, BigDecimal couponRemitFee) {
        if (goodsIds == null || goodsIds.size() <= 0) {
            return null;
        }
        if (balance == null) {
            balance = BigDecimal.ZERO;
        }
        StudentPaymentOrder order = studentPaymentOrderDao.get(orderId);
        BigDecimal totalActualAmount = order.getActualAmount() == null ? BigDecimal.ZERO : order.getActualAmount();
        MusicGroup musicGroup = new MusicGroup();
        if (StringUtils.isNotBlank(musicGroupId)) {
            musicGroup = musicGroupDao.get(musicGroupId);
        }
        int goodsNum = goodsIds.size();
        BigDecimal goodsTotalPrice = BigDecimal.ZERO;
        List<Goods> goodies = goodsDao.getGoodies(goodsIds);
        int i = 1;
        for (Integer goodsId : goodsIds) {
            for (Goods goods : goodies) {
                if (goods.getId().equals(goodsId)) {
                    goodsTotalPrice = goodsTotalPrice.add(goods.getDiscountPrice());
                    break;
                }
            }
        }
        //商品总价值去掉优惠券减免
//        if(goodsTotalPrice.compareTo(couponRemitFee) <= 0){
//            goodsTotalPrice = BigDecimal.ZERO;
//        }else {
//            goodsTotalPrice = goodsTotalPrice.subtract(couponRemitFee);
//        }

        //已分配的商品余额
        BigDecimal hasRouteBalance = BigDecimal.ZERO;
        //已分配的商品现金
        BigDecimal hasRouteActualAmount = BigDecimal.ZERO;
        //商品占用的的余额
        BigDecimal goodsTotalBalance = totalAmount.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : goodsTotalPrice.multiply(balance).divide(totalAmount, 2, BigDecimal.ROUND_DOWN);
        //商品占用的总现金
        BigDecimal goodsTotalActualAmount = totalAmount.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : goodsTotalPrice.multiply(totalActualAmount).divide(totalAmount, 2, BigDecimal.ROUND_DOWN);
        AccountType accountType = sysPaymentConfigService.checkAccountType(PaymentChannelEnum.valueOf(order.getPaymentChannel()), order.getMerNos(), order.getTenantId());

        List<SellOrder> sellOrderList = goodsService.subtractStock(goodsIds, accountType);
        BigDecimal freeCouponRemitFee = couponRemitFee;
        for (int j = 0; j < goodsIds.size(); j++) {
            Integer goodsId = goodsIds.get(j);
            BigDecimal goodsPrice = BigDecimal.ZERO;
            Goods nowGoods = new Goods();
            for (Goods goods : goodies) {
                if (goods.getId().equals(goodsId)) {
                    nowGoods = goods;
                    break;
                }
            }
            goodsPrice = nowGoods.getDiscountPrice();
            //扣除减免金额
//            if(couponRemitFee.compareTo(BigDecimal.ZERO) > 0){
//                if(j == goodsIds.size() - 1){
//                    goodsPrice = goodsPrice.subtract(freeCouponRemitFee);
//                }else {
//                    //获取比例
//                    BigDecimal divide = goodsPrice.divide(goodsPrice.add(couponRemitFee), 6, BigDecimal.ROUND_HALF_UP);
//                    //分摊金额
//                    BigDecimal scale = couponRemitFee.multiply(divide).setScale(2, BigDecimal.ROUND_HALF_UP);
//                    freeCouponRemitFee = freeCouponRemitFee.subtract(scale);
//                    goodsPrice = goodsPrice.subtract(scale);
//                }
//            }

            //当前商品占用的总优惠券减免
            BigDecimal couponBalance = goodsTotalPrice.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO :
                    couponRemitFee.multiply(goodsPrice).divide(goodsTotalPrice, 2, BigDecimal.ROUND_DOWN);
            //当前商品占用的总余额
            BigDecimal goodsBalance = goodsTotalPrice.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO :
                    goodsTotalBalance.multiply(goodsPrice).divide(goodsTotalPrice, 2, BigDecimal.ROUND_DOWN);
            //当前商品占用的总现金
            BigDecimal goodsActualAmount = goodsTotalPrice.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO :
                    goodsTotalActualAmount.multiply(goodsPrice).divide(goodsTotalPrice, 2, BigDecimal.ROUND_DOWN);

            if (i == goodsNum) {
                couponBalance = couponRemitFee.subtract(freeCouponRemitFee);
                goodsBalance = goodsTotalBalance.subtract(hasRouteBalance);
                goodsActualAmount = goodsTotalActualAmount.subtract(hasRouteActualAmount);
            }
            freeCouponRemitFee = freeCouponRemitFee.subtract(couponBalance);
            hasRouteBalance = hasRouteBalance.add(goodsBalance);
            hasRouteActualAmount = hasRouteActualAmount.add(goodsActualAmount);
            i++;

            int complementGoodsNum = nowGoods.getComplementGoodsIdList() == null ? 1 : nowGoods.getComplementGoodsIdList().split(",").length;
            BigDecimal complementPrice = nowGoods.getDiscountPrice();
            Map<Integer, BigDecimal> complementGoodsPrice = new HashMap<>();
            complementGoodsPrice.put(nowGoods.getId(), nowGoods.getDiscountPrice());
            if (nowGoods.getComplementGoodsIdList() != null) {
                List<Goods> complementGoodies = goodsDao.findGoodsByIds(nowGoods.getComplementGoodsIdList());
                complementGoodsPrice = complementGoodies.stream().collect(Collectors.toMap(Goods::getId, Goods::getDiscountPrice));
                complementPrice = complementGoodies.stream().map(Goods::getDiscountPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            }

            BigDecimal hasRouteSellOrderActualAmount = BigDecimal.ZERO;
            BigDecimal hasRouteSellOrderBalance = BigDecimal.ZERO;
            BigDecimal hasRouteCouponBalance = BigDecimal.ZERO;
            for (SellOrder sellOrder : sellOrderList) {
                if (!goodsId.equals(sellOrder.getParentGoodsId()) && !goodsId.equals(sellOrder.getGoodsId())) {
                    continue;
                }
                if (sellOrder.getHasRoute()) {
                    continue;
                }
                BigDecimal sellOrderActualAmount = BigDecimal.ZERO;
                BigDecimal sellOrderBalance = BigDecimal.ZERO;
                if (complementPrice.compareTo(BigDecimal.ZERO) > 0) {
                    sellOrderActualAmount = complementGoodsPrice.get(sellOrder.getGoodsId()).multiply(new BigDecimal(sellOrder.getNum())).multiply(goodsActualAmount).divide(complementPrice, 2, BigDecimal.ROUND_DOWN);
                    sellOrderBalance = complementGoodsPrice.get(sellOrder.getGoodsId()).multiply(new BigDecimal(sellOrder.getNum())).multiply(goodsBalance).divide(complementPrice, 2, BigDecimal.ROUND_DOWN);
                }

                complementGoodsNum = complementGoodsNum - sellOrder.getNum();
                if (complementGoodsNum <= 0) {
                    sellOrderActualAmount = goodsActualAmount.subtract(hasRouteSellOrderActualAmount);
                    sellOrderBalance = goodsBalance.subtract(hasRouteSellOrderBalance);
                }
                hasRouteSellOrderActualAmount = hasRouteSellOrderActualAmount.add(sellOrderActualAmount);
                hasRouteSellOrderBalance = hasRouteSellOrderBalance.add(sellOrderBalance);

                sellOrder.setExpectAmount(sellOrderActualAmount.add(sellOrderBalance));
                sellOrder.setBalanceAmount(sellOrderBalance);
//                sellOrder.setCouponRemitAmount(sellOrderCouponBalance);
                sellOrder.setActualAmount(sellOrderActualAmount);
                sellOrder.setOrganId(order.getOrganId());
                sellOrder.setCooperationOrganId(musicGroup.getCooperationOrganId());
                sellOrder.setTransNo(order.getTransNo());
                sellOrder.setOrderId(order.getId());
                sellOrder.setOrderNo(order.getOrderNo());
                sellOrder.setUserId(order.getUserId());
                sellOrder.setPaymentChannel(order.getPaymentChannel());
                sellOrder.setMerNo(order.getMerNos());
                sellOrder.setSellTime(order.getCreateTime());
                sellOrder.setCreateIme(new Date());
                sellOrder.setUpdateTime(new Date());
                if (nowGoods.getType().equals(GoodsType.INSTRUMENT)) {
                    sellOrder.setType(SellTypeEnum.INSTRUMENT);
                } else if (nowGoods.getType().equals(GoodsType.ACCESSORIES)) {
                    sellOrder.setType(SellTypeEnum.ACCESSORIES);
                } else {
                    sellOrder.setType(SellTypeEnum.OTHER);
                }
                sellOrder.setHasRoute(true);
                if (complementGoodsNum <= 0) {
                    break;
                }
            }
        }
        if (sellOrderList.size() > 0) {
            //如果有优惠券金额
            if (couponRemitFee.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal reduce = sellOrderList.stream().map(e -> e.getExpectAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                List<SellOrder> sellOrders = sellOrderList.stream().filter(e -> e.getExpectAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                //可用优惠券金额
                BigDecimal subCouponMarketAmount = couponRemitFee;
                for (int j = 0; j < sellOrders.size(); j++) {
                    SellOrder sellOrder = sellOrders.get(j);
                    //如果是最后一件商品
                    if (j == sellOrders.size() - 1) {
                        sellOrder.setCouponRemitAmount(subCouponMarketAmount);
                    } else {
                        //获取比例
                        BigDecimal ratioAmount = sellOrder.getExpectAmount().divide(reduce, 6, BigDecimal.ROUND_HALF_UP);
                        //获取分配的减免金额
                        BigDecimal multiply = couponRemitFee.multiply(ratioAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
                        subCouponMarketAmount = subCouponMarketAmount.subtract(multiply);
                        sellOrder.setCouponRemitAmount(multiply);
                    }
                }
            }
            sellOrderDao.batchInsert(sellOrderList);
        }
        return sellOrderList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public List<SellOrder> addOrderDetail2SellOrder(List<StudentPaymentOrderDetail> orderDetails,
                                                    StudentPaymentOrder studentPaymentOrder, MusicGroup musicGroup,BigDecimal musicRemitFee) {
        Integer tenantId = studentPaymentOrder.getTenantId();
        List<SellOrder> sellOrders = new ArrayList<>();
        //总余额支付
        BigDecimal totalBalance = studentPaymentOrder.getBalancePaymentAmount() != null ? studentPaymentOrder.getBalancePaymentAmount() : BigDecimal.ZERO;
        //总价格
        BigDecimal totalPrice = studentPaymentOrder.getExpectAmount();
        //商品总付款
        BigDecimal detailTotalPrice = orderDetails.stream().map(StudentPaymentOrderDetail::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        //商品销售占的余额
        BigDecimal detailTotalBalance = detailTotalPrice.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO :
                detailTotalPrice.multiply(totalBalance).divide(totalPrice, 2, BigDecimal.ROUND_DOWN);

        int i = 1;
        BigDecimal detailRouteBalance = BigDecimal.ZERO;

        AccountType accountType = sysPaymentConfigService.checkAccountType(PaymentChannelEnum.valueOf(studentPaymentOrder.getPaymentChannel()), studentPaymentOrder.getMerNos(), tenantId);

        for (StudentPaymentOrderDetail orderDetail : orderDetails) {
            BigDecimal detailBalance = orderDetail.getPrice().compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO :
                    orderDetail.getPrice().multiply(detailTotalBalance).divide(detailTotalPrice, 2, BigDecimal.ROUND_DOWN);
            if (i == orderDetails.size()) {
                detailBalance = detailTotalBalance.subtract(detailRouteBalance);
            }
            detailRouteBalance = detailRouteBalance.add(detailBalance);
            i++;

            BigDecimal goodsTotalPrice = orderDetail.getGoodsList().stream().map(Goods::getGroupPurchasePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal routePrice = BigDecimal.ZERO;
            BigDecimal routeBalance = BigDecimal.ZERO;
            int j = 1;

            List<Integer> goodsIds = orderDetail.getGoodsList().stream().map(Goods::getId).collect(Collectors.toList());
            List<SellOrder> sellOrderList = goodsService.subtractStock(goodsIds, accountType);
            for (Goods goods : orderDetail.getGoodsList()) {
                BigDecimal expectAmount = BigDecimal.ZERO;
                BigDecimal balance = BigDecimal.ZERO;
                if (goodsTotalPrice.compareTo(BigDecimal.ZERO) > 0) {
                    expectAmount = goods.getGroupPurchasePrice().multiply(orderDetail.getPrice()).divide(goodsTotalPrice, 2, BigDecimal.ROUND_DOWN);
                    balance = goods.getGroupPurchasePrice().multiply(detailBalance).divide(goodsTotalPrice, 2, BigDecimal.ROUND_DOWN);
                }
                if (j == orderDetail.getGoodsList().size()) {
                    expectAmount = orderDetail.getPrice().subtract(routePrice);
                    balance = detailBalance.subtract(routeBalance);
                }
                routePrice = routePrice.add(expectAmount);
                routeBalance = routeBalance.add(balance);
                j++;

                int complementGoodsNum = goods.getComplementGoodsIdList() == null ? 1 : goods.getComplementGoodsIdList().split(",").length;
                BigDecimal complementPrice = goods.getGroupPurchasePrice();
                Map<Integer, BigDecimal> complementGoodsPrice = new HashMap<>();
                complementGoodsPrice.put(goods.getId(), goods.getGroupPurchasePrice());
                if (goods.getComplementGoodsIdList() != null) {
                    List<Goods> complementGoodies = goodsDao.findGoodsByIds(goods.getComplementGoodsIdList());
                    complementGoodsPrice = complementGoodies.stream().collect(Collectors.toMap(Goods::getId, Goods::getGroupPurchasePrice));
                    complementPrice = complementGoodies.stream().map(Goods::getGroupPurchasePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                }

                BigDecimal hasRouteSellOrderExpectAmount = BigDecimal.ZERO;
                BigDecimal hasRouteSellOrderBalance = BigDecimal.ZERO;
                for (SellOrder sellOrder : sellOrderList) {
                    if (!goods.getId().equals(sellOrder.getParentGoodsId()) && !goods.getId().equals(sellOrder.getGoodsId())) {
                        continue;
                    }
                    if (sellOrder.getHasRoute()) {
                        continue;
                    }
                    sellOrder.setTenantId(tenantId);
                    BigDecimal sellOrderExpectAmount = BigDecimal.ZERO;
                    BigDecimal sellOrderBalance = BigDecimal.ZERO;
                    if (complementPrice.compareTo(BigDecimal.ZERO) > 0) {
                        sellOrderExpectAmount = complementGoodsPrice.get(sellOrder.getGoodsId()).multiply(new BigDecimal(sellOrder.getNum())).multiply(expectAmount).divide(complementPrice, 2, BigDecimal.ROUND_DOWN);
                        sellOrderBalance = complementGoodsPrice.get(sellOrder.getGoodsId()).multiply(new BigDecimal(sellOrder.getNum())).multiply(balance).divide(complementPrice, 2, BigDecimal.ROUND_DOWN);
                    }
                    complementGoodsNum = complementGoodsNum - sellOrder.getNum();
                    if (complementGoodsNum <= 0) {
                        sellOrderExpectAmount = expectAmount.subtract(hasRouteSellOrderExpectAmount);
                        sellOrderBalance = balance.subtract(hasRouteSellOrderBalance);
                    }
                    hasRouteSellOrderExpectAmount = hasRouteSellOrderExpectAmount.add(sellOrderExpectAmount);
                    hasRouteSellOrderBalance = hasRouteSellOrderBalance.add(sellOrderBalance);

                    sellOrder.setOrganId(studentPaymentOrder.getOrganId());
                    sellOrder.setTransNo(studentPaymentOrder.getTransNo());
                    sellOrder.setOrderId(studentPaymentOrder.getId());
                    if (musicGroup != null) {
                        sellOrder.setCooperationOrganId(musicGroup.getCooperationOrganId());
                        sellOrder.setEduTeacherId(musicGroup.getEducationalTeacherId());
                    }
                    sellOrder.setOrderNo(studentPaymentOrder.getOrderNo());
                    sellOrder.setActualAmount(sellOrderExpectAmount.subtract(sellOrderBalance));
                    sellOrder.setBalanceAmount(sellOrderBalance);
                    sellOrder.setExpectAmount(sellOrderExpectAmount);
//                    sellOrder.setCouponRemitAmount(goods.getGroupPurchasePrice().subtract(sellOrderExpectAmount));
                    sellOrder.setNum(1);
                    sellOrder.setUserId(studentPaymentOrder.getUserId());
                    sellOrder.setPaymentChannel(studentPaymentOrder.getPaymentChannel());
                    sellOrder.setMerNo(studentPaymentOrder.getMerNos());
                    sellOrder.setSellTime(studentPaymentOrder.getCreateTime());
                    sellOrder.setCreateIme(new Date());
                    sellOrder.setUpdateTime(new Date());
                    if (goods.getType().equals(GoodsType.INSTRUMENT)) {
                        sellOrder.setType(SellTypeEnum.INSTRUMENT);
                    } else if (goods.getType().equals(GoodsType.ACCESSORIES)) {
                        sellOrder.setType(SellTypeEnum.ACCESSORIES);
                    } else {
                        sellOrder.setType(SellTypeEnum.OTHER);
                    }
                    //租赁、免费的没有销售收入，有销售成本
                    if (orderDetail.getType().equals(OrderDetailTypeEnum.MUSICAL) &&
                            (orderDetail.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.LEASE) ||
                                    orderDetail.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.FREE)
                            )) {
                        sellOrder.setActualAmount(BigDecimal.ZERO);
                        sellOrder.setBalanceAmount(BigDecimal.ZERO);
                        sellOrder.setExpectAmount(BigDecimal.ZERO);
                    }
                    sellOrder.setHasRoute(true);
                    if (complementGoodsNum <= 0) {
                        break;
                    }
                }

            }
            sellOrders.addAll(sellOrderList);
        }
        if (sellOrders.size() > 0) {
            //如果有优惠券金额
            if (musicRemitFee.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal reduce = sellOrders.stream().map(e -> e.getExpectAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
                List<SellOrder> sellOrderList = sellOrders.stream().filter(e -> e.getExpectAmount().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                //可用优惠券金额
                BigDecimal subCouponMarketAmount = musicRemitFee;
                for (int j = 0; j < sellOrderList.size(); j++) {
                    SellOrder sellOrder = sellOrderList.get(j);
                    //如果是最后一件商品
                    if (j == sellOrderList.size() - 1) {
                        sellOrder.setCouponRemitAmount(subCouponMarketAmount);
                    } else {
                        //获取比例
                        BigDecimal ratioAmount = sellOrder.getExpectAmount().divide(reduce, 6, BigDecimal.ROUND_HALF_UP);
                        //获取分配的减免金额
                        BigDecimal multiply = musicRemitFee.multiply(ratioAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
                        subCouponMarketAmount = subCouponMarketAmount.subtract(multiply);
                        sellOrder.setCouponRemitAmount(multiply);
                    }
                }
            }
            sellOrderDao.batchInsert(sellOrders);
        }
        return sellOrders;
    }

    @Override
    public void batchInsert(List<SellOrder> sellOrders) {
        sellOrderDao.batchInsert(sellOrders);
    }

    @Override
    public List<SellOrder> getSellOrderByParentGoodsId(Long orderId, Integer parentGoodsId) {
        return sellOrderDao.getSellOrderByParentGoodsId(orderId, parentGoodsId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public List<SellOrder> refund(List<SellOrder> sellOrders, Boolean reBackFee) {
        Date nowDate = new Date();
        for (SellOrder sellOrder : sellOrders) {
            //1、更改销售列表状态
            sellOrder.setStatus(SellStatus.REFUND);
            sellOrder.setUpdateTime(nowDate);
            sellOrder.setRefundTime(nowDate);
            sellOrderDao.update(sellOrder);

            //2、金额退到余额
            if (reBackFee && sellOrder.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                SysUserCashAccountLog sysUserCashAccountLog = new SysUserCashAccountLog();
                sysUserCashAccountLog.setReturnFeeType(ReturnFeeEnum.GOODS);
                sysUserCashAccountLog.setOrganId(sellOrder.getOrganId());
                sysUserCashAccountLog.setUserId(sellOrder.getUserId());
                sysUserCashAccountLog.setGroupType(GOODS_SELL);
                sysUserCashAccountLog.setComment("商品退费");
                sysUserCashAccountLog.setGroupId(sellOrder.getId().toString());
                sysUserCashAccountLog.setAmount(sysUserCashAccountLogService.musicReturnFeeCharges(sellOrder.getExpectAmount(),0));
                sysUserCashAccountLogService.insert(sysUserCashAccountLog);
//                sysUserCashAccountService.updateBalance(sellOrder.getUserId(), sellOrder.getExpectAmount().multiply(new BigDecimal(0.995)).setScale(CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP), PlatformCashAccountDetailTypeEnum.REFUNDS, "订单：" + sellOrder.getOrderId() + " 商品id：" + sellOrder.getGoodsId() + "退货");
            }
        }
        //3、退货
        if (sellOrders.get(0).getAccountType() != null) {
            goodsService.increaseStock(sellOrders, sellOrders.get(0).getAccountType());
        }
        return sellOrders;
    }

    @Override
    public List<SellOrder> refundByOrderId(Long orderId, Boolean reBackFee) {
        List<SellOrder> sellOrders = sellOrderDao.getSellOrderByParentGoodsId(orderId, null);
        if (sellOrders.size() <= 0) {
            return sellOrders;
        }
        return refund(sellOrders, reBackFee);
    }

    @Override
    public List<SellOrder> getRefundSellOrder(List<Long> orderIdList) {
        return sellOrderDao.getRefundSellOrder(orderIdList);
    }

    @Override
    public Map<String, BigDecimal> getSellAmount(String orderNo) {
        StudentPaymentOrder order = studentPaymentOrderDao.findOrderByOrderNo(orderNo);
        if (order == null) {
            return null;
        }
        
        List<StudentPaymentOrderDetail> studentPaymentOrderDetailList = studentPaymentOrderDetailService.queryOrderDetail(order.getId());
        BigDecimal cloudIncome = BigDecimal.ZERO;
        BigDecimal cloudBalanceIncome = BigDecimal.ZERO;
        if(studentPaymentOrderDetailList != null) {
        	cloudIncome = studentPaymentOrderDetailList.stream().filter(t -> StringUtils.isNoneBlank(t.getMinuendStockGoodsIdList()) && StringUtils.equals(t.getIncomeItem(), OrderDetailTypeEnum.CLOUD_TEACHER.name())).map(t -> t.getIncome()).reduce(BigDecimal.ZERO, BigDecimal::add);
        	cloudBalanceIncome = studentPaymentOrderDetailList.stream().filter(t -> StringUtils.isNoneBlank(t.getMinuendStockGoodsIdList()) && StringUtils.equals(t.getIncomeItem(), OrderDetailTypeEnum.CLOUD_TEACHER.name())).map(t -> t.getBalanceIncome()).reduce(BigDecimal.ZERO, BigDecimal::add);
        }

        //零星支付除了充值其他都是服务费用
        if (order.getType().equals(OrderTypeEnum.SPORADIC)) {
            SporadicChargeInfo info = sporadicChargeInfoDao.get(Integer.parseInt(order.getMusicGroupId()));
            if (info.getChargeType().equals(SporadicChargeTypeEnum.RECHARGE)) {
                return null;
            }
        }
        Map<String, BigDecimal> sellAmount = new HashMap<>();
        //乐器销售,声部更改,乐器置换
        if (order.getType().equals(OrderTypeEnum.GOODS_SELL) || order.getType().equals(OrderTypeEnum.SUBJECT_CHANGE) || order.getType().equals(OrderTypeEnum.REPLACEMENT)) {
            sellAmount.put("actualAmount", order.getActualAmount().subtract(cloudIncome));
            sellAmount.put("balance", order.getBalancePaymentAmount() == null ? BigDecimal.ZERO : order.getBalancePaymentAmount().subtract(cloudBalanceIncome));
            return sellAmount;
        }
        //乐团报名,乐器维修
        if (order.getType().equals(OrderTypeEnum.APPLY) || order.getType().equals(OrderTypeEnum.REPAIR)) {
            return this.calcSellAmount(order,cloudBalanceIncome, cloudIncome);
        }
        sellAmount.put("actualAmount", BigDecimal.ZERO);
        sellAmount.put("balance", BigDecimal.ZERO);
        return sellAmount;
    }

    public Map<String, BigDecimal> calcSellAmount(StudentPaymentOrder order,BigDecimal cloudBalanceIncome,BigDecimal cloudIncome) {
        List<StudentPaymentOrderDetail> orderDetails = studentPaymentOrderDetailDao.getOrderDetail(order.getId());
        //总余额支付
        BigDecimal totalBalance = order.getBalancePaymentAmount() != null ? order.getBalancePaymentAmount() : BigDecimal.ZERO;
        //总价格
        BigDecimal totalPrice = order.getExpectAmount();
        //商品总付款
        BigDecimal detailTotalPrice = orderDetails.stream().map(StudentPaymentOrderDetail::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        //商品销售占的余额
        BigDecimal detailTotalBalance = detailTotalPrice.multiply(totalBalance).divide(totalPrice, 2, BigDecimal.ROUND_DOWN);

        if(detailTotalBalance.subtract(cloudBalanceIncome).compareTo(BigDecimal.ZERO) < 0) {
            detailTotalBalance = cloudBalanceIncome;
        }

        BigDecimal actualAmount = detailTotalPrice.multiply(order.getActualAmount()).divide(totalPrice, 2, BigDecimal.ROUND_DOWN);

        if(actualAmount.subtract(cloudIncome).compareTo(BigDecimal.ZERO) < 0){
            actualAmount = cloudIncome;
        }
        Map<String, BigDecimal> sellAmount = new HashMap<>(2);
        //返回销售收入
        sellAmount.put("actualAmount", actualAmount.subtract(cloudIncome));
        sellAmount.put("balance", detailTotalBalance.subtract(cloudBalanceIncome));
        return sellAmount;
    }

}
