package com.xingxi.mq.consumer.order;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryV3Result;
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.xingxi.business.Order.domain.Order;
import com.xingxi.business.Order.domain.OrderDetail;
import com.xingxi.business.Order.service.IOrderDetailService;
import com.xingxi.business.Order.service.IOrderService;
import com.xingxi.business.PaymentInfo.domain.PaymentInfo;
import com.xingxi.business.PaymentInfo.service.IPaymentInfoService;
import com.xingxi.business.ProdInventory.domain.ProdInventory;
import com.xingxi.business.ProdInventory.domain.ProdInventoryBill;
import com.xingxi.business.ProdInventory.mapper.ProdInventoryBillMapper;
import com.xingxi.business.ProdInventory.mapper.ProdInventoryMapper;
import com.xingxi.business.RefundInfo.domain.RefundInfo;
import com.xingxi.business.RefundInfo.service.impl.RefundInfoServiceImpl;
import com.xingxi.common.annotation.Excel;
import com.xingxi.common.enums.*;
import com.xingxi.common.exception.BusinessException;
import com.xingxi.common.mq.bo.order.OrderBO;
import com.xingxi.common.mq.constant.OrderMqKey;
import com.xingxi.common.mq.core.AbstractRabbitConsumer;
import com.google.common.collect.Lists;
import com.rabbitmq.client.Channel;
import com.xingxi.common.utils.DateUtils;
import com.xingxi.mq.server.order.mapper.MqProdInventoryMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Slf4j
@Component
public class OrderCloseConsumer extends AbstractRabbitConsumer {

    @Resource
    private IOrderService orderService;

    @Resource
    private IOrderDetailService orderDetailService;

    @Resource
    private IPaymentInfoService paymentInfoService;

    @Autowired
    private ProdInventoryBillMapper prodInventoryBillMapper;
    @Autowired
    private ProdInventoryMapper prodInventoryMapper;
    @Autowired
    private MqProdInventoryMapper mqProdInventoryMapper;



    @Autowired
    private WxPayService wxPayService;
    private WxPayConfig config;
    @Autowired
    private RefundInfoServiceImpl refundInfoServiceImpl;

//    @Value("${wx.pay.refundcallbackUrl}")
//    private String notifyUrl;

    @Bean(OrderMqKey.EDIT_QUEUE_DELAY_FOR_UNPAID)
    @Override
    protected List<Binding> getBindingList() {
        long xmTtl = 15 * 60 * 1000;
        return Lists.newArrayList(
                this.bindDelay(OrderMqKey.EDIT_EXCHANGE_DELAY,
                        OrderMqKey.EDIT_QUEUE_DELAY_FOR_UNPAID,
                        OrderMqKey.EDIT_ROUTE_DELAY_FOR_CREATED,
                        xmTtl));
    }

