package com.yonge.cooleshow.portal.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.yonge.cooleshow.api.feign.AdminFeignService;
import com.yonge.cooleshow.api.feign.dto.CouponInfoApi;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.entity.MallOrderItemDto;
import com.yonge.cooleshow.common.enums.PostStatusEnum;
import com.yonge.cooleshow.common.entity.ContractDto;
import com.yonge.cooleshow.common.service.IdGeneratorService;
import com.yonge.cooleshow.mall.common.api.CommonPage;
import com.yonge.cooleshow.mall.common.enums.OrderCacheEnum;
import com.yonge.cooleshow.mall.common.exception.Asserts;
import com.yonge.cooleshow.mall.common.service.RedisService;
import com.yonge.cooleshow.mbg.mapper.*;
import com.yonge.cooleshow.mbg.model.*;
import com.yonge.cooleshow.portal.component.CancelOrderSender;
import com.yonge.cooleshow.portal.dao.PortalOrderDao;
import com.yonge.cooleshow.portal.dao.PortalOrderItemDao;
import com.yonge.cooleshow.portal.dao.PortalProductDao;
import com.yonge.cooleshow.portal.domain.*;
import com.yonge.cooleshow.portal.dto.OrderPayReq;
import com.yonge.cooleshow.portal.dto.OrderPayRes;
import com.yonge.cooleshow.portal.service.*;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.result.BaseResult;
import com.yonge.toolset.base.util.StringUtil;
import com.yonge.toolset.payment.base.enums.OpenEnum;
import com.yonge.toolset.payment.base.enums.PayChannelEnum;
import com.yonge.toolset.payment.base.enums.PaymentClientEnum;
import com.yonge.toolset.payment.base.enums.TradeStatusEnum;
import com.yonge.toolset.payment.base.model.*;
import com.yonge.toolset.payment.base.model.callback.PaymentCallBack;
import com.yonge.toolset.payment.core.props.PaymentProperties;
import com.yonge.toolset.payment.core.service.PaymentClient;
import com.yonge.toolset.payment.util.DistributedLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 前台订单管理Service
 * Created by macro on 2018/8/30.
 */
