package com.leromro.core.facade;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.leromro.common.core.domain.AjaxResult;
import com.leromro.common.core.domain.R;
import com.leromro.common.exception.ServiceException;
import com.leromro.core.domain.MainOrders;
import com.leromro.core.domain.SecondOrder;
import com.leromro.core.service.IMainOrderService;
import com.leromro.core.service.IOrderRefundService;
import com.leromro.core.service.ISecondOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
public class OrdersFacade {

    @Autowired
    private IMainOrderService mainOrderService;

    @Autowired
    private ISecondOrderService secondOrderService;

    @Autowired
    private IOrderRefundService orderRefundService;

    @Autowired
    @Qualifier("wxMiniPayService")
    private WxPayService wxMiniPayService;

    @Autowired
    @Qualifier("wxMiniPayRefundService")
    private  WxPayService wxMiniPayRefundService;

    @Autowired
    private RedissonClient redissonClient;


    /**
     * 支付超时或取消
     */
    public AjaxResult PayCancel(MainOrders mainOrders) {
        //查询订单
        mainOrders = mainOrderService.getOne(new QueryWrapper<MainOrders>().eq("main_order_id", mainOrders.getMainOrderId()));
        if (ObjectUtil.isNull(mainOrders)){
            log.error("取消失败,未查询到当前主订单信息，主订单id：{}", mainOrders.getMainOrderId());
            return AjaxResult.error("取消失败,未查询到当前主订单信息");
        }
        //查询小订单
        List<SecondOrder> secondOrderList = secondOrderService.list(new QueryWrapper<SecondOrder>().eq("main_order_id", mainOrders.getMainOrderId()));
        if (CollectionUtil.isEmpty(secondOrderList)){
            log.error("取消失败,未查询到当前子订单信息,主订单id：{}", mainOrders.getMainOrderId());
            return AjaxResult.error("取消失败,未查询到当前子订单信息");
        }

        //修改主、小订单状态 全额退款，设置主订单的状态为6 已取消
        mainOrders.setOrderStatus("2");
        orderRefundService.updateMainOrderAndSeconderStatus(mainOrders,"2");
        //修改志愿者的工作时间以及日期
        orderRefundService.updateVolunteerWorkDateAndTime(secondOrderList, mainOrders);
        return AjaxResult.success("取消成功");
    }


    /**
     * 订单支付回调
     */
    @Transactional(rollbackFor = Exception.class)
    public String payNotify(String xmlData) {
        RLock fairLock = null;
        try {
            log.info("=====================>>>微信支付回调接收<<====================={}", xmlData);
            //解析微信回调数据
            WxPayOrderNotifyResult notifyResult = wxMiniPayService.parseOrderNotifyResult(xmlData);
            log.info("=====================>>>微信支付回调解析<<====================={}", notifyResult);
            //查询订单相关信息
            fairLock = redissonClient.getLock("order:notify:"+notifyResult.getOutTradeNo());
            //获取锁
            boolean lock = fairLock.tryLock(1000, TimeUnit.MILLISECONDS);
            if (lock){
                //再执行订单状态修改
                MainOrders mainOrders = mainOrderService.getOne(new QueryWrapper<MainOrders>().eq("out_trade_no", notifyResult.getOutTradeNo()));
                if (ObjectUtil.isNull(mainOrders)){
                    log.error("微信支付回调结果异常1,异常原因：订单号无法找到对应订单{}",notifyResult.getOutTradeNo() );
                }
                //判断支付结果
                if ("SUCCESS".equals(notifyResult.getResultCode())){
                    //修改平台流水
                    //查询小订单
                    List<SecondOrder> secondOrderList = secondOrderService.list(new QueryWrapper<SecondOrder>().eq("main_order_id", mainOrders.getMainOrderId()));
                    mainOrderService.changePlatformFinance(secondOrderList.stream().map(SecondOrder::getSecondOrderId).collect(Collectors.toList()), mainOrders);
                    //修改订单状态
                    mainOrderService.update(new LambdaUpdateWrapper<MainOrders>()
                            .set(MainOrders::getOrderStatus, 1)
                            .eq(MainOrders::getMainOrderId, mainOrders.getMainOrderId()));
                    secondOrderService.update(new LambdaUpdateWrapper<SecondOrder>()
                            .set(SecondOrder::getOrderStatus, 1)
                            .eq(SecondOrder::getMainOrderId, mainOrders.getMainOrderId()));
                    //向志愿者推送消息，并且插入未读消息
                }else if ("FAIL".equals(notifyResult.getResultCode())){
                    //调用支付取消接口
                    this.PayCancel(mainOrders);
                }
            }
            return WxPayNotifyResponse.success("成功");
        }catch (Exception e){
            log.error("微信支付回调结果异常2,异常原因：{}", e.getMessage());
            return WxPayNotifyResponse.fail("code:9999微信支付回调结果异常,异常原因:" + e.getMessage());
        }finally {
            if (ObjectUtil.isNotNull(fairLock) && fairLock.isLocked() && fairLock.isHeldByCurrentThread()) {
                fairLock.unlock();
            }
        }
    }