    @RabbitListener(queues = OrderMqKey.EDIT_QUEUE_DELAY_FOR_UNPAID)
    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        this.convertMessage(message, channel);
    }

    @Override
    public boolean execute(String body, Channel channel, Message message) throws Exception {
        log.info("订单关闭MQ,处理推送的订单数据【{}】.", body);

        OrderBO orderBO = JSON.parseObject(body, OrderBO.class);

        Date nowDate = DateUtils.getNowDate();
        String opName = "订单关闭MQ";

        if(orderBO == null || orderBO.getOrderId() == null || orderBO.getOrderId() == 0L) {
            return true;
        }
        // 如果没有支付成功就取消
        Order orgOrder = orderService.selectOrderByOrderId(orderBO.getOrderId());
        if(orgOrder == null) {
            log.info("订单关闭MQ,订单【{}】的信息不存在,不做处理.", orderBO.getOrderNo());
            return true;
        }
        if(!EOrderStatus.ORDERED.getVal().equals(orgOrder.getOrderStatus())) {
            log.info("订单关闭MQ,订单【{}】的订单状态为【{}】,非【{}】不做处理.", orgOrder.getOrderNo(), orgOrder.getOrderStatus(), EOrderStatus.ORDERED.getDesc());
            return true;
        }

        // 支付信息
        PaymentInfo spi = new PaymentInfo();
        spi.setOrderId(orgOrder.getOrderId());
        spi.setDelFlag(EDelFlag.NO.getVal());

        List<PaymentInfo> paymentInfoList = paymentInfoService.selectPaymentInfoList(spi);
        PaymentInfo pi = null;
        if(CollectionUtils.isNotEmpty(paymentInfoList)){
//            config = wxPayService.getConfig();

            pi = paymentInfoList.get(0);
            // 查询是否支付成功 TODO
            WxPayOrderQueryV3Request wxQryRequest = new WxPayOrderQueryV3Request();
            wxQryRequest.setOutTradeNo(orgOrder.getOrderNo());
//            wxrequest.setMchid(config.getMchId());

            WxPayOrderQueryV3Result rtn = wxPayService.queryOrderV3(wxQryRequest);

            if (ETradeState.SUCCESS.getVal().equals(rtn.getTradeState())) {

                // 如果支付成功并且微信支付没有回调成功就在这里退款 TODO
                String outRefundNo = "REFUND" + orgOrder.getOrderNo();
                WxPayRefundV3Request wxRefundRequest = new WxPayRefundV3Request();
                wxRefundRequest.setOutTradeNo(orgOrder.getOrderNo());
                wxRefundRequest.setOutRefundNo(outRefundNo);
                wxRefundRequest.setReason(orderBO.getOrderNo() + "退款");

                WxPayRefundV3Request.Amount refundAmount = new WxPayRefundV3Request.Amount();
                refundAmount.setRefund(orgOrder.getPayAmount().intValue()); // 分
                refundAmount.setTotal(orgOrder.getPayAmount().intValue()); // 分
                refundAmount.setCurrency("CNY");

                wxRefundRequest.setAmount(refundAmount);
                WxPayRefundV3Result refundV3Result = wxPayService.refundV3(wxRefundRequest);

                // TODO 增加退款表，保存退款信息
                RefundInfo refundInfo = new RefundInfo();
                refundInfo.setTransactionId(refundV3Result.getTransactionId());
                refundInfo.setOutTradeNo(orgOrder.getOrderNo());
                refundInfo.setOutRefundNo(outRefundNo);
                refundInfo.setReason(orderBO.getOrderNo() + "退款");
//                refundInfo.setNotifyUrl(notifyUrl);
                refundInfo.setAmountRefund(new BigDecimal(refundV3Result.getAmount().getRefund()));
                refundInfo.setAmountTotal(new BigDecimal(refundV3Result.getAmount().getTotal()));
                refundInfo.setRefundId(refundV3Result.getRefundId());

                refundInfo.setChannel(refundV3Result.getChannel());
                refundInfo.setUserReceivedAccount(refundV3Result.getUserReceivedAccount());
                refundInfo.setSuccessTime(refundV3Result.getSuccessTime());
                refundInfo.setRefundTime(nowDate.toString());
                refundInfo.setStatus(refundV3Result.getStatus());
                refundInfo.setFundsAccount(refundV3Result.getFundsAccount());
                refundInfo.setPayerTotal(new BigDecimal(refundV3Result.getAmount().getPayerTotal()));
                refundInfo.setPayerRefund(new BigDecimal(refundV3Result.getAmount().getPayerRefund()));
                refundInfo.setSettlementRefund(new BigDecimal(refundV3Result.getAmount().getSettlementRefund()));
                refundInfo.setSettlementTotal(new BigDecimal(refundV3Result.getAmount().getSettlementTotal()));
                refundInfo.setDiscountRefund(new BigDecimal(refundV3Result.getAmount().getDiscountRefund()));

                refundInfoServiceImpl.insertRefundInfo(refundInfo);

            }

            return true;
        }

        // 取消主订单
        Order order = new Order();
        order.setOrderId(orgOrder.getOrderId());
        order.setOrderStatus(EOrderStatus.CANCELLED.getVal());
        order.setCancelTime(nowDate);
        order.setUpdateUser(opName);
        order.setUpdateTime(nowDate);
        orderService.updateOrder(order);

        // 取消子订单
        OrderDetail sod = new OrderDetail();
        sod.setOrderId(order.getOrderId());
        List<OrderDetail> orderDetails = orderDetailService.selectOrderDetailList(sod);
        for (OrderDetail od : orderDetails) {

            //将订单明细设为已取消
            OrderDetail updateDetail = new OrderDetail();
            updateDetail.setOrderDetailId(od.getOrderDetailId());
            updateDetail.setOrderDetailStatus(EOrderDetailStatus.CANCELLED.getVal());
            updateDetail.setUpdateUser(opName);
            updateDetail.setUpdateTime(nowDate);
            orderDetailService.updateOrderDetail(updateDetail);

            //减少锁库，恢复库存
            ProdInventory prodInventory = mqProdInventoryMapper.selectProdInventoryLock(od.getProdId(), od.getProdAttrId(), orgOrder.getSellerId());

            prodInventory.setAvailQty(od.getQuantity());
            prodInventory.setUpdateTime(nowDate);
            prodInventory.setUpdateUser(opName);
            int cnt = mqProdInventoryMapper.updatePlusProdStock(prodInventory);

            ProdInventoryBill inventoryBill = new ProdInventoryBill();
            inventoryBill.setBillTime(nowDate);
            inventoryBill.setBillType(EInventoryBillType.LOCK.getVal());
            inventoryBill.setQuantity(od.getQuantity());
            inventoryBill.setInventoryId(prodInventory.getProdInventoryId());
            inventoryBill.setOrderId(order.getOrderId());
            inventoryBill.setOrderNo(orgOrder.getOrderNo());
            inventoryBill.setDelFlag(EDelFlag.NO.getVal());
            inventoryBill.setCreateUser(opName);
            inventoryBill.setCreateTime(nowDate);
            inventoryBill.setUpdateUser(opName);
            inventoryBill.setUpdateTime(nowDate);

            cnt = prodInventoryBillMapper.insertProdInventoryBill(inventoryBill);

        }

        // 关闭支付信息
        if (pi != null) {
            PaymentInfo upi = new PaymentInfo();
            upi.setPayId(pi.getPayId());
            upi.setOrderId(orgOrder.getOrderId());
            upi.setTradeState(EOrderStatus.CANCELLED.getVal());
            upi.setUpdateUser(opName);
            upi.setUpdateTime(nowDate);
            paymentInfoService.updatePaymentInfo(upi);
        }

        log.info("订单关闭MQ,订单【{}】数据处理完成.", orgOrder.getOrderNo());
        return true;
    }
}