@Service
public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {

    private static final Logger LOG = LoggerFactory.getLogger(OmsPortalOrderServiceImpl.class);
    @Autowired
    private UmsMemberService memberService;
    @Autowired
    private OmsCartItemService cartItemService;
    @Autowired
    private UmsMemberReceiveAddressService memberReceiveAddressService;
    @Autowired
    private UmsMemberCouponService memberCouponService;
    @Autowired
    private UmsIntegrationConsumeSettingMapper integrationConsumeSettingMapper;
    @Autowired
    private PmsSkuStockMapper skuStockMapper;

    @Autowired
    private OmsOrderMapper orderMapper;
    @Autowired
    private PortalOrderItemDao orderItemDao;
    @Autowired
    private SmsCouponHistoryMapper couponHistoryMapper;
    @Autowired
    private RedisService redisService;
    private String REDIS_KEY_ORDER_ID = "redis.key.orderId";
    private String REDIS_DATABASE = "redis.database";
    @Autowired
    private PortalOrderDao portalOrderDao;

    @Autowired
    private IdGeneratorService idGeneratorService;

    @Autowired
    private OmsOrderSettingMapper orderSettingMapper;
    @Autowired
    private OmsOrderItemMapper orderItemMapper;
    @Autowired
    private CancelOrderSender cancelOrderSender;

    @Autowired
    private AdminFeignService adminFeignService;
    @Autowired
    private UserOrderPaymentService userOrderPaymentService;

    @Autowired(required = true)
    private PaymentClient paymentClient;

    @Autowired
    private PaymentProperties paymentProperties;

    @Autowired
    private PmsProductMapper pmsProductMapper;

    @Autowired
    private UserOrderRefundMapper userOrderRefundMapper;

    @Autowired
    private RedissonClient redissonClient;


    @Autowired
    private PortalProductDao productDao;

    @Override
    public ConfirmOrderResult generateConfirmOrder(List<Long> cartIds) {
        ConfirmOrderResult result = new ConfirmOrderResult();
        //获取购物车信息
        UmsMember currentMember = memberService.getCurrentMember();
        List<CartPromotionItem> cartPromotionItemList = cartItemService.listPromotion(currentMember.getId(), cartIds,
                                                                                      true);
        result.setCartPromotionItemList(cartPromotionItemList);
        //获取用户收货地址列表
        List<UmsMemberReceiveAddress> memberReceiveAddressList = memberReceiveAddressService.list();
        result.setMemberReceiveAddressList(memberReceiveAddressList);
        //获取用户可用优惠券列表
        List<SmsCouponHistoryDetail> couponHistoryDetailList = memberCouponService.listCart(cartPromotionItemList, 1);
        result.setCouponHistoryDetailList(couponHistoryDetailList);
        //获取用户积分
        result.setMemberIntegration(currentMember.getIntegration());
        //获取积分使用规则
        UmsIntegrationConsumeSetting integrationConsumeSetting = integrationConsumeSettingMapper.selectByPrimaryKey(1L);
        result.setIntegrationConsumeSetting(integrationConsumeSetting);
        //计算总金额、活动优惠、应付金额
        ConfirmOrderResult.CalcAmount calcAmount = calcCartAmount(cartPromotionItemList);
        result.setCalcAmount(calcAmount);
        return result;
    }

    @Override
    public Map<String, Object> generateOrder(OrderParam orderParam) {
        if (orderParam.getOrderAmount() == null) {
            throw new BizException("订单金额校验不通过");
        }
        List<OmsOrderItem> orderItemList = new ArrayList<>();
        //获取购物车及优惠信息
        UmsMember currentMember = memberService.getCurrentMember();
        List<CartPromotionItem> cartPromotionItemList = cartItemService.listPromotion(currentMember.getId(),
                                                                                      orderParam.getCartIds(), true);
        for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
            //生成下单商品信息
            OmsOrderItem orderItem = new OmsOrderItem();
            orderItem.setProductId(cartPromotionItem.getProductId());
            orderItem.setProductName(cartPromotionItem.getProductName());
            orderItem.setProductPic(cartPromotionItem.getProductPic());
            orderItem.setProductAttr(cartPromotionItem.getProductAttr());
            orderItem.setProductBrand(cartPromotionItem.getProductBrand());
            orderItem.setProductSn(cartPromotionItem.getProductSn());
            orderItem.setProductPrice(cartPromotionItem.getPrice());
            orderItem.setProductQuantity(cartPromotionItem.getQuantity());
            orderItem.setProductSkuId(cartPromotionItem.getProductSkuId());
            orderItem.setProductSkuCode(cartPromotionItem.getProductSkuCode());
            orderItem.setProductCategoryId(cartPromotionItem.getProductCategoryId());
            orderItem.setPromotionAmount(cartPromotionItem.getReduceAmount());
            orderItem.setPromotionName(cartPromotionItem.getPromotionMessage());
            orderItem.setGiftIntegration(cartPromotionItem.getIntegration());
            orderItem.setGiftGrowth(cartPromotionItem.getGrowth());
            orderItem.setPromoterId(cartPromotionItem.getPromoterId());
            orderItem.setPrecisionAmount(BigDecimal.ZERO);
            orderItemList.add(orderItem);
        }
        //判断购物车中商品是否都有库存
        if (!hasStock(cartPromotionItemList)) {
            Asserts.fail("库存不足，无法下单");
        }
        BigDecimal couponAmount = BigDecimal.ZERO;
        //判断使用使用了优惠券
        if (StringUtil.isEmpty(orderParam.getCouponId())) {
            //不用优惠券
            for (OmsOrderItem orderItem : orderItemList) {
                orderItem.setCouponAmount(new BigDecimal(0));
            }
        } else {
            // todo 使用优惠券 远程调用获取优惠券金额
            // SmsCouponHistoryDetail couponHistoryDetail = getUseCoupon(cartPromotionItemList, orderParam.getCouponId());
            //     if (couponHistoryDetail == null) {
            //         Asserts.fail("该优惠券不可用");
            // }
            //对下单商品的优惠券进行处理
            HttpResponseResult<CouponInfoApi> couponInfoApiHttpResponseResult = adminFeignService.queryCouponOrderPageInfo(
                    currentMember.getId(), orderParam.getCouponId(), orderParam.getOrderAmount(),
                    orderParam.getPlatformType());
            CouponInfoApi data = couponInfoApiHttpResponseResult.getData();
            if(data != null) {
                couponAmount = data.getDiscountedPrices();
            }
            if (couponAmount.compareTo(orderParam.getOrderAmount()) > 0) {
                couponAmount = orderParam.getOrderAmount();
            }
            handleCouponAmount(orderItemList, couponAmount);
        }
        //判断是否使用积分
        if (orderParam.getUseIntegration() == null || orderParam.getUseIntegration().equals(0)) {
            //不使用积分
            for (OmsOrderItem orderItem : orderItemList) {
                orderItem.setIntegrationAmount(new BigDecimal(0));
            }
        } else {
            //使用积分
            BigDecimal totalAmount = calcTotalAmount(orderItemList);
            BigDecimal integrationAmount = getUseIntegrationAmount(orderParam.getUseIntegration(), totalAmount,
                                                                   currentMember, orderParam.getCouponId() != null);
            if (integrationAmount.compareTo(new BigDecimal(0)) == 0) {
                Asserts.fail("积分不可用");
            } else {
                //可用情况下分摊到可用商品中
                for (OmsOrderItem orderItem : orderItemList) {
                    BigDecimal perAmount = orderItem.getProductPrice()
                                                    .divide(totalAmount, 3, RoundingMode.HALF_EVEN)
                                                    .multiply(integrationAmount);
                    orderItem.setIntegrationAmount(perAmount);
                }
            }
        }
        //计算order_item的实付金额
        handleRealAmount(orderItemList);
        //进行sku库存锁定
        lockSkuStock(cartPromotionItemList);

        // 进行商品库存锁定
        lockProductStock(cartPromotionItemList);

        //根据商品合计、运费、活动优惠、优惠券、积分计算应付金额
        OmsOrder order = new OmsOrder();
        String cartIds = orderParam.getCartIds().stream().map(String::valueOf).collect(Collectors.joining());
        order.setCartIds(cartIds);
        order.setDiscountAmount(new BigDecimal(0));
        order.setTotalAmount(calcTotalAmount(orderItemList));
        order.setFreightAmount(new BigDecimal(0));
        order.setPromotionAmount(calcPromotionAmount(orderItemList));
        order.setPromotionInfo(getOrderPromotionInfo(orderItemList));
        order.setPlatformType(orderParam.getPlatformType());
        if (StringUtil.isEmpty(orderParam.getCouponId())) {
            order.setCouponAmount(new BigDecimal(0));
        } else {
            order.setCouponId(orderParam.getCouponId());
            order.setCouponAmount(couponAmount);
        }
        if (orderParam.getUseIntegration() == null) {
            order.setIntegration(0);
            order.setIntegrationAmount(new BigDecimal(0));
        } else {
            order.setIntegration(orderParam.getUseIntegration());
            order.setIntegrationAmount(calcIntegrationAmount(orderItemList));
        }
        LOG.info("payAmount:{},totalAmount:{},couponAmount:{}",order.getTotalAmount().subtract(couponAmount),order.getTotalAmount(),couponAmount);
        if (orderParam.getOrderAmount().compareTo(order.getTotalAmount().subtract(couponAmount)) != 0) {
            throw new BizException("订单金额校验不通过");
        }
        order.setPayAmount(orderParam.getOrderAmount());
        //转化为订单信息并插入数据库
        order.setMemberId(currentMember.getId());
        order.setCreateTime(new Date());
        order.setMemberUsername(currentMember.getUsername());
        //支付方式：0->未支付；1->支付宝；2->微信
        order.setPayType(orderParam.getPayType());
        //订单来源：0->PC订单；1->app订单
        order.setSourceType(1);
        //订单状态：0->待付款；1->待发货；2->已发货；3->已完成；4->已关闭；5->无效订单 6 -> 未支付
        order.setStatus(6);
        //订单类型：0->正常订单；1->秒杀订单
        order.setOrderType(0);
        //收货人信息：姓名、电话、邮编、地址
        UmsMemberReceiveAddress address = memberReceiveAddressService.getItem(orderParam.getMemberReceiveAddressId());
        order.setReceiverName(address.getName());
        order.setReceiverPhone(address.getPhoneNumber());
        order.setReceiverPostCode(address.getPostCode());
        order.setReceiverProvince(address.getProvince());
        order.setReceiverCity(address.getCity());
        order.setReceiverRegion(address.getRegion());
        order.setReceiverDetailAddress(address.getDetailAddress());
        //0->未确认；1->已确认
        order.setConfirmStatus(0);
        order.setDeleteStatus(0);
        //计算赠送积分
        order.setIntegration(calcGifIntegration(orderItemList));
        //计算赠送成长值
        order.setGrowth(calcGiftGrowth(orderItemList));
        //生成订单号
        order.setOrderSn(generateOrderSn(order));
        //设置自动收货天数
        List<OmsOrderSetting> orderSettings = orderSettingMapper.selectByExample(new OmsOrderSettingExample());
        if (CollUtil.isNotEmpty(orderSettings)) {
            order.setAutoConfirmDay(orderSettings.get(0).getConfirmOvertime());
        }
        //插入order表和order_item表
        orderMapper.insert(order);
        for (OmsOrderItem orderItem : orderItemList) {
            orderItem.setOrderId(order.getId());
            orderItem.setOrderSn(order.getOrderSn());
        }
        orderItemDao.insertList(orderItemList);
        //如使用优惠券更新优惠券使用状态
        if (orderParam.getCouponId() != null) {
            // updateCouponStatus(orderParam.getCouponId(), currentMember.getId(), 1);
            // todo 远程调用更新优惠券使用
            adminFeignService.updateCouponOrderInfo(orderParam.getCouponId(),false,order.getOrderSn());
        }
        //如使用积分需要扣除积分
        if (orderParam.getUseIntegration() != null) {
            order.setUseIntegration(orderParam.getUseIntegration());
            memberService.updateIntegration(currentMember.getId(),
                                            currentMember.getIntegration() - orderParam.getUseIntegration());
        }
        //删除购物车中的下单商品
        deleteCartItemList(cartPromotionItemList, currentMember);
        //发送延迟消息取消订单
        sendDelayMessageCancelOrder(order.getId());
        Map<String, Object> result = new HashMap<>();
        result.put("order", order);
        result.put("orderItemList", orderItemList);
        if (order.getPayAmount().compareTo(BigDecimal.ZERO) == 0) {
            paySuccess(order.getId(),order.getPayType());
            order.setStatus(1);
        }
        return result;
    }

    @Override
    public Integer paySuccess(Long orderId, Integer payType) {
        //修改订单支付状态
        OmsOrder order = new OmsOrder();
        order.setId(orderId);
        order.setStatus(1);
        order.setPaymentTime(new Date());
        order.setPayType(payType);
        orderMapper.updateByPrimaryKeySelective(order);
        //恢复所有下单商品的锁定库存，扣减真实库存
        OmsOrderDetail orderDetail = portalOrderDao.getDetail(orderId);
        // 减sku库存
        int count = portalOrderDao.updateSkuStock(orderDetail.getOrderItemList());

        // 减商品库存
        updateProductStock(orderDetail);

        // 查询订单
        OmsOrderDetail detail = detail(orderId);

        // 设置平台收入和分润
        setPromoterRecord(detail,PostStatusEnum.WAIT);

        // 签协议
        adminFeignService.contractRecord(new ContractDto(orderDetail.getPlatformType(),orderDetail.getMemberId()));

        return count;
    }

    private void setPromoterRecord(OmsOrderDetail detail,PostStatusEnum status) {

        List<OmsOrderItem> orderItemList = detail.getOrderItemList();

        // orderItemList = orderItemList.stream().filter(omsOrderItem -> omsOrderItem.getPromoterId() != null).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(orderItemList) ) {
            return;
        }

        List<MallOrderItemDto> list = new ArrayList<>();
        for (OmsOrderItem omsOrderItem : orderItemList) {
            if (omsOrderItem.getReturnStatus() != -1) {
                continue;
            }
            MallOrderItemDto teacherShareDto = new MallOrderItemDto();
            BeanUtils.copyProperties(omsOrderItem,teacherShareDto);
            teacherShareDto.setRealAmount(omsOrderItem.getRealAmount().multiply(BigDecimal.valueOf(omsOrderItem.getProductQuantity()))
                                                      .subtract(omsOrderItem.getPrecisionAmount()));
            teacherShareDto.setStatus(status);
            teacherShareDto.setUserId(detail.getMemberId());
            list.add(teacherShareDto);
        }
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        HttpResponseResult<Boolean> result;
        if (status.equals(PostStatusEnum.WAIT)) {
            result = adminFeignService.mallRecord(list);
        } else {
            result = adminFeignService.mallRecordState(list);
        }
        if (result.getStatus()) {
            LOG.debug("分润记录写入成功，json: {}",JSON.toJSONString(list));
        } else {
            LOG.error("分润记录写入失败，json: {}",JSON.toJSONString(list));
        }
    }

    /**
     * 减商品库存
     */
    private void updateProductStock(OmsOrderDetail orderDetail) {
        Map<Long, List<OmsOrderItem>> collect = orderDetail.getOrderItemList()
                                                           .stream()
                                                           .collect(Collectors.groupingBy(OmsOrderItem::getProductId));

        List<ProductStock> productStockList = new ArrayList<>();
        for (Map.Entry<Long, List<OmsOrderItem>> entry : collect.entrySet()) {
            ProductStock stock = new ProductStock();
            stock.setProductId(entry.getKey());
            List<OmsOrderItem> value = entry.getValue();
            if (CollectionUtils.isEmpty(value)) {
                continue;
            }
            int sum = value.stream().mapToInt(OmsOrderItem::getProductQuantity).sum();
            stock.setStock(sum);
            productStockList.add(stock);
        }
        productDao.updateProductStock(productStockList);
    }

    @Override
    public Integer cancelTimeOutOrder() {
        Integer count = 0;
        OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L);
        //查询超时、未支付的订单及订单详情
        List<OmsOrderDetail> timeOutOrders = portalOrderDao.getTimeOutOrders(orderSetting.getNormalOrderOvertime(),
                                                                             orderSetting.getPayOrderOvertime());
        if (CollectionUtils.isEmpty(timeOutOrders)) {
            return count;
        }
        for (OmsOrderDetail timeOutOrder : timeOutOrders) {

            DistributedLock.of(redissonClient)
                           .runIfLockCanGet(OrderCacheEnum.LOCK_ORDER_NO_MALL.getRedisKey(timeOutOrder.getOrderSn())
                                   , () -> {
                                       if (timeOutOrder.getStatus() == 0) {
                                           payingOrderHandle(timeOutOrder);
                                       } else if (timeOutOrder.getStatus() == 6) {
                                           try {
                                               cancelOrder(timeOutOrder.getId(), "超时取消", null);
                                           } catch (Exception e) {
                                               LOG.warn("订单取消失败,{}",e.fillInStackTrace());
                                           }
                                       }
                                   }, 60L, TimeUnit.SECONDS);

        }
        return timeOutOrders.size();
    }

    @Override
    public void cancelOrder(Long orderId, String message, PaymentCallBack data) {
        //查询未付款的取消订单
        OmsOrderExample example = new OmsOrderExample();
        example.createCriteria().andIdEqualTo(orderId).andDeleteStatusEqualTo(0);
        List<OmsOrder> cancelOrderList = orderMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(cancelOrderList)) {
            return;
        }
        OmsOrder cancelOrder = cancelOrderList.get(0);
        if (cancelOrder != null && (cancelOrder.getStatus() == 0 || cancelOrder.getStatus() == 6)) {

            // 查询订单是否为支付
            UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNoAndStatusPaying(cancelOrder.getOrderSn());

            if (orderPayment != null) {
                // 查询订单信息
                BaseResult<Payment> res = getPaymentBaseResult(orderPayment);
                //支付成功
                if (res.getStatus() && TradeStatusEnum.succeeded.getCode().equals(res.getData().getStatus().getCode())
                        && cancelOrder.getStatus() == 0) {
                    orderSuccess(cancelOrder,null, res.getData());
                    return;
                }

                //查询订单下支付中的付款单，取消支付
                userOrderPaymentService.closePayment(orderPayment.getOrderNo(),  "用户发起了新的付款请求", null);
            }

            //修改订单状态为取消
            cancelOrder.setStatus(4);
            orderMapper.updateByPrimaryKeySelective(cancelOrder);
            OmsOrderItemExample orderItemExample = new OmsOrderItemExample();
            orderItemExample.createCriteria().andOrderIdEqualTo(orderId);
            List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(orderItemExample);
            //解除订单商品库存锁定
            if (!CollectionUtils.isEmpty(orderItemList)) {
                portalOrderDao.releaseSkuStockLock(orderItemList);
                portalOrderDao.releaseProductStockLock(orderItemList);
            }
            //修改优惠券使用状态
            // updateCouponStatus(cancelOrder.getCouponId(), cancelOrder.getMemberId(), 0);
            // todo 退回优惠券

            adminFeignService.updateCouponOrderInfo(cancelOrder.getCouponId(),true,cancelOrder.getOrderSn());
            //返还使用积分
            if (cancelOrder.getUseIntegration() != null) {
                UmsMember member = memberService.getById(cancelOrder.getMemberId());
                memberService.updateIntegration(cancelOrder.getMemberId(),
                                                member.getIntegration() + cancelOrder.getUseIntegration());
            }
            // 发起关单
            userOrderPaymentService.closePayment(cancelOrder.getOrderSn(), message, data);

        } else {
            throw new BizException("订单状态非待支付和支付中，不能取消");
        }
    }

    @Override
    public void sendDelayMessageCancelOrder(Long orderId) {
        //获取订单超时时间
        OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L);
        long delayTimes = orderSetting.getNormalOrderOvertime() * 60 * 1000L;
        //发送延迟消息
        cancelOrderSender.sendMessage(orderId, delayTimes);
    }

    @Override
    public void confirmReceiveOrder(Long orderId) {
        // UmsMember member = memberService.getCurrentMember();
        OmsOrder order = orderMapper.selectByPrimaryKey(orderId);
        // if (!member.getId().equals(order.getMemberId())) {
        //     Asserts.fail("不能确认他人订单！");
        // }
        if (order.getStatus() != 2) {
            Asserts.fail("该订单还未发货！");
        }else if (order.getStatus() == 3) {
            Asserts.fail("已确认收货！");
        }
        order.setStatus(3);
        order.setConfirmStatus(1);
        order.setReceiveTime(new Date());
        orderMapper.updateByPrimaryKey(order);

    }

    @Override
    public CommonPage<OmsOrderDetail> list(String status, Integer pageNum, Integer pageSize) {
        if (status.equals("-1")) {
            status = null;
        }
        UmsMember member = memberService.getCurrentMember();
        PageHelper.startPage(pageNum, pageSize);
        OmsOrderExample orderExample = new OmsOrderExample();
        OmsOrderExample.Criteria criteria = orderExample.createCriteria();
        criteria.andDeleteStatusEqualTo(0).andMemberIdEqualTo(member.getId());
        if (status != null && !StringUtil.isEmpty(status)) {
            List<Long> list = StringUtil.toLongList(status);
            List<Integer> collect = list.stream().map(Long::intValue).collect(Collectors.toList());
            criteria.andStatusIn(collect);
        }
        orderExample.setOrderByClause(" field(status,'0','6','1','2','3','4','5'),create_time desc");
        List<OmsOrder> orderList = orderMapper.selectByExample(orderExample);
        CommonPage<OmsOrder> orderPage = CommonPage.restPage(orderList);
        //设置分页信息
        CommonPage<OmsOrderDetail> resultPage = new CommonPage<>();
        resultPage.setPageNum(orderPage.getPageNum());
        resultPage.setPageSize(orderPage.getPageSize());
        resultPage.setTotal(orderPage.getTotal());
        resultPage.setTotalPage(orderPage.getTotalPage());
        if (CollUtil.isEmpty(orderList)) {
            return resultPage;
        }
        //设置数据信息
        List<Long> orderIds = orderList.stream().map(OmsOrder::getId).collect(Collectors.toList());
        OmsOrderItemExample orderItemExample = new OmsOrderItemExample();
        orderItemExample.createCriteria().andOrderIdIn(orderIds);
        List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(orderItemExample);
        List<OmsOrderDetail> orderDetailList = new ArrayList<>();
        for (OmsOrder omsOrder : orderList) {
            OmsOrderDetail orderDetail = new OmsOrderDetail();
            BeanUtil.copyProperties(omsOrder, orderDetail);
            List<OmsOrderItem> relatedItemList = orderItemList.stream()
                                                              .filter(item -> item.getOrderId()
                                                                                  .equals(orderDetail.getId()))
                                                              .collect(Collectors.toList());
            orderDetail.setOrderItemList(relatedItemList);
            orderDetailList.add(orderDetail);
        }
        resultPage.setList(orderDetailList);
        return resultPage;
    }

    @Override
    public OmsOrderDetail detail(Long orderId) {
        OmsOrder omsOrder = orderMapper.selectByPrimaryKey(orderId);
        OmsOrderItemExample example = new OmsOrderItemExample();
        example.createCriteria().andOrderIdEqualTo(orderId);
        List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(example);
        OmsOrderDetail orderDetail = new OmsOrderDetail();
        BeanUtil.copyProperties(omsOrder, orderDetail);
        orderDetail.setOrderItemList(orderItemList);
        return orderDetail;
    }

    @Override
    public OmsOrderDetail detail(String orderSn) {
        OmsOrderExample orderExample = new OmsOrderExample();
        orderExample.createCriteria().andOrderSnEqualTo(orderSn);
        List<OmsOrder> omsOrders = orderMapper.selectByExample(orderExample);
        if (CollUtil.isEmpty(omsOrders)) {
            throw new BizException("订单信息错误");
        } else if (omsOrders.size() != 1) {
            throw new BizException("订单号重复");
        }
        OmsOrder omsOrder = omsOrders.get(0);
        OmsOrderItemExample example = new OmsOrderItemExample();
        example.createCriteria().andOrderIdEqualTo(omsOrder.getId());
        List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(example);
        OmsOrderDetail orderDetail = new OmsOrderDetail();
        BeanUtil.copyProperties(omsOrder, orderDetail);
        orderDetail.setOrderItemList(orderItemList);
        return orderDetail;
    }

    @Override
    public void deleteOrder(Long orderId) {
        UmsMember member = memberService.getCurrentMember();
        OmsOrder order = orderMapper.selectByPrimaryKey(orderId);
        if (!member.getId().equals(order.getMemberId())) {
            Asserts.fail("不能删除他人订单！");
        }
        if (order.getStatus() == 3 || order.getStatus() == 4) {
            order.setDeleteStatus(1);
            orderMapper.updateByPrimaryKey(order);
        } else {
            Asserts.fail("只能删除已完成或已关闭的订单！");
        }
    }

    @Override
    @Transactional
    public OrderPayRes orderPay(OrderPayReq payReq) {
        OrderPayRes orderPayRes = new OrderPayRes();
        OmsOrderDetail detail = detail(payReq.getOrderNo());
        if (detail == null) {
            orderPayRes.setStatus(false);
            orderPayRes.setMessage("订单不存在");
            return orderPayRes;
        }
        if (detail.getStatus() != 0 && detail.getStatus() != 6) {
            orderPayRes.setStatus(false);
            orderPayRes.setMessage("订单已付款或已关闭");
            return orderPayRes;
        }
        UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNoAndStatusPaying(detail.getOrderSn());

        if (orderPayment != null) {
            // 查询订单信息
            BaseResult<Payment> res = getPaymentBaseResult(orderPayment);
            //支付成功
            if (res.getStatus() && TradeStatusEnum.succeeded.getCode().equals(res.getData().getStatus().getCode())
                    && detail.getStatus() == 0) {
                orderSuccess(detail,null, res.getData());
                orderPayRes.setStatus(false);
                orderPayRes.setMessage("订单已付款或已关闭");
                return orderPayRes;
            }

            //查询订单下支付中的付款单，取消支付
            userOrderPaymentService.closePayment(orderPayment.getOrderNo(),  "用户发起了新的付款请求", null);
        }

        //构建汇付统一下单请求
        OpenEnum openType = OpenEnum.valueOf(paymentProperties.getOpenType());
        Payment payment = new Payment(openType, PaymentClientEnum.valueOf(payReq.getPaymentClient()),
                                      payReq.getPayChannel());
        payment.setPaymentNo(generateOrderSn(detail));
        payment.setOrderNo(payReq.getOrderNo());
        payment.setOrderTitle("酷乐秀商城订单编号-" + detail.getOrderSn());
        payment.setOrderDesc("酷乐秀商城订单编号-" + detail.getOrderSn());

        //封装订单详情
        List<OrderDetil> orderDetails = new ArrayList<>();
        for (OmsOrderItem orderDetailVo : detail.getOrderItemList()) {
            orderDetails.add(new OrderDetil(orderDetailVo.getId().toString(), orderDetailVo.getProductName(),
                                            orderDetailVo.getProductQuantity(),
                                            orderDetailVo.getRealAmount().toString()));
        }
        payment.setOrderDetils(orderDetails);
        payment.setPayAmt(detail.getPayAmount().setScale(2, RoundingMode.HALF_UP).toString());
        payment.setDescription(payReq.getReason());

        if (OpenEnum.ADAPAY.equals(openType)) {
            //创建分账对象
            DivMember div_member = new DivMember();
            div_member.setMember_id("0");
            div_member.setAmount(detail.getPayAmount().setScale(2, RoundingMode.HALF_UP).toString());
            div_member.setFee_flag("Y");
            List<DivMember> div_members = Arrays.asList(div_member);
            payment.setDivMembers(div_members);

            //前端设备信息
            DeviceInfo deviceInfo = new DeviceInfo();
            deviceInfo.setDevice_ip(payReq.getIpAddress());
            payment.setDeviceInfo(deviceInfo);

            if (PayChannelEnum.wx_lite.equals(payReq.getPayChannel())) {
                Map<String, Object> expend = new HashMap<>();
                expend.put("open_id", payReq.getOpenId());
                payment.setExpend(expend);
            }
        }
        // 支付中的返回拉起信息
        BaseResult<Payment> executePayment = paymentClient.executePayment(payment);
        if (!executePayment.getStatus()) {
            // 异常将取消订单
            // cancelOrder(detail.getId(), executePayment.getMsg(), null);
            throw new BizException(executePayment.getMsg());
        }
        if (!executePayment.getData()
                           .getPayAmt()
                           .equals(detail.getPayAmount().setScale(2, RoundingMode.HALF_UP).toString())) {
            // cancelOrder(detail.getId(), "订单金额和实际支付金额不符", null);
            throw new BizException("订单金额和实际支付金额不符");
        }


        saveOrderPayment(executePayment.getData(), detail, payReq.getPaymentClient());

        if (executePayment.getStatus()) {
            orderPayRes.setPay_amt(detail.getPayAmount().setScale(2, RoundingMode.HALF_UP).toString());
            String pay_info = executePayment.getData().getPayInfo();
            orderPayRes.setPay_info(pay_info);
            orderPayRes.setPayChannel(payReq.getPayChannel().getCode());
            orderPayRes.setPaymentNo(payment.getPaymentNo());
            orderPayRes.setStatus(true);

        } else {
            orderPayRes.setMessage(executePayment.getMsg());
            orderPayRes.setStatus(false);
        }
        return orderPayRes;
    }

    private BaseResult<Payment> getPaymentBaseResult(UserOrderPayment orderPayment) {
        Payment param = new Payment(OpenEnum.valueOf(orderPayment.getOpenType()),
                                    PaymentClientEnum.valueOf(orderPayment.getPaymentClient()),
                                    PayChannelEnum.valueOf(orderPayment.getPayChannel()));
        param.setId(orderPayment.getTransNo());
        param.setPaymentNo(orderPayment.getAdapayNo());
        return paymentClient.queryPayment(param);
    }


    private void saveOrderPayment(Payment payment, OmsOrderDetail detail, String paymentClient) {
        UserOrderPayment userOrderPayment;
        OmsOrder omsOrder = new OmsOrder();
        omsOrder.setId(detail.getId());

        omsOrder.setStatus(0);
        orderMapper.updateByPrimaryKeySelective(omsOrder);
        // 保存订单支付表
        userOrderPayment = new UserOrderPayment();
        userOrderPayment.setPaymentClient(paymentClient);
        userOrderPayment.setOpenType(paymentProperties.getOpenType());
        userOrderPayment.setOrderNo(detail.getOrderSn());
        userOrderPayment.setAdapayNo(payment.getPaymentNo());
        userOrderPayment.setPayChannel(payment.getPayChannel().getCode());
        userOrderPayment.setTransNo(payment.getId());
        userOrderPayment.setPayAmt(new BigDecimal(payment.getPayAmt()));
        userOrderPayment.setPayInfo(payment.getPayInfo());
        userOrderPayment.setStatus(TradeStatusEnum.pending.getCode());
        userOrderPayment.setPayFailMsg("");
        userOrderPayment.setCreateTime(new Date());
        userOrderPayment.setUpdateTime(new Date());

        userOrderPaymentService.save(userOrderPayment);
    }

    @Override
    public OmsOrder getOrderById(Long orderId) {
        return orderMapper.selectByPrimaryKey(orderId);
    }

    @Override
    public void executePaymentCallBack(PaymentCallBack data) {
        LOG.info("支付回调信息： {}",JSON.toJSONString(data));
        if (TradeStatusEnum.succeeded.equals(data.getStatus())) {//支付成功
            paymentSucceededHandle(data);
        } else if (TradeStatusEnum.failed.equals(data.getStatus())) {//支付失败
            paymentFailedHandle(data);
        }
    }

    @Override
    public void closePaymentCallBack(PaymentCallBack data) {

        LOG.info("关单回调信息： {}",JSON.toJSONString(data));
        if (TradeStatusEnum.succeeded.equals(data.getStatus())) {//关单成功
            paymentCloseSucceededHandle(data);
        } else if (TradeStatusEnum.failed.equals(data.getStatus())) {//关单失败
            paymentCloseFailedHandle(data);
        }
    }

    @Override
    public Integer autoReceive() {
        OmsOrderSetting omsOrderSetting = orderSettingMapper.selectByPrimaryKey(1L);
        Integer confirmOvertime = omsOrderSetting.getConfirmOvertime();
        LocalDateTime localDateTime = LocalDateTime.now().plusDays(-confirmOvertime);
        OmsOrderExample orderExample = new OmsOrderExample();
        orderExample.createCriteria().andStatusEqualTo(2).andDeleteStatusEqualTo(0).andConfirmStatusEqualTo(0)
                .andDeliveryTimeLessThanOrEqualTo(Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()));

        List<OmsOrder> omsOrders = orderMapper.selectByExample(orderExample);
        if (CollectionUtils.isEmpty(omsOrders)) {
            return 0;
        }
        for (OmsOrder omsOrder : omsOrders) {

            DistributedLock.of(redissonClient)
                           .runIfLockCanGet(OrderCacheEnum.LOCK_ORDER_NO_MALL.getRedisKey(omsOrder.getOrderSn())
                                   , () -> {
                                        try {
                                            this.confirmReceiveOrder(omsOrder.getId());

                                        }catch (Exception e) {
                                            LOG.warn("订单收货，{}",e.fillInStackTrace());
                                        }
                                   }, 60L, TimeUnit.SECONDS);
        }
        return omsOrders.size();

    }

    @Override
    public Integer shareProfit() {
        OmsOrderSetting omsOrderSetting = orderSettingMapper.selectByPrimaryKey(1L);
        Integer finishOvertime = omsOrderSetting.getFinishOvertime();
        LocalDateTime localDateTime = LocalDateTime.now().plusDays(-finishOvertime);
        OmsOrderExample orderExample = new OmsOrderExample();
        orderExample.createCriteria().andStatusEqualTo(3).andDeleteStatusEqualTo(0).andConfirmStatusEqualTo(1)
                .andAfterSaleEqualTo(0)
                .andReceiverCityIsNotNull()
                    .andReceiveTimeLessThan(Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()));

        List<OmsOrder> omsOrders = orderMapper.selectByExample(orderExample);
        if (CollectionUtils.isEmpty(omsOrders)) {
            return 0;
        }
        for (OmsOrder omsOrder : omsOrders) {

            DistributedLock.of(redissonClient)
                           .runIfLockCanGet(OrderCacheEnum.LOCK_ORDER_NO_MALL.getRedisKey(omsOrder.getOrderSn())
                                   , () -> {
                               try {
                                   this.FinishReceiveOrder(omsOrder.getId());

                               } catch (Exception e) {
                                   LOG.warn("停止售后失败，{}",e.fillInStackTrace());
                               }
                                   }, 60L, TimeUnit.SECONDS);
        }
        return omsOrders.size();
    }

    private void FinishReceiveOrder(Long orderId) {

        // UmsMember member = memberService.getCurrentMember();
        OmsOrder order = orderMapper.selectByPrimaryKey(orderId);
        // if (!member.getId().equals(order.getMemberId())) {
        //     Asserts.fail("不能确认他人订单！");
        // }
         if (order.getStatus() != 3) {
            Asserts.fail("未确认收货！");
        }
        order.setAfterSale(1);
        orderMapper.updateByPrimaryKey(order);


        // 设置平台收入和分润 实际收款
        setPromoterRecord(detail(orderId), PostStatusEnum.RECORDED);
    }


    /***
     * 处理回调-支付成功
     * @author liweifan
     * @param: hfRes
     * @updateTime 2022/4/27 15:09
     */
    private void paymentSucceededHandle(PaymentCallBack data) {
        //订单完成
        UserOrderPayment userOrderPayment = userOrderPaymentService.getByAdapayNo(data.getPaymentNo());
        if (null == userOrderPayment) {
            String string = JSON.toJSONString(data);
            LOG.error("汇付支付回调，订单未找到。 req is {}", string);
            return;
        }
        OmsOrderDetail detail = detail(userOrderPayment.getOrderNo());
        if (detail.getStatus() == 0) {
            orderSuccess(detail, data, null);
        } else {
            LOG.error("汇付支付回调，订单状态异常。 req is {}", detail.getOrderSn());
            LOG.warn("支付金额原路退回 {}", detail.getOrderSn());
            orderRefund(userOrderPayment,data.getExecutePaymentCallBack().getPayAmt(),data.getId(),detail);
        }
    }

    /**
     * 支付成功，业务退款
     */
    private void orderRefund(UserOrderPayment userOrderPayment,String refundAmount,String payTransNo,OmsOrder order) {
        UserOrderRefund userOrderRefund = userOrderRefundMapper.selectByPayOrderNo(userOrderPayment.getAdapayNo());
        if (userOrderRefund != null && userOrderRefund.getStatus().equals("succeeded")) {
            LOG.warn("支付金额已退回");
            return;
        }

        String orderSn = generateOrderSn(order);

        RefundBill refundReq = new RefundBill(OpenEnum.valueOf(userOrderPayment.getOpenType()), PaymentClientEnum.valueOf(userOrderPayment.getPaymentClient()), PayChannelEnum.valueOf(userOrderPayment.getPayChannel()));
        refundReq.setRefundNo(orderSn);
        refundReq.setRefundAmt(new BigDecimal(refundAmount));

        refundReq.setReason("支付超时,全额退回");
        refundReq.setPaymentNo(userOrderPayment.getAdapayNo());
        refundReq.setTradeNo(payTransNo);
        refundReq.setOrderAmt(userOrderPayment.getPayAmt());
        BaseResult<RefundBill> refundBillBaseResult = paymentClient.refundPayment(refundReq);
        userOrderRefund = new UserOrderRefund();
        userOrderRefund.setOrderNo(orderSn);
        userOrderRefund.setPayTransNo(payTransNo);
        userOrderRefund.setRefundAmt(new BigDecimal(refundAmount));
        userOrderRefund.setPayOrderNo(userOrderPayment.getOrderNo());
        if (refundBillBaseResult.getStatus()) {
            RefundBill refundBill = refundBillBaseResult.getData();
            userOrderRefund.setRefundAmt(refundBill.getRefundAmt());
            userOrderRefund.setStatus(TradeStatusEnum.pending.getCode());
        } else {
            userOrderRefund.setStatus(TradeStatusEnum.failed.getCode());
            userOrderRefund.setPayFailMsg("退款失败：" + refundBillBaseResult.getMsg());
        }
        userOrderRefundMapper.insert(userOrderRefund);
    }
    /***
     * 处理回调-支付失败
     * @author liweifan
     * @param: hfRes
     * @updateTime 2022/4/27 15:09
     */
    private void paymentFailedHandle(PaymentCallBack data) {
        //订单完成
        UserOrderPayment userOrderPayment = userOrderPaymentService.getByAdapayNo(data.getPaymentNo());
        String dataString = JSON.toJSONString(data);
        if (null == userOrderPayment) {
            LOG.error("汇付支付回调，订单未找到。 req is {}", dataString);
            return;
        }

        OmsOrderDetail detail = detail(userOrderPayment.getOrderNo());
        if (null == detail) {
            LOG.error("汇付支付回调，订单未找到。 req is {}", dataString);
            return;
        }
        if (detail.getStatus() == 0) {

            cancelOrder(detail.getId(), data.getErrMsg(), data);
        } else {
            LOG.error("汇付支付回调，订单状态异常。 req is {}", dataString);
        }
    }

    /***
     * 支付关单成功
     * @author liweifan
     * @param: hfRes
     * @updateTime 2022/4/27 15:33
     */
    private void paymentCloseSucceededHandle(PaymentCallBack data) {
        UserOrderPayment orderPayment = userOrderPaymentService.getByAdapayNo(data.getPaymentNo());
        if (null == orderPayment) {
            return;
        }
        orderPayment.setStatus(TradeStatusEnum.failed.getCode());
        orderPayment.setTransNo(data.getId());
        orderPayment.setCloseStatus(TradeStatusEnum.succeeded.getCode());
        orderPayment.setCloseTime(data.getClosePaymentCallBack().getTradeTime());
        userOrderPaymentService.saveOrUpdate(orderPayment);
    }

    /***
     * 支付关单失败
     * @author liweifan
     * @param: hfRes
     * @updateTime 2022/4/27 15:33
     */
    private void paymentCloseFailedHandle(PaymentCallBack data) {
        UserOrderPayment orderPayment = userOrderPaymentService.getByAdapayNo(data.getPaymentNo());
        if (null == orderPayment) {
            return;
        }
        orderPayment.setStatus(TradeStatusEnum.failed.getCode());
        orderPayment.setCloseStatus(TradeStatusEnum.failed.getCode());
        orderPayment.setCloseTime(data.getClosePaymentCallBack().getTradeTime());
        orderPayment.setPayFailMsg("支付关单回调失败-" + data.getErrMsg());
        orderPayment.setUpdateTime(new Date());
        userOrderPaymentService.saveOrUpdate(orderPayment);
    }

    /***
     * 处理支付中订单
     */
    void payingOrderHandle(OmsOrder userOrder) {
        //判断汇付订单状态
        UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNoAndStatusPaying(userOrder.getOrderSn());
        if (null == orderPayment) {
            cancelOrder(userOrder.getId(), "支付超时", null);
            return;
        }
        OmsOrderDetail detail = detail(orderPayment.getOrderNo());
        try {
            BaseResult<Payment> res = getPaymentBaseResult(orderPayment);
            //支付成功
            if (res.getStatus() && TradeStatusEnum.succeeded.getCode()
                                                            .equals(res.getData()
                                                                       .getStatus()
                                                                       .getCode()) && detail.getStatus() == 0) {
                orderSuccess(detail,null, res.getData());
                return;
            }
            //支付失败
            if (!res.getStatus()) {
                cancelOrder(userOrder.getId(), res.getMsg(), null);
                return;
            }
            cancelOrder(userOrder.getId(), "支付超时", null);
        } catch (Exception e) {
            e.printStackTrace();
            LOG.error("轮询处理支付中订单异常，异常参数: {}", JSON.toJSONString(userOrder));
        }
    }


    /**
     * 订单完成
     *
     * @param: detail
     * @updateTime 2022/4/13 17:17
     */
    @Transactional(rollbackFor = Exception.class)
    public void orderSuccess(OmsOrder detail, PaymentCallBack data,Payment payment) {
        //更新订单
        UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNoAndStatusPaying(detail.getOrderSn());

        if (orderPayment == null) {
            LOG.error("支付回调，支付中订单未找到。 orderNo is {}", detail.getOrderSn());
            return;
        }

        // 判断支付金额 是否正确
        BigDecimal pay_amt;
        if (data != null) {
            pay_amt = new BigDecimal(data.getExecutePaymentCallBack().getPayAmt());

            orderPayment.setTransNo(data.getId());
        } else {
            pay_amt = new BigDecimal(payment.getPayAmt());
            orderPayment.setTransNo(payment.getId());
        }
        if (pay_amt.compareTo(detail.getPayAmount()) != 0) {
            orderPayment.setPayFailMsg("订单金额和实际支付金额不符");
            orderRefund(orderPayment,pay_amt.setScale(2, RoundingMode.HALF_UP).toString(),orderPayment.getTransNo(),detail);
        } else {

            if (orderPayment.getPayChannel().equals("alipay") || orderPayment.getPayChannel().equals("ali_app")) {
                paySuccess(detail.getId(), 1);
            } else if (orderPayment.getPayChannel().equals("wx_lite") || orderPayment.getPayChannel().equals("wx_app")) {
                paySuccess(detail.getId(), 2);
            }
        }

        orderPayment.setStatus(TradeStatusEnum.succeeded.getCode());
        orderPayment.setArrivalTime(new Date());
        orderPayment.setPayAmt(pay_amt);
        if (null != data) {
            try {
                orderPayment.setArrivalTime(data.getExecutePaymentCallBack().getTradeTime());
                orderPayment.setTransNo(data.getId());
                orderPayment.setFeeAmt(new BigDecimal(data.getExecutePaymentCallBack().getFeeAmt()));
            } catch (Exception e) {
                e.printStackTrace();
                LOG.error("完成订单，付款单金额格式化失败,参数{}", JSON.toJSONString(data));
            }
        }
        userOrderPaymentService.saveOrUpdate(orderPayment);

    }


    /**
     * 生成18位订单编号:8位日期+2位平台号码+2位支付方式+6位以上自增id
     */
    private String generateOrderSn(OmsOrder order) {
        return String.valueOf(idGeneratorService.generatorId("mall"));
    }

    /**
     * 删除下单商品的购物车信息
     */
    private void deleteCartItemList(List<CartPromotionItem> cartPromotionItemList, UmsMember currentMember) {
        List<Long> ids = new ArrayList<>();
        for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
            ids.add(cartPromotionItem.getId());
        }
        cartItemService.delete(currentMember.getId(), ids);
    }

    /**
     * 计算该订单赠送的成长值
     */
    private Integer calcGiftGrowth(List<OmsOrderItem> orderItemList) {
        int sum = 0;
        for (OmsOrderItem orderItem : orderItemList) {
            sum = sum + orderItem.getGiftGrowth() * orderItem.getProductQuantity();
        }
        return sum;
    }

    /**
     * 计算该订单赠送的积分
     */
    private Integer calcGifIntegration(List<OmsOrderItem> orderItemList) {
        int sum = 0;
        for (OmsOrderItem orderItem : orderItemList) {
            sum += orderItem.getGiftIntegration() * orderItem.getProductQuantity();
        }
        return sum;
    }

    /**
     * 将优惠券信息更改为指定状态
     *
     * @param couponId  优惠券id
     * @param memberId  会员id
     * @param useStatus 0->未使用；1->已使用
     */
    private void updateCouponStatus(Long couponId, Long memberId, Integer useStatus) {
        if (couponId == null) return;
        //查询第一张优惠券
        SmsCouponHistoryExample example = new SmsCouponHistoryExample();
        example.createCriteria()
               .andMemberIdEqualTo(memberId)
               .andCouponIdEqualTo(couponId)
               .andUseStatusEqualTo(useStatus == 0 ? 1 : 0);
        List<SmsCouponHistory> couponHistoryList = couponHistoryMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(couponHistoryList)) {
            SmsCouponHistory couponHistory = couponHistoryList.get(0);
            couponHistory.setUseTime(new Date());
            couponHistory.setUseStatus(useStatus);
            couponHistoryMapper.updateByPrimaryKeySelective(couponHistory);
        }
    }

    private void handleRealAmount(List<OmsOrderItem> orderItemList) {
        for (OmsOrderItem orderItem : orderItemList) {
            //原价-促销优惠-优惠券抵扣-积分抵扣
            BigDecimal realAmount = orderItem.getProductPrice()
                                             .subtract(orderItem.getPromotionAmount())
                                             .subtract(orderItem.getCouponAmount())
                                             .subtract(orderItem.getIntegrationAmount());
            orderItem.setRealAmount(realAmount);
        }
    }

    /**
     * 获取订单促销信息
     */
    private String getOrderPromotionInfo(List<OmsOrderItem> orderItemList) {
        StringBuilder sb = new StringBuilder();
        for (OmsOrderItem orderItem : orderItemList) {
            sb.append(orderItem.getPromotionName());
            sb.append(";");
        }
        String result = sb.toString();
        if (result.endsWith(";")) {
            result = result.substring(0, result.length() - 1);
        }
        return result;
    }

    /**
     * 计算订单应付金额
     */
    private BigDecimal calcPayAmount(OmsOrder order) {
        //总金额+运费-促销优惠-优惠券优惠-积分抵扣
        return order.getTotalAmount()
                    .add(order.getFreightAmount())
                    .subtract(order.getPromotionAmount())
                    .subtract(order.getCouponAmount())
                    .subtract(order.getIntegrationAmount());
    }

    /**
     * 计算订单优惠券金额
     */
    private BigDecimal calcIntegrationAmount(List<OmsOrderItem> orderItemList) {
        BigDecimal integrationAmount = new BigDecimal(0);
        for (OmsOrderItem orderItem : orderItemList) {
            if (orderItem.getIntegrationAmount() != null) {
                integrationAmount = integrationAmount.add(
                        orderItem.getIntegrationAmount().multiply(new BigDecimal(orderItem.getProductQuantity())));
            }
        }
        return integrationAmount;
    }

    /**
     * 计算订单优惠券金额
     */
    private BigDecimal calcCouponAmount(List<OmsOrderItem> orderItemList) {
        BigDecimal couponAmount = new BigDecimal(0);
        for (OmsOrderItem orderItem : orderItemList) {
            if (orderItem.getCouponAmount() != null) {
                couponAmount = couponAmount.add(
                        orderItem.getCouponAmount().multiply(new BigDecimal(orderItem.getProductQuantity())));
            }
        }
        return couponAmount;
    }

    /**
     * 计算订单活动优惠
     */
    private BigDecimal calcPromotionAmount(List<OmsOrderItem> orderItemList) {
        BigDecimal promotionAmount = new BigDecimal(0);
        for (OmsOrderItem orderItem : orderItemList) {
            if (orderItem.getPromotionAmount() != null) {
                promotionAmount = promotionAmount.add(
                        orderItem.getPromotionAmount().multiply(new BigDecimal(orderItem.getProductQuantity())));
            }
        }
        return promotionAmount;
    }

    /**
     * 获取可用积分抵扣金额
     *
     * @param useIntegration 使用的积分数量
     * @param totalAmount    订单总金额
     * @param currentMember  使用的用户
     * @param hasCoupon      是否已经使用优惠券
     */
    private BigDecimal getUseIntegrationAmount(Integer useIntegration, BigDecimal totalAmount, UmsMember currentMember, boolean hasCoupon) {
        BigDecimal zeroAmount = new BigDecimal(0);
        //判断用户是否有这么多积分
        if (useIntegration.compareTo(currentMember.getIntegration()) > 0) {
            return zeroAmount;
        }
        //根据积分使用规则判断是否可用
        //是否可与优惠券共用
        UmsIntegrationConsumeSetting integrationConsumeSetting = integrationConsumeSettingMapper.selectByPrimaryKey(1L);
        if (hasCoupon && integrationConsumeSetting.getCouponStatus().equals(0)) {
            //不可与优惠券共用
            return zeroAmount;
        }
        //是否达到最低使用积分门槛
        if (useIntegration.compareTo(integrationConsumeSetting.getUseUnit()) < 0) {
            return zeroAmount;
        }
        //是否超过订单抵用最高百分比
        BigDecimal integrationAmount = new BigDecimal(useIntegration).divide(
                new BigDecimal(integrationConsumeSetting.getUseUnit()), 2, RoundingMode.HALF_EVEN);
        BigDecimal maxPercent = new BigDecimal(integrationConsumeSetting.getMaxPercentPerOrder()).divide(
                new BigDecimal(100), 2, RoundingMode.HALF_EVEN);
        if (integrationAmount.compareTo(totalAmount.multiply(maxPercent)) > 0) {
            return zeroAmount;
        }
        return integrationAmount;
    }

    /**
     * 对优惠券优惠进行处理
     *
     * @param orderItemList       order_item列表
     * @param couponHistoryDetail 可用优惠券详情
     */
    private void handleCouponAmount(List<OmsOrderItem> orderItemList, BigDecimal couponAmount) {
        // SmsCoupon coupon = couponHistoryDetail.getCoupon();
        // if (coupon.getUseType().equals(0)) {
            //全场通用
            calcPerCouponAmount(orderItemList, couponAmount);
        // } else if (coupon.getUseType().equals(1)) {
        //     //指定分类
        //     List<OmsOrderItem> couponOrderItemList = getCouponOrderItemByRelation(couponHistoryDetail, orderItemList,
        //                                                                           0);
        //     calcPerCouponAmount(couponOrderItemList, coupon);
        // } else if (coupon.getUseType().equals(2)) {
        //     //指定商品
        //     List<OmsOrderItem> couponOrderItemList = getCouponOrderItemByRelation(couponHistoryDetail, orderItemList,
        //                                                                           1);
        //     calcPerCouponAmount(couponOrderItemList, coupon);
        // }
    }

    /**
     * 对每个下单商品进行优惠券金额分摊的计算
     *
     * @param orderItemList 可用优惠券的下单商品商品
     */
    private void calcPerCouponAmount(List<OmsOrderItem> orderItemList, BigDecimal coupon) {

        BigDecimal totalAmount = calcTotalAmount(orderItemList);
        for (OmsOrderItem orderItem : orderItemList) {
            //(商品价格/可用商品总价)*优惠券面额
            BigDecimal couponAmount = orderItem.getProductPrice()
                                               .divide(totalAmount, 2, BigDecimal.ROUND_DOWN)
                                               .multiply(coupon);
            orderItem.setCouponAmount(couponAmount);
            orderItem.setPrecisionAmount(BigDecimal.ZERO);

        }
        BigDecimal reduce = orderItemList.stream()
                                         .map(omsOrderItem -> omsOrderItem.getCouponAmount().multiply(BigDecimal.valueOf(omsOrderItem.getProductQuantity())))
                                         .reduce(BigDecimal.ZERO, BigDecimal::add);
        OmsOrderItem omsOrderItem = orderItemList.get(0);
        omsOrderItem.setPrecisionAmount(coupon.subtract(reduce));

    }

    /**
     * 获取与优惠券有关系的下单商品
     *
     * @param couponHistoryDetail 优惠券详情
     * @param orderItemList       下单商品
     * @param type                使用关系类型：0->相关分类；1->指定商品
     */
    private List<OmsOrderItem> getCouponOrderItemByRelation(SmsCouponHistoryDetail couponHistoryDetail, List<OmsOrderItem> orderItemList, int type) {
        List<OmsOrderItem> result = new ArrayList<>();
        if (type == 0) {
            List<Long> categoryIdList = new ArrayList<>();
            for (SmsCouponProductCategoryRelation productCategoryRelation : couponHistoryDetail.getCategoryRelationList()) {
                categoryIdList.add(productCategoryRelation.getProductCategoryId());
            }
            for (OmsOrderItem orderItem : orderItemList) {
                if (categoryIdList.contains(orderItem.getProductCategoryId())) {
                    result.add(orderItem);
                } else {
                    orderItem.setCouponAmount(new BigDecimal(0));
                }
            }
        } else if (type == 1) {
            List<Long> productIdList = new ArrayList<>();
            for (SmsCouponProductRelation productRelation : couponHistoryDetail.getProductRelationList()) {
                productIdList.add(productRelation.getProductId());
            }
            for (OmsOrderItem orderItem : orderItemList) {
                if (productIdList.contains(orderItem.getProductId())) {
                    result.add(orderItem);
                } else {
                    orderItem.setCouponAmount(new BigDecimal(0));
                }
            }
        }
        return result;
    }

    /**
     * 获取该用户可以使用的优惠券
     *
     * @param cartPromotionItemList 购物车优惠列表
     * @param couponId              使用优惠券id
     */
    private SmsCouponHistoryDetail getUseCoupon(List<CartPromotionItem> cartPromotionItemList, Long couponId) {
        List<SmsCouponHistoryDetail> couponHistoryDetailList = memberCouponService.listCart(cartPromotionItemList, 1);
        for (SmsCouponHistoryDetail couponHistoryDetail : couponHistoryDetailList) {
            if (couponHistoryDetail.getCoupon().getId().equals(couponId)) {
                return couponHistoryDetail;
            }
        }
        return null;
    }

    /**
     * 计算总金额
     */
    private BigDecimal calcTotalAmount(List<OmsOrderItem> orderItemList) {
        BigDecimal totalAmount = new BigDecimal("0");
        for (OmsOrderItem item : orderItemList) {
            totalAmount = totalAmount.add(item.getProductPrice().multiply(new BigDecimal(item.getProductQuantity())));
        }
        return totalAmount;
    }

    /**
     * 锁定下单商品的所有库存
     */
    private void lockSkuStock(List<CartPromotionItem> cartPromotionItemList) {
        for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
            if (cartPromotionItem.getProductSkuId() == null) {
                continue;
            }
            int i = skuStockMapper.lockStock(cartPromotionItem.getProductSkuId(), cartPromotionItem.getQuantity());
            if (i == 0) {
                Asserts.fail("库存不足");
            }
        }
    }

    /**
     * 锁定下单商品的所有库存
     */
    private void lockProductStock(List<CartPromotionItem> cartPromotionItemList) {
        Map<Long, List<CartPromotionItem>> collect = cartPromotionItemList.stream()
                                                                          .collect(Collectors.groupingBy(
                                                                                  CartPromotionItem::getProductId));
        for (Map.Entry<Long, List<CartPromotionItem>> entry : collect.entrySet()) {
            List<CartPromotionItem> value = entry.getValue();
            if (CollectionUtils.isEmpty(value)) {
                continue;
            }
            int sum = value.stream().mapToInt(CartPromotionItem::getQuantity).sum();
            if (sum > 0) {
                int i = pmsProductMapper.lockStock(entry.getKey(), sum);
                if (i == 0) {
                    Asserts.fail("库存不足");
                }
            }
        }
    }

    /**
     * 判断下单商品是否都有库存
     */
    private boolean hasStock(List<CartPromotionItem> cartPromotionItemList) {
        for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
            if (cartPromotionItem.getRealStock() == null || cartPromotionItem.getRealStock() <= 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * 计算购物车中商品的价格
     */
    private ConfirmOrderResult.CalcAmount calcCartAmount(List<CartPromotionItem> cartPromotionItemList) {
        ConfirmOrderResult.CalcAmount calcAmount = new ConfirmOrderResult.CalcAmount();
        calcAmount.setFreightAmount(new BigDecimal(0));
        BigDecimal totalAmount = new BigDecimal("0");
        BigDecimal promotionAmount = new BigDecimal("0");
        for (CartPromotionItem cartPromotionItem : cartPromotionItemList) {
            totalAmount = totalAmount.add(
                    cartPromotionItem.getPrice().multiply(new BigDecimal(cartPromotionItem.getQuantity())));
            promotionAmount = promotionAmount.add(
                    cartPromotionItem.getReduceAmount().multiply(new BigDecimal(cartPromotionItem.getQuantity())));
        }
        calcAmount.setTotalAmount(totalAmount);
        calcAmount.setPromotionAmount(promotionAmount);
        calcAmount.setPayAmount(totalAmount.subtract(promotionAmount));
        return calcAmount;
    }

}
