package com.hai.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.CacheUpdate;
import com.alicp.jetcache.anno.Cached;
import com.hai.common.exception.ErrorCode;
import com.hai.common.exception.ErrorHelp;
import com.hai.common.exception.SysCode;
import com.hai.common.security.AESEncodeUtil;
import com.hai.common.utils.DateUtil;
import com.hai.config.ThirdProductConfig;
import com.hai.dao.HighChildOrderMapper;
import com.hai.dao.HighOrderMapper;
import com.hai.entity.*;
import com.hai.enum_type.DiscountUseScope;
import com.hai.goods.service.DeliveryAddressService;
import com.hai.goods.service.GoodsOrderExtService;
import com.hai.goods.service.GoodsRegionFreightService;
import com.hai.goods.service.GoodsSkuService;
import com.hai.order.model.CreateOrderChildModel;
import com.hai.order.model.CreateOrderModel;
import com.hai.order.model.RefundPriceModel;
import com.hai.order.model.combine.CombineOrderModel;
import com.hai.order.service.*;
import com.hai.order.topic.OrderTopic;
import com.hai.order.type.*;
import com.hai.order.utils.OrderUtil;
import com.hai.service.*;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @className: OrderServiceImpl
 * @author: HuRui
 * @date: 2022/8/18
 **/
@Service("newOrderService")
public class OrderServiceImpl implements OrderService {

    @Resource
    private HighOrderMapper orderMapper;

    @Resource
    private HighChildOrderMapper childOrderMapper;

    @Resource
    private OrderRefundService orderRefundService;

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Resource
    private HighDiscountUserRelService discountUserRelService;

    @Resource
    private HighDiscountAgentCodeService discountAgentCodeService;

    @Resource
    private BsDistributionUserRelService bsDistributionUserRelService;

    @Resource
    private HighUserService userService;

    @Resource
    private HighUserPayPasswordService userPayPasswordService;

    @Resource
    private OrderCreateHandleService orderCreateHandleService;

    @Resource
    private OrderCancelHandleService orderCancelHandleService;

    @Resource
    private OrderPayBeforeService orderPayBeforeService;
    @Resource
    private OrderPaySuccessService paySuccessService;

    @Resource
    private ThirdProductConfig thirdProductConfig;

    @Resource
    private HighDiscountPackageActualService discountPackageActualService;

    @Resource
    private DeliveryAddressService deliveryAddressService;

    @Resource
    private GoodsRegionFreightService goodsRegionFreightService;


    @Resource
    private GoodsOrderExtService goodsOrderExtService;




    @Override
    public HighOrder insertOrderData(HighOrder order) {
        orderMapper.insert(order);
        for (HighChildOrder childOrder : order.getHighChildOrderList()) {
            childOrder.setOrderId(order.getId());
            childOrderMapper.insert(childOrder);
        }
        return order;
    }

    @Override
    @CacheUpdate(name = "order:", key = "#order.orderNo", value = "#order")
    public HighOrder updateOrderData(HighOrder order) {
        orderMapper.updateByPrimaryKey(order);
        for (HighChildOrder childOrder : order.getHighChildOrderList()) {
            childOrderMapper.updateByPrimaryKey(childOrder);
        }
        return order;
    }

