package com.yonge.cooleshow.portal.controller;

import com.alibaba.fastjson.JSON;
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.common.controller.BaseController;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.mall.common.enums.OrderCacheEnum;
import com.yonge.cooleshow.mbg.model.UserOrderPayment;
import com.yonge.cooleshow.portal.dto.OrderPayReq;
import com.yonge.cooleshow.portal.dto.OrderPayRes;
import com.yonge.cooleshow.portal.service.OmsPortalOrderReturnApplyService;
import com.yonge.cooleshow.portal.service.OmsPortalOrderService;
import com.yonge.cooleshow.portal.service.UserOrderPaymentService;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.result.BaseResult;
import com.yonge.toolset.payment.base.enums.MethodNameEnum;
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.model.OpenAuth;
import com.yonge.toolset.payment.base.model.Payment;
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.utils.web.WebUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: liweifan
 * @Data: 2022/3/11 18:16
 */
@RestController
@RequestMapping("/payment")
@Api(value = "付款接口", tags = "付款接口")
public class PaymentController extends BaseController {
    private final static Logger log = LoggerFactory.getLogger(PaymentController.class);

    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private PaymentClient paymentClient;
    @Autowired
    private PaymentProperties paymentProperties;

    @Autowired
    private OmsPortalOrderService orderService;

    @Autowired
    private UserOrderPaymentService userOrderPaymentService;

    @Autowired
    private OmsPortalOrderReturnApplyService portalOrderReturnApplyService;

    @Autowired
    private RedissonClient redissonClient;

    @ApiOperation(value = "订单付款")
    @PostMapping("/orderPay")
    public HttpResponseResult<OrderPayRes> orderPay(@Valid @RequestBody OrderPayReq payReq, HttpServletRequest request) {
        SysUser user = sysUserFeignService.queryUserInfo();
        if (user == null || null == user.getId()) {
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }
        payReq.setUserId(user.getId());
        payReq.setIpAddress(WebUtil.getRemoteIp(request));

        RLock lock = redissonClient.getLock(OrderCacheEnum.LOCK_ORDER_NO_MALL.getRedisKey(payReq.getOrderNo()));
        try {
            boolean b = lock.tryLock(60, TimeUnit.SECONDS);
            if (b) {
                OrderPayRes orderPayRes = orderService.orderPay(payReq);
                if (orderPayRes.isStatus()) {
                    return succeed(orderPayRes);
                } else {
                    return failed(orderPayRes.getMessage());
                }
            }
            return failed("请求超时");
        } catch (BizException e) {
            return failed(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            return HttpResponseResult.failed("付款失败");
        } finally {
            if (lock.getHoldCount()>0) {
                lock.unlock();
            }
        }
    }

    @ApiOperation(value = "查询付款单")
    @GetMapping("/queryPayment")
    public HttpResponseResult<Payment> queryPayment(String paymentNo) {
        UserOrderPayment userOrderPayment = userOrderPaymentService.getByTranNo(paymentNo);
        if (null == userOrderPayment) {
            return HttpResponseResult.succeed();
        }
        Payment param = new Payment(OpenEnum.valueOf(userOrderPayment.getOpenType()),
                PaymentClientEnum.valueOf(userOrderPayment.getPaymentClient()), PayChannelEnum.valueOf(userOrderPayment.getPayChannel()));
        param.setId(userOrderPayment.getTransNo());
        param.setPaymentNo(userOrderPayment.getAdapayNo());
        BaseResult<Payment> paymentBaseResult = paymentClient.queryPayment(param);
        return HttpResponseResult.status(paymentBaseResult);
    }

    @ApiOperation(value = "通过用户给的授权码获取三方支付授权信息")
    @GetMapping("/getOpenId")
    public HttpResponseResult<Map<String, Object>> getOpenId(OpenAuth openAuth) {
        SysUser user = sysUserFeignService.queryUserInfo();
        if (user == null || null == user.getId()) {
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }
        OpenEnum openType = OpenEnum.valueOf(paymentProperties.getOpenType());
        openAuth.setOpenType(openType);
        BaseResult<Map<String, Object>> res = paymentClient.getOpenAuthMsg(openAuth);
        return HttpResponseResult.status(res);
    }

    /***
     * 支付回调
     * @author liweifan
     * @param: request
     * @updateTime 2022/3/11 18:35
     */
    @RequestMapping("/callback/{openType}/{client}/{payChannel}/{payMethod}")
    public Object callback(
            @PathVariable("openType") String openType,
            @PathVariable("client") String client,
            @PathVariable("payChannel") String payChannel,
            @PathVariable("payMethod") String payMethod,
            HttpServletRequest request
    ) {
        BaseResult<PaymentCallBack> res = paymentClient.analysisNotice(
                OpenEnum.valueOf(openType), PaymentClientEnum.valueOf(client),
                PayChannelEnum.valueOf(payChannel), MethodNameEnum.valueOf(payMethod), request);
        log.info("支付回调整理后的信息 ： {}", JSON.toJSONString(res));
        if (res.getStatus()) {
            PaymentCallBack data = res.getData();

            UserOrderPayment userOrderPayment = userOrderPaymentService.getByAdapayNo(data.getPaymentNo());
            if (userOrderPayment != null) {
                RLock lock = redissonClient.getLock(OrderCacheEnum.LOCK_ORDER_NO_MALL.getRedisKey(userOrderPayment.getOrderNo()));
                try {
                    boolean b = lock.tryLock(60, TimeUnit.SECONDS);
                    if (b) {
                        if (MethodNameEnum.executePayment.equals(data.getMethodName())) {
                            //支付交易
                            orderService.executePaymentCallBack(data);
                        } else if (MethodNameEnum.closePayment.equals(data.getMethodName())) {
                            //关闭订单
                            orderService.closePaymentCallBack(data);
                        }
                    } else {
                        return failed("请求超时");
                    }
                }catch (Exception e) {
                    e.printStackTrace();
                    return HttpResponseResult.failed("付款失败");
                } finally {
                    if (lock.getHoldCount()>0) {
                        lock.unlock();
                    }
                }
            }
            try {
                if (MethodNameEnum.refundPayment.equals(data.getMethodName())) {
                    //退款
                    portalOrderReturnApplyService.refundPaymentCallBack(data);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return res.getData().getResMsg();
    }

}
