package com.hai.order.service.impl;

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.dao.HighChildOrderMapper;
import com.hai.dao.HighOrderMapper;
import com.hai.entity.*;
import com.hai.enum_type.DiscountUseScope;
import com.hai.enum_type.OrderStatusEnum;
import com.hai.order.model.CreateOrderChildModel;
import com.hai.order.model.CreateOrderModel;
import com.hai.order.service.*;
import com.hai.order.type.*;
import com.hai.order.utils.OrderUtil;
import com.hai.service.HighDiscountAgentCodeService;
import com.hai.service.HighDiscountUserRelService;
import com.hai.service.HighUserPayPasswordService;
import com.hai.service.HighUserService;
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.*;

/**
 * @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 HighUserService userService;

    @Resource
    private HighUserPayPasswordService userPayPasswordService;

    @Resource
    private OrderCreateHandleService orderCreateHandleService;

    @Resource
    private OrderCancelHandleService orderCancelHandleService;

    @Resource
    private OrderPaySuccessService paySuccessService;

    @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 = 10,
        rollbackFor = Exception.class)
    @Cached(cacheType = CacheType.BOTH, 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.getMemId());
            if (discountUserRel == null || discountUserRel.getStatus() != 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);
        }

        HighOrder order = new HighOrder();
        order.setOrderNo(createOrderModel.getOrderNo());
        order.setMemId(createOrderModel.getMemId());
        order.setMemName(createOrderModel.getMemName());
        order.setMemPhone(createOrderModel.getMemPhone());
        order.setPromoteCode(createOrderModel.getPromoteCode());
        order.setRemarks(createOrderModel.getRemarks());
        order.setOrderStatus(OrderStatus.STATUS1.getNumber());
        order.setWhetherCheck(false);
        order.setWhetherRebate(false);
        order.setExceptionStatus(false);
        order.setCreateTime(new Date());
        order.setPayGold(0);


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

            // 购买卡券
            if (child.getGoodsType().equals(OrderChildGoodsType.TYPE1.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE5.getNumber());
                childOrderList = orderCreateHandleService.couponHandle(discountUserRel, child);

            // 积分充值
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE2.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE4.getNumber());
                childOrderList.add(orderCreateHandleService.integralRecharge(child));
                
            // 加油订单
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE3.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE6.getNumber());
                childOrderList.add(orderCreateHandleService.oilHandle(order, discountUserRel, child));

            // 肯德基
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE4.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE2.getNumber());

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

            // 话费充值
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE6.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE7.getNumber());

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

            // 贵州汇联通工会卡充值
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE8.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE8.getNumber());
                orderCreateHandleService.hltUnionCardRecharge(child);
                
            // 星巴克
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE9.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE1.getNumber());
                
            // 第三方充值
            } else if (child.getGoodsType().equals(OrderChildGoodsType.TYPE10.getNumber())) {
                order.setProductType(OrderProductType.PRODUCT_TYPE3.getNumber());

            } 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()));
        order.setDeductionPrice(order.getTotalPrice().subtract(order.getPayablePrice()));
        order.setPayPrice(order.getPayablePrice());

        // 是否使用了优惠券
        if (discountUserRel != null) {
            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.type7.getType())) {
                if (!order.getProductType().equals(OrderProductType.PRODUCT_TYPE6.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.setDeductionPrice(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.setDeductionPrice(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.setDeductionPrice(order.getTotalPrice().subtract(payablePrice));
                order.setPayablePrice(payablePrice);
            }
        }

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

            // 积分金额等于应付金额
            if (goldPrice.compareTo(order.getPayablePrice()) == 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(), order.getPayGold(), 2, 2, order.getId(),
                        "抵扣积分订单：" + order.getOrderNo() + "，使用积分:" + order.getPayGold());

                order.setOrderStatus(OrderStatus.STATUS2.getNumber());
                order.setPayRealPrice(order.getPayPrice());
                order.setPayTime(new Date());
                for (HighChildOrder childOrder : order.getHighChildOrderList()) {
                    childOrder.setChildOrderStatus(OrderChildStatus.STATUS2.getNumber());
                }
            }
        }

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

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

            // 计算子订单退款积分
            if (order.getPayGold() > 0) {
                childOrder.setSurplusRefundIntegral(childOrder.getTotalActualPrice()
                        .divide(new BigDecimal(order.getPayGold().toString()), 4, BigDecimal.ROUND_DOWN)
                        .multiply(new BigDecimal("100")).setScale(2).multiply(new BigDecimal("10000")).intValue());
            } else {
                childOrder.setSurplusRefundIntegral(0);
            }
        }

        // 订单入库
        HighOrder orderData = insertOrderData(order);
        if (orderData.getOrderStatus().equals(OrderStatus.STATUS1.getNumber())) {
            // 10分钟后取消订单
            Message<HighOrder> rocketMsg = MessageBuilder.withPayload(order).build();
            rocketMQTemplate.syncSend("order-topic:cancel", rocketMsg, 1000,14);

        } else if (orderData.getOrderStatus().equals(OrderStatus.STATUS2.getNumber())) {
            // 异步处理业务
            asyncOrderPaySuccess(orderData);
        }
        return orderData;
    }

    @Override
    @Transactional(
            propagation= Propagation.REQUIRES_NEW,
            isolation = Isolation.READ_COMMITTED,
            timeout = 10,
            rollbackFor = Exception.class)
    public HighOrder cancelOrder(String orderNo,String remarks) {
        HighOrder order = getOrderDetailByNo(orderNo);
        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().intValue() > 0) {
            // 积分返回
            String remark = "订单" + order.getOrderNo() + "取消，退还积分：" +  order.getPayGold();
            userService.goldHandle(order.getMemId(), order.getPayGold(), 1, 3, order.getId() , remark);
        }

        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.TYPE7.getNumber())) {

            }
        }

        return updateOrderData(order);
    }

    @Override
    public HighOrder refundOrder(String orderNo, String remarks) {
        HighOrder order = getOrderDetailByNo(orderNo);
        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, "订单无法退款！");
        }

        return orderRefundService.createOrderRefund(order, remarks);
    }

    @Override
    public HighOrder refundChildOrder(String childOrderNo, String remarks) {
        return null;
    }

    @Override
    @Cached(cacheType = CacheType.BOTH,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 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 HighOrder orderPaySuccessBus(HighOrder order) {
        try {
            for (HighChildOrder childOrder : order.getHighChildOrderList()) {
                if (childOrder.getGoodsType().equals(OrderChildGoodsType.TYPE1.getNumber())) {
                    paySuccessService.couponHandle(order, childOrder);

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

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

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

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

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

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

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

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

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

                }
            }

            return order;

        } catch (Exception e) {
            order.setExceptionStatus(true);
            order.setExceptionContent(e.getMessage());
            updateOrderData(order);
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, e.getMessage());
        }
    }

    @Override
    public void asyncOrderPaySuccess(HighOrder order) {
        new Thread(() -> {
            orderPaySuccessBus(order);
        });
    }

    @Override
    public List<HighOrder> getOrderList(Map<String, Object> param) {
        return null;
    }
}