    @Override
    @Transactional(
        propagation= Propagation.REQUIRES_NEW,
        isolation = Isolation.READ_COMMITTED,
        timeout = 20,
        rollbackFor = Exception.class)
    @Cached(cacheType = CacheType.REMOTE, name="order:", key = "#createOrderModel.orderNo", expire = 3600*24*30)     // 缓存一个月
    public HighOrder createOrder(CreateOrderModel createOrderModel) throws Exception {

        HighDiscountUserRel discountUserRel = null;

        // 使用优惠券
        if (createOrderModel.getMemDiscountId() != null) {
            // 卡优惠券信息
            discountUserRel = discountUserRelService.getRelById(createOrderModel.getMemDiscountId());
            if (discountUserRel == null || discountUserRel.getStatus() != 1) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "优惠券不可用");
            }
            if (new Date().compareTo(discountUserRel.getUseEndTime()) >= 1) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "优惠券不可用");
            }
            discountUserRel.setUseTime(new Date()); // 使用时间
            discountUserRel.setStatus(2);  //状态  0:已过期  1：未使用  2：已使用
            discountUserRelService.updateDiscountUserRel(discountUserRel);

            HighDiscountAgentCode code = discountAgentCodeService.getCodeById(discountUserRel.getDiscountAgentCodeId());
            code.setStatus(3);
            discountAgentCodeService.updateCode(code);
        }

        // 查询推广员信息
        Map<String, Object> mapUser = new HashMap<>();
        mapUser.put("userId" , createOrderModel.getMemId());
        BsDistributionUserRel popularizeUser = bsDistributionUserRelService.findDistributionUserRel(mapUser);

        HighOrder order = new HighOrder();
        if (popularizeUser != null) {
            order.setPromoteCode(popularizeUser.getAgentId().toString());
        }

        order.setOrderNo(createOrderModel.getOrderNo());
        order.setMemId(createOrderModel.getMemId());
        order.setMemName(createOrderModel.getMemName());
        order.setMemPhone(createOrderModel.getMemPhone());
        order.setRemarks(createOrderModel.getRemarks());
        order.setOrderStatus(OrderStatus.STATUS1.getNumber());
        order.setWhetherCheck(false);
        order.setWhetherRebate(false);
        order.setProfitSharingStatus(false);
        order.setExceptionStatus(false);
        order.setCreateTime(new Date());
        order.setPayGold(createOrderModel.getPayGold()!=null?createOrderModel.getPayGold():0);
        order.setDeductionCouponPrice(new BigDecimal("0"));
        order.setDeductionProductPrice(new BigDecimal("0"));
        order.setCompanyId(createOrderModel.getCompanyId());


        /*********** 组装处理子订单 商品业务************/
        List<HighChildOrder> childOrderList = new ArrayList<>();
        for (CreateOrderChildModel child : createOrderModel.getChildOrderList()) {
            child.setMemId(order.getMemId());
            child.setMemName(order.getMemName());
            child.setMemPhone(order.getMemPhone());
            child.setOrderNo(order.getOrderNo());

            // 购买卡券
            if (child.getGoodsType().equals(OrderChildGoodsType.TYPE1.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE5.getNumber());
                // 创建购买卡券业务
                List<HighChildOrder> couponOrderList = orderCreateHandleService.couponHandle(discountUserRel, child);
                childOrderList = couponOrderList;
                for (HighChildOrder childOrder : couponOrderList) {
                    if (StringUtils.isBlank(order.getSearchTitle())) {
                        order.setTitle(childOrder.getGoodsName());
                    } else {
                        order.setTitle(order.getTitle() + "+" + childOrder.getGoodsName());
                    }
                }
            // 积分充值
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE2.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE4.getNumber());
                // 创建积分充值订单业务
                HighChildOrder oilOrder = orderCreateHandleService.integralRecharge(order , child);
                childOrderList.add(oilOrder);
                order.setTitle("积分充值");

            // 加油订单
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE3.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE6.getNumber());
                // 创建加油订单业务
                HighChildOrder oilOrder = orderCreateHandleService.oilHandle(order, discountUserRel, createOrderModel, child);
                childOrderList.add(oilOrder);
                order.setTitle(oilOrder.getGoodsName());

            // 肯德基
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE4.getNumber())) {

                /*********** 组装肯德基，星巴克，第三方会员充值 话费 请求数据************/
                JSONObject object = thirdProductConfig.assembleOrder(order , child);

                order.setProductType(OrderProductType.PRODUCT_TYPE2.getNumber());
                // 创建肯德基订单业务
                List<HighChildOrder> couponOrderList = orderCreateHandleService.thirdPartyOrder(order , object);
                childOrderList = couponOrderList;
                for (HighChildOrder childOrder : couponOrderList) {
                    if (order.getTitle() == null) {
                        order.setTitle(childOrder.getGoodsName());
                    } else {
                        order.setTitle(order.getTitle() + "+" + childOrder.getGoodsName());
                    }
                }

            // 电影票
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE5.getNumber())) {

            // 话费充值
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE6.getNumber())) {
                /*********** 组装肯德基，星巴克，第三方会员充值 话费 请求数据************/
                JSONObject object = thirdProductConfig.assembleOrder(order , child);

                HighChildOrder childOrder = orderCreateHandleService.mobileRecharge(order , object);
                childOrderList.add(childOrder);
                order.setTitle(childOrder.getGoodsName());
                order.setProductType(OrderProductType.PRODUCT_TYPE9.getNumber());

            // 优惠券包
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE7.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE7.getNumber());
                HighChildOrder childOrder = orderCreateHandleService.couponPackage(order , child);

                // 查询库存
                List<HighDiscountPackageActual> list = discountPackageActualService.getListByPackageId(childOrder.getGoodsId().intValue(), 1);
                if (list == null || list.size() == 0) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COUPON_STOCK_INSUFFICIENT, "");
                }
                list.get(0).setUserId(order.getMemId().intValue());
                list.get(0).setExt1(childOrder.getChildOrderNo());
                list.get(0).setStatus(2);  // 状态： 1: 待分配 2:预分配（售卖）3:已分配
                discountPackageActualService.updateHighDiscountPackageActual(list.get(0));

                childOrderList.add(childOrder);
                order.setTitle(childOrder.getGoodsName());

            // 贵州汇联通工会卡充值
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE8.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE8.getNumber());
                HighChildOrder childOrder = orderCreateHandleService.hltUnionCardRecharge(order , child);
                childOrderList.add(childOrder);
                order.setTitle(childOrder.getGoodsName());
                
            // 星巴克
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE9.getNumber())) {

                /*********** 组装肯德基，星巴克，第三方会员充值 话费 请求数据************/
                JSONObject object = thirdProductConfig.assembleOrder(order , child);

                order.setProductType(OrderProductType.PRODUCT_TYPE1.getNumber());
                // 创建星巴克订单业务
                List<HighChildOrder> couponOrderList = orderCreateHandleService.thirdPartyOrder(order, object);
                childOrderList = couponOrderList;
                for (HighChildOrder childOrder : couponOrderList) {
                    if (StringUtils.isBlank(order.getTitle())) {
                        order.setTitle(childOrder.getGoodsName());
                    } else {
                        order.setTitle(order.getTitle() + "+"+childOrder.getGoodsName());
                    }
                }
            // 第三方充值
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE10.getNumber())) {

                /*********** 组装肯德基，星巴克，第三方会员充值 话费 请求数据************/
                JSONObject object = thirdProductConfig.assembleOrder(order , child);

                order.setProductType(OrderProductType.PRODUCT_TYPE3.getNumber());
                // 创建第三方充值订单业务
                List<HighChildOrder> couponOrderList = orderCreateHandleService.thirdPartyOrder(order , object);
                childOrderList = couponOrderList;
                for (HighChildOrder childOrder : couponOrderList) {
                    if (StringUtils.isBlank(order.getTitle())) {
                        order.setTitle(childOrder.getGoodsName());
                    } else {
                        order.setTitle("+"+childOrder.getGoodsName());
                    }
                }
                order.setRemarks(object.getString("customerMobile"));
                // 实物商品
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE11.getNumber())) {

                HighChildOrder childOrder = orderCreateHandleService.goods(order , child);
                childOrderList.add(childOrder);
                order.setProductType(OrderProductType.PRODUCT_TYPE12.getNumber());
                order.setSecUserId(childOrder.getId());

                if (StringUtils.isBlank(order.getTitle())) {
                    order.setTitle(childOrder.getGoodsName());
                    order.setExt6(childOrder.getGoodsImg());
                } else {
                    order.setTitle(order.getTitle() + "+" +childOrder.getGoodsName());
                    order.setExt6(order.getExt6() + "," +childOrder.getGoodsImg());
                }

            } else {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知业务类型");
            }
        }
        order.setHighChildOrderList(childOrderList);
        /*********** 组装处理子订单 商品业务************/



        // 计算订单金额
        Map<String, Object> calculateOrderPrice = OrderUtil.calculateOrderPrice(order.getHighChildOrderList());

        order.setTotalPrice(new BigDecimal(calculateOrderPrice.get("totalPrice").toString()));
        order.setPayablePrice(new BigDecimal(calculateOrderPrice.get("payablePrice").toString()));



        // 是否使用了优惠券
        if (discountUserRel != null) {
            order.setMemDiscountId(discountUserRel.getId());
            order.setMemDiscountName(discountUserRel.getHighDiscount().getDiscountName());
            // 优惠券使用范围
            if (discountUserRel.getHighDiscount().getUseScope().equals(DiscountUseScope.type1.getType())) {
                // 暂无限制
            } else if (discountUserRel.getHighDiscount().getUseScope().equals(DiscountUseScope.type2.getType())) {
                if (!order.getProductType().equals(OrderProductType.PRODUCT_TYPE5.getNumber())) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "此优惠券只能购买卡券商品使用");
                }
            } else if (discountUserRel.getHighDiscount().getUseScope().equals(DiscountUseScope.type3.getType())) {
                if (!order.getProductType().equals(OrderProductType.PRODUCT_TYPE9.getNumber())) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "此优惠券只能充值话费中使用");
                }
            } else if (discountUserRel.getHighDiscount().getUseScope().equals(DiscountUseScope.type4.getType())) {
                if (!order.getProductType().equals(OrderProductType.PRODUCT_TYPE2.getNumber())) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "此优惠券只能肯德基中使用");
                }
            } else if (discountUserRel.getHighDiscount().getUseScope().equals(DiscountUseScope.type5.getType())) {
                if (!order.getProductType().equals(OrderProductType.PRODUCT_TYPE1.getNumber())) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "此优惠券只能星巴克中使用");
                }
            } else if (discountUserRel.getHighDiscount().getUseScope().equals(DiscountUseScope.type6.getType())) {
                if (!order.getProductType().equals(OrderProductType.PRODUCT_TYPE3.getNumber())) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "此优惠券只能第三方会员充值中使用");
                }
            } else if (discountUserRel.getHighDiscount().getUseScope().equals(DiscountUseScope.type7.getType())) {
                if (!order.getProductType().equals(OrderProductType.PRODUCT_TYPE6.getNumber())) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "此优惠券只能加油订单中使用");
                }
            } else if (discountUserRel.getHighDiscount().getUseScope().equals(DiscountUseScope.type9.getType())) {
                if (!order.getProductType().equals(OrderProductType.PRODUCT_TYPE12.getNumber())) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "此优惠券只能是实物订单中使用");
                }
            } else {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "暂时无法使用此优惠券");
            }

            // 卡卷类型  1：满减  2：抵扣   3：折扣
            if (discountUserRel.getHighDiscount().getDiscountType() == 1) {
                // 如果订单总额 小于 满减价格
                if (order.getTotalPrice().compareTo(discountUserRel.getHighDiscount().getDiscountCondition()) > 1) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.UN_MEMBER_ERROR, "订单未达到"+discountUserRel.getHighDiscount().getDiscountCondition()+"元,无法使用此优惠券");
                }
                // 订单总额 - 满减额度
                BigDecimal payablePrice = order.getTotalPrice().subtract(discountUserRel.getHighDiscount().getDiscountPrice());

                order.setDeductionCouponPrice(discountUserRel.getHighDiscount().getDiscountPrice());
                // 如果总额小于0
                if (payablePrice.compareTo(new BigDecimal("0")) < 0) {
                    order.setPayablePrice(new BigDecimal("0"));
                } else {
                    order.setPayablePrice(payablePrice);
                }
            }
            else if (discountUserRel.getHighDiscount().getDiscountType() == 2) {
                // 订单总额 - 满减额度
                BigDecimal payablePrice = order.getTotalPrice().subtract(discountUserRel.getHighDiscount().getDiscountPrice());
                order.setDeductionCouponPrice(discountUserRel.getHighDiscount().getDiscountPrice());

                // 如果总额小于0
                if (payablePrice.compareTo(new BigDecimal("0")) == -1) {
                    order.setPayablePrice(new BigDecimal("0"));
                } else {
                    order.setPayablePrice(payablePrice);
                }
            }
            else if (discountUserRel.getHighDiscount().getDiscountType() == 3) {
                // 折扣除100
                BigDecimal discountPrice = discountUserRel.getHighDiscount().getDiscountPrice();
                // 订单总额 * 折扣
                BigDecimal payablePrice = order.getTotalPrice().multiply(discountPrice).setScale(2, BigDecimal.ROUND_HALF_DOWN);
                order.setDeductionCouponPrice(order.getTotalPrice().subtract(payablePrice));
                order.setPayablePrice(payablePrice);
            }
        }

        order.setDeductionProductPrice(new BigDecimal(calculateOrderPrice.get("deductionPrice").toString()));
        order.setTotalDeductionPrice(order.getDeductionCouponPrice().add(order.getDeductionProductPrice()));
        order.setPayPrice(order.getPayablePrice());


        if (order.getProductType().equals(OrderProductType.PRODUCT_TYPE12.getNumber())) {

            GoodsDeliveryAddress deliveryAddress = deliveryAddressService.findDeliveryAddressById(createOrderModel.getDeliveryAddressId());

            // 生成实物专属订单实体
            GoodsOrder goodsOrder = new GoodsOrder();

            JSONObject object  = goodsRegionFreightService.getRegionFreight(deliveryAddress.getRegionId());

            if (object.getBigDecimal("freePostPrice").compareTo(order.getPayablePrice())  > 0) {
                order.setTotalPrice(order.getTotalPrice().add(object.getBigDecimal("freightPrice")));
                order.setPayablePrice(order.getPayablePrice().add(object.getBigDecimal("freightPrice")));
                order.setPayPrice(order.getPayPrice().add(object.getBigDecimal("freightPrice")));
                goodsOrder.setFreightPrice(object.getBigDecimal("freightPrice"));
            }

            goodsOrder.setStatus("8");
            goodsOrder.setOpName("系统生成");
            goodsOrder.setUpdateTime(new Date());
            goodsOrder.setCreateTime(new Date());
            goodsOrder.setDeliveryAddressId(createOrderModel.getDeliveryAddressId());
            goodsOrder.setOrderNo(order.getOrderNo());
            goodsOrder.setDeliveryAddress(deliveryAddress.getRegionName() + deliveryAddress.getAddress());

            goodsOrderExtService.insertGoodsOrder(goodsOrder);
        }

        // 积分抵扣
        if (createOrderModel.getPayGold() != null && createOrderModel.getPayGold() > 0) {
            // 查询用户
            HighUser user = userService.findByUserId(order.getMemId());
            if (user == null) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到用户信息");
            }
            if (createOrderModel.getPayGold().compareTo(user.getGold()) > 0) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "抵扣积分大于用户拥有积分");
            }
            // 积分转换成金额
            BigDecimal goldPrice = new BigDecimal(createOrderModel.getPayGold().toString()).divide(new BigDecimal(100));
            // 积分金额大于应付金额
            if (goldPrice.compareTo(order.getPayablePrice()) > 0) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "支付的积分金额大于支付金额");
            }
            // 支付金额 减去 积分抵扣金额 = 应付金额
            order.setPayPrice(order.getPayablePrice().subtract(goldPrice));

            // 积分金额等于应付金额
            if (order.getPayPrice().compareTo(new BigDecimal("0")) == 0) {
                if (StringUtils.isBlank(createOrderModel.getPayPwd())) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.NOT_ENTER_USER_PAY_PWD, "");
                }
                // 查询用户密码
                HighUserPayPassword userPayPwd = userPayPasswordService.getDetailByUser(order.getMemId());
                if (userPayPwd == null) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.NOT_SET_USER_PAY_PWD, "");
                }
                // 校验支付密码是否正确
                if (!userPayPwd.getPassword().equals(AESEncodeUtil.aesEncrypt(createOrderModel.getPayPwd()))) {
                    throw ErrorHelp.genException(SysCode.System, ErrorCode.USER_PAY_PWD_ERROR, "");
                }
                // 扣除用户积分
                userService.goldHandle(order.getMemId(), createOrderModel.getPayGold(), 2, 2, order.getId(),
                        "积分抵扣金额，交易订单：" + order.getOrderNo() + "，使用积分:" + order.getPayGold() , order.getOrderNo());

                order.setOrderStatus(OrderStatus.STATUS2.getNumber());
                order.setPayRealPrice(order.getPayPrice());
                order.setPayTime(new Date());
                order.setPayGold(createOrderModel.getPayGold());
                for (HighChildOrder childOrder : order.getHighChildOrderList()) {
                    childOrder.setChildOrderStatus(OrderChildStatus.STATUS2.getNumber());
                }
            } else {
                // 扣除用户积分
                userService.goldHandle(order.getMemId(), createOrderModel.getPayGold(), 2, 2, order.getId(),
                        "积分抵扣金额，交易订单：" + order.getOrderNo() + "，使用积分:" + order.getPayGold() , order.getOrderNo());
            }
        }


        order.setSurplusRefundPrice(new BigDecimal("0") );
        order.setSurplusRefundIntegral(0);
        order.setSearchTitle(order.getOrderNo());

        // 订单入库前处理
        for (HighChildOrder childOrder : order.getHighChildOrderList()) {
            childOrder.setOrderNo(order.getOrderNo());
            childOrder.setSurplusRefundNum(childOrder.getSaleCount()) ;

            // 计算 子订单 在交易订单金额中的占比
            BigDecimal ratio = childOrder.getGoodsPrice().divide(order.getTotalPrice(), 2, BigDecimal.ROUND_DOWN).setScale(2);

            // 计算子订单退款金额。
            if (order.getPayPrice().compareTo(new BigDecimal("0")) == 1) {
                childOrder.setSurplusRefundPrice(order.getPayPrice().multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN));
            } else {
                childOrder.setSurplusRefundPrice(new BigDecimal("0"));
            }

            // 计算子订单退款积分
            if (order.getPayGold() > 0) {
                childOrder.setSurplusRefundIntegral(new BigDecimal(order.getPayGold().toString()).multiply(ratio).setScale(2).intValue());
            } else {
                childOrder.setSurplusRefundIntegral(0);
            }
            order.setSurplusRefundPrice(order.getSurplusRefundPrice().add(childOrder.getSurplusRefundPrice()));
            order.setSurplusRefundIntegral(order.getSurplusRefundIntegral() + childOrder.getSurplusRefundIntegral());
            order.setSearchTitle(order.getSearchTitle()+childOrder.getGoodsName());
        }

        // 订单入库
        HighOrder orderData = insertOrderData(order);

        if (orderData.getOrderStatus().equals(OrderStatus.STATUS1.getNumber())) {
            // 10分钟内未支付，自动取消订单
            Message<HighOrder> rocketMsg = MessageBuilder.withPayload(order).build();
            rocketMQTemplate.syncSend(OrderTopic.ORDER_TOPIC_CANCEL.getTopic(), rocketMsg,1000,14);

        } else if (orderData.getOrderStatus().equals(OrderStatus.STATUS2.getNumber())) {
            // 支付校验
            orderPayBeforeService.payOrderCheck(order);
            // 处理业务
            return paySuccessService.orderPaySuccessHandle(orderData.getOrderNo(), OrderPayType.PAY_TYPE3, null, new BigDecimal("0"), null);
        }
        return orderData;
    }


    @Override
    public JSONObject createOrderCombine(CombineOrderModel combineOrderModel) throws Exception {
        return null;
    }

    @Override
    @Transactional(
            propagation= Propagation.REQUIRES_NEW,
            isolation = Isolation.READ_COMMITTED,
            timeout = 10,
            rollbackFor = Exception.class)
    @CacheUpdate(name = "order:", key = "#order.orderNo", value = "#order")
    public HighOrder cancelOrder(HighOrder order,String remarks) {
        if (!order.getOrderStatus().equals(OrderStatus.STATUS1.getNumber())) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "订单状态错误");
        }
        order.setOrderStatus(OrderStatus.STATUS5.getNumber());
        order.setCancelTime(new Date());
        order.setRemarks(remarks);

        // 使用了优惠券
        if (order.getMemDiscountId() != null) {
            HighDiscountUserRel rel = discountUserRelService.getRelById(order.getMemDiscountId());
            if (rel != null) {
                rel.setStatus(1);  // 状态  0:已过期  1：未使用  2：已使用
                rel.setUseTime(null);
                discountUserRelService.updateDiscountUserRel(rel);

                HighDiscountAgentCode code = discountAgentCodeService.getCodeById(rel.getDiscountAgentCodeId());
                code.setStatus(2);
                discountAgentCodeService.updateCode(code);
            }
        }

        // 使用了积分抵扣
        if (order.getPayGold() != null && order.getPayGold() > 0) {
            // 积分返回
            String remark = "订单" + order.getOrderNo() + "取消，退还积分：" +  order.getPayGold();
            userService.goldHandle(order.getMemId(), order.getPayGold(), 1, 3, order.getId() , remark , order.getOrderNo());
        }

        for (HighChildOrder childOrder : order.getHighChildOrderList()) {
            childOrder.setChildOrderStatus(OrderChildStatus.STATUS5.getNumber());
            childOrder.setCancelTime(new Date());

            if (childOrder.getGoodsType().equals(OrderChildGoodsType.TYPE1.getNumber())) {
                orderCancelHandleService.couponHandle(childOrder);

            } else if (childOrder.getGoodsType().equals(OrderChildGoodsType.TYPE3.getNumber())) {
                orderCancelHandleService.oilHandle(childOrder);

            } else if (childOrder.getGoodsType().equals(OrderChildGoodsType.TYPE11.getNumber())) {
                orderCancelHandleService.goodsHandle(childOrder);

            } else if (childOrder.getGoodsType().equals(OrderChildGoodsType.TYPE7.getNumber())) {

            }
        }

        return updateOrderData(order);
    }

    @Override
    @Transactional(
            propagation= Propagation.REQUIRES_NEW,
            isolation = Isolation.READ_COMMITTED,
            timeout = 25,
            rollbackFor = Exception.class)
    @CacheUpdate(name = "order:", key = "#order.orderNo", value = "#order")
    public HighOrder refundOrder(HighOrder order, String remarks, OrderRefundOpUserType opUserType, Long opUserId, String opUserName) {

        try {

            if (!order.getOrderStatus().equals(OrderStatus.STATUS2.getNumber())
                    && !order.getOrderStatus().equals(OrderStatus.STATUS3.getNumber())) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "订单状态错误");
            }
            // 订单是否异常，订单没异常则需要校验产品业务是否支持退款
            if (order.getExceptionStatus().equals(false)
                    // 产品业务是否支付退款
                    && (order.getProductType().equals(OrderProductType.PRODUCT_TYPE3.getNumber())
                    || order.getProductType().equals(OrderProductType.PRODUCT_TYPE4.getNumber())
                    || order.getProductType().equals(OrderProductType.PRODUCT_TYPE5.getNumber()))
            ) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "订单无法退款！");
            }

            // 退款订单号
            String refundOrderNo = OrderUtil.generateRefundOrderNo();

            // 创建退款
            order = orderRefundService.createOrderRefund(refundOrderNo, order, remarks, opUserType, opUserId, opUserName);

            for (HighChildOrder childOrder : order.getHighChildOrderList()) {
                if (childOrder.getGiveawayType() == false) {
                    childOrder.setRefundRemarks(remarks);
                    childOrder.setRefundTime(new Date());
                    childOrder.setChildOrderStatus(OrderChildStatus.STATUS4.getNumber());
                }

            }

            order.setSurplusRefundIntegral(0);
            order.setSurplusRefundPrice(new BigDecimal("0"));
            order.setRefundTime(new Date());
            order.setOrderStatus(OrderStatus.STATUS4.getNumber());

            //  退回金额，原路返回
            RefundPriceModel refundPrice = orderRefundService.refundPrice(refundOrderNo
                    , order
                    , OrderPayType.getDataByType(order.getPayType())
                    , order.getPayRealPrice()
                    , order.getPayGold());
            if (!refundPrice.getRefundSuccess()) {
                throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败，请稍后重试");
            }

            List<HighOrderRefund> refundList = orderRefundService.getRefundByRefundNo(refundOrderNo);
            for (HighOrderRefund orderRefund : refundList) {
                orderRefund.setRefundStatus(OrderRefundStatus.STATUS2.getNumber());
                orderRefund.setRefundTime(new Date());
                orderRefund.setThirdPartyRefundOrderNo(refundPrice.getThirdPartyRefundOrderNo());
                orderRefundService.update(orderRefund);

                rocketMQTemplate.syncSend(OrderTopic.ORDER_TOPIC_REFUND_SUCCESS.getTopic(), orderRefund);
            }
            return updateOrderData(order);
        } catch (Exception e) {
            return null;
        }

    }

    @Override
    @Transactional(
            propagation= Propagation.REQUIRES_NEW,
            isolation = Isolation.READ_COMMITTED,
            timeout = 10,
            rollbackFor = Exception.class)
    @CacheUpdate(name = "order:", key = "#order.orderNo", value = "#order")
    public HighOrder refundChildOrder(HighOrder order, String childOrderNo, Integer refundGoodsNum, String remarks, OrderRefundOpUserType opUserType, Long opUserId, String opUserName) throws Exception {
        List<HighChildOrder> collect = order.getHighChildOrderList().stream().filter(o -> o.getChildOrderNo().equals(childOrderNo)).collect(Collectors.toList());
        if (collect == null || collect.size() == 0) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未找到订单");
        }
        HighChildOrder orderChild = collect.get(0);

        // 创建退款记录
        HighOrderRefund orderRefund = orderRefundService.createOrderChildRefund(orderChild, OrderUtil.generateRefundOrderNo(), refundGoodsNum, remarks, opUserType, opUserId, opUserName);

        orderChild.setSurplusRefundNum(orderChild.getSurplusRefundNum() - orderRefund.getRefundGoodsNum());
        orderChild.setSurplusRefundPrice(orderChild.getSurplusRefundPrice().subtract(orderRefund.getRefundPrice()));
        orderChild.setSurplusRefundIntegral(orderChild.getSurplusRefundIntegral() - orderRefund.getRefundIntegral());
        if (orderChild.getSurplusRefundNum() == 0) {
            orderChild.setChildOrderStatus(OrderChildStatus.STATUS4.getNumber());
        }

        //  退回金额，原路返回
        RefundPriceModel refundPrice = orderRefundService.refundPrice(orderRefund.getRefundOrderNo()
                , order
                , OrderPayType.getDataByType(order.getPayType())
                , orderRefund.getRefundPrice()
                , orderRefund.getRefundIntegral());
        if (refundPrice.getRefundSuccess() == false) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "退款失败，请稍后重试");
        }

        childOrderMapper.updateByPrimaryKey(orderChild);

        orderRefund.setRefundTime(new Date());
        orderRefund.setRefundStatus(OrderRefundStatus.STATUS2.getNumber());
        orderRefundService.update(orderRefund);


        // 购买的订单列表
        List<HighChildOrder> buyChildOrderList = order.getHighChildOrderList()
                                            .stream().filter(o -> o.getGiveawayType().equals(false))
                                            .collect(Collectors.toList());
        // 已退款的订单列表
        List<HighChildOrder> refundList = buyChildOrderList.stream()
                .filter(o -> o.getChildOrderStatus().equals(OrderChildStatus.STATUS4.getNumber()))
                .collect(Collectors.toList());

        Integer surplusRefundIntegral = 0;
        BigDecimal surplusRefundPrice = new BigDecimal("0");

        for (HighChildOrder childOrder : order.getHighChildOrderList()) {
            surplusRefundIntegral = surplusRefundIntegral + childOrder.getSurplusRefundIntegral();
            surplusRefundPrice = surplusRefundPrice.add(childOrder.getSurplusRefundPrice());
        }

        order.setSurplusRefundIntegral(surplusRefundIntegral);
        order.setSurplusRefundPrice(surplusRefundPrice);
        // 校验购买的订单是否都已退款
        if (refundList.size() >= buyChildOrderList.size()) {
            order.setRefundTime(new Date());
            order.setOrderStatus(OrderStatus.STATUS4.getNumber());
        }
        rocketMQTemplate.syncSend(OrderTopic.ORDER_TOPIC_REFUND_SUCCESS.getTopic(), orderRefund);
        return updateOrderData(order);
    }

    @Override
    @Cached(cacheType = CacheType.REMOTE,name="order:", key = "#orderNo",expire = 3600*24*30)
    public HighOrder getOrderDetailByNo(String orderNo) {
        HighOrderExample orderExample = new HighOrderExample();
        orderExample.createCriteria().andOrderNoEqualTo(orderNo);
        List<HighOrder> orderList = orderMapper.selectByExample(orderExample);
        if (orderList.size() == 0) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的订单号");
        }
        HighOrder order = orderList.get(0);

        // 子订单
        HighChildOrderExample childOrderExample = new HighChildOrderExample();
        childOrderExample.createCriteria().andOrderIdEqualTo(order.getId());
        order.setHighChildOrderList(childOrderMapper.selectByExample(childOrderExample));
        return order;
    }

    @Override
    public HighOrder getOrderDetail(String orderNo) {
        HighOrderExample orderExample = new HighOrderExample();
        orderExample.createCriteria().andOrderNoEqualTo(orderNo);
        List<HighOrder> orderList = orderMapper.selectByExample(orderExample);
        if (orderList.size() == 0) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的订单号");
        }

        return orderList.get(0);
    }

    @Override
    public HighChildOrder getChildOrderByNo(String childOrderNo) {
        HighChildOrderExample childOrderExample = new HighChildOrderExample();
        childOrderExample.createCriteria().andChildOrderNoEqualTo(childOrderNo);
        List<HighChildOrder> list = childOrderMapper.selectByExample(childOrderExample);
        if (list.size() == 0) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的子订单号");
        }
        return list.get(0);
    }

    @Override
    public List<HighOrder> getOrderList(Map<String, Object> param) {
        HighOrderExample example = new HighOrderExample();
        HighOrderExample.Criteria criteria = example.createCriteria();

        if (MapUtils.getLong(param, "userId") != null) {
            criteria.andMemIdEqualTo(MapUtils.getLong(param, "userId"));
        }

        if (MapUtils.getBoolean(param, "exceptionStatus") != null) {
            criteria.andExceptionStatusEqualTo(MapUtils.getBoolean(param, "exceptionStatus"));
        }

        if (MapUtils.getLong(param, "companyId") != null) {
            criteria.andCompanyIdEqualTo(MapUtils.getLong(param, "companyId"));
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "title"))) {
            criteria.andTitleLike("%" + MapUtils.getString(param, "title") + "%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "searchTitle"))) {
            criteria.andSearchTitleLike("%" + MapUtils.getString(param, "searchTitle") + "%");
        }

        if (StringUtils.isNotBlank(MapUtils.getString(param, "orderNo"))) {
            criteria.andOrderNoLike("%" + MapUtils.getString(param, "orderNo") + "%");
        }

        if (MapUtils.getInteger(param, "productType") != null) {
            criteria.andProductTypeEqualTo(MapUtils.getInteger(param, "productType"));
        }
        if (MapUtils.getInteger(param, "payType") != null) {
            criteria.andPayTypeEqualTo(MapUtils.getInteger(param, "payType"));
        }
        if (StringUtils.isNotBlank(MapUtils.getString(param, "memCardNo"))) {
            criteria.andMemCardNoLike("%" + MapUtils.getString(param, "memCardNo") + "%");
        }
        if (StringUtils.isNotBlank(MapUtils.getString(param, "memPhone"))) {
            criteria.andMemPhoneLike("%" + MapUtils.getString(param, "memPhone") + "%");
        }
        if (StringUtils.isNotBlank(MapUtils.getString(param, "promoteCode"))) {
            criteria.andPromoteCodeEqualTo(MapUtils.getString(param, "promoteCode"));
        }

        if (MapUtils.getInteger(param, "orderStatus") != null) {
            criteria.andOrderStatusEqualTo(MapUtils.getInteger(param, "orderStatus"));
        }
        if (MapUtils.getLong(param, "createTimeS") != null) {
            criteria.andCreateTimeGreaterThanOrEqualTo(new Date(MapUtils.getLong(param, "createTimeS")));
        }
        if (MapUtils.getLong(param, "createTimeE") != null) {
            criteria.andCreateTimeLessThan(new Date(MapUtils.getLong(param, "createTimeE")));
        }

        if (MapUtils.getLong(param, "payTimeS") != null) {
            criteria.andPayTimeGreaterThanOrEqualTo(new Date(MapUtils.getLong(param, "payTimeS")));
        }
        if (MapUtils.getLong(param, "payTimeE") != null) {
            criteria.andPayTimeLessThan(new Date(MapUtils.getLong(param, "payTimeE")));
        }

        if (MapUtils.getLong(param, "finishTimeS") != null) {
            criteria.andFinishTimeGreaterThanOrEqualTo(new Date(MapUtils.getLong(param, "finishTimeS")));
        }
        if (MapUtils.getLong(param, "finishTimeE") != null) {
            criteria.andFinishTimeLessThan(new Date(MapUtils.getLong(param, "finishTimeE")));
        }

        if (MapUtils.getLong(param, "refundTimeS") != null) {
            criteria.andRefundTimeGreaterThanOrEqualTo(new Date(MapUtils.getLong(param, "refundTimeS")));
        }
        if (MapUtils.getLong(param, "refundTimeE") != null) {
            criteria.andRefundTimeLessThan(new Date(MapUtils.getLong(param, "refundTimeE")));
        }


        example.setOrderByClause("create_time desc");
        return orderMapper.selectByExample(example);
    }

    @Override
    public void orderCheck(String orderNo) {
        HighOrder highOrder = getOrderDetailByNo(orderNo);

        highOrder.setWhetherCheck(true);

        if  (highOrder.getOrderStatus() == 3) {
            orderMapper.updateByPrimaryKey(highOrder);
        }
    }

    @Override
    public List<HighOrder> phoneErrorOrder() {
        return orderMapper.phoneErrorOrder();
    }

    @Override
    public List<HighChildOrder> getChildOrderList(Map<String, Object> param) {

        HighChildOrderExample example = new HighChildOrderExample();
        HighChildOrderExample.Criteria criteria = example.createCriteria();

        if (MapUtils.getString(param, "orderNo") != null) {
            criteria.andOrderNoEqualTo(MapUtils.getString(param, "orderNo"));
        }

        if (MapUtils.getString(param, "childOrderNo") != null) {
            criteria.andChildOrderNoEqualTo(MapUtils.getString(param, "childOrderNo"));
        }

        if (MapUtils.getString(param, "memPhone") != null) {
            criteria.andMemPhoneEqualTo(MapUtils.getString(param, "memPhone"));
        }
        if (MapUtils.getInteger(param, "status") != null) {
            criteria.andChildOrderStatusEqualTo(MapUtils.getInteger(param, "status"));
        }
        if (MapUtils.getLong(param, "createTimeS") != null) {
            criteria.andCreateTimeGreaterThanOrEqualTo(new Date(MapUtils.getLong(param, "createTimeS")));
        }
        if (MapUtils.getLong(param, "createTimeE") != null) {
            criteria.andCreateTimeLessThan(new Date(MapUtils.getLong(param, "createTimeE")));
        }
        if (MapUtils.getLong(param, "secUserId") != null) {
            criteria.andSecUserIdEqualTo(MapUtils.getLong(param, "secUserId"));
        }
        example.setOrderByClause("create_time desc");


        return childOrderMapper.selectByExample(example);
    }
}