    /**
     * 申请退款回调
     */
    @Transactional(rollbackFor = Exception.class)
    public String refundNotify(String xmlData) {
        RLock fairLock = null;
        try {
            log.info("=====================>>>微信退款回调接收<<====================={}", xmlData);
            //解析微信回调数据
            WxPayRefundNotifyResult result = wxMiniPayRefundService.parseRefundNotifyResult(xmlData);
            WxPayRefundNotifyResult.ReqInfo reqInfo = result.getReqInfo();
            log.info("=====================>>>微信退款回调解析<<====================={}", result);
            //查询订单相关信息
            fairLock = redissonClient.getLock("order:notify:"+reqInfo.getOutTradeNo());
            //获取锁
            boolean lock = fairLock.tryLock(1000, TimeUnit.MILLISECONDS);
            if (lock){
                //查询订单
                MainOrders mainOrders = mainOrderService.getOne(new QueryWrapper<MainOrders>().eq("out_trade_no", reqInfo.getOutTradeNo()));
                if ("SUCCESS".equals(reqInfo.getRefundStatus())){
                    if (ObjectUtil.isNotNull(mainOrders)){
                        //修改退款状态,如果退款金额不等于订单金额，修改退款状态为部分退款
                        if (reqInfo.getTotalFee().equals(reqInfo.getSettlementRefundFee())){
                            //修改为已退款
                            mainOrderService.update(new LambdaUpdateWrapper<MainOrders>()
                                    .set(MainOrders::getOrderStatus, 6)
                                    .eq(MainOrders::getMainOrderId, mainOrders.getMainOrderId()));
                            secondOrderService.update(new LambdaUpdateWrapper<SecondOrder>()
                                    .set(SecondOrder::getOrderStatus, 6)
                                    .eq(SecondOrder::getMainOrderId, mainOrders.getMainOrderId()));
                        } else {
                            //修改为部分退款
                            mainOrderService.update(new LambdaUpdateWrapper<MainOrders>()
                                    .set(MainOrders::getOrderStatus, 7)
                                    .eq(MainOrders::getMainOrderId, mainOrders.getMainOrderId()));
                            secondOrderService.update(new LambdaUpdateWrapper<SecondOrder>()
                                    .set(SecondOrder::getOrderStatus, 6)
                                    .eq(SecondOrder::getMainOrderId, mainOrders.getMainOrderId())
                                    .in(SecondOrder::getOrderStatus,"0","1"));
                        }
                    }
                }
            }
        }catch (Exception e){
            log.error("微信退款回调结果异常,异常原因：{}", e.getMessage());
        }finally {
            if (ObjectUtil.isNotNull(fairLock) && fairLock.isLocked() && fairLock.isHeldByCurrentThread()) {
                fairLock.unlock();
            }
        }
        return WxPayNotifyResponse.success("成功");
    }

    /**
     * 微信支付-查询退款
     * @param transactionId
     * @param outTradeNo
     * @param outRefundNo
     * @param refundId
     * @return
     */
    public R<WxPayRefundQueryResult> refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId){
        try {
            return R.ok(this.wxMiniPayRefundService.refundQuery(transactionId, outTradeNo, outRefundNo, refundId));
        }catch (Exception e){
            return R.fail("查询退款失败:"+e.getMessage());
        }
    }
}
