package com.yonge.cooleshow.tenant.controller;

import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.microsvc.toolkit.common.response.template.R;
import com.microsvc.toolkit.common.webportal.exception.BizException;
import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.biz.dal.dto.req.OrderPayReq;
import com.yonge.cooleshow.biz.dal.entity.TenantStaff;
import com.yonge.cooleshow.biz.dal.entity.UserOrder;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.service.TenantStaffService;
import com.yonge.cooleshow.biz.dal.service.UserOrderService;
import com.yonge.cooleshow.biz.dal.service.UserPaymentCoreService;
import com.yonge.cooleshow.biz.dal.vo.UserOrderVo;
import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.enums.CacheNameEnum;
import com.yonge.cooleshow.common.enums.EPaymentVersion;
import com.yonge.cooleshow.tenant.vo.UserPaymentOrderVo;
import com.yonge.toolset.base.util.StringUtil;
import com.yonge.toolset.payment.util.DistributedLock;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Objects;

import static com.yonge.cooleshow.common.entity.HttpResponseResult.failed;
import static com.yonge.cooleshow.common.entity.HttpResponseResult.succeed;

@Validated
@RestController
@RequestMapping("${app-config.url.tenant:}/userOrder")
@Api(tags = "用户支付订单")
public class UserOrderController {


    @Autowired
    private UserOrderService userOrderService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private SysUserFeignService sysUserFeignService;

    @Autowired
    private UserPaymentCoreService userPaymentCoreService;

    @Autowired
    private TenantStaffService tenantStaffService;

    @ApiOperation(value = "用户下单", notes = "用户下单")
    @PostMapping("/executeOrder/v2")
    public R<UserPaymentOrderWrapper.PaymentConfig> executeOrder(@Validated @RequestBody UserPaymentOrderVo.OrderReq orderReq) {

        // 设置下单用户信息
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (Objects.isNull(sysUser)) {
            throw BizException.from("用户信息不存在");
        }
        orderReq.setUserId(sysUser.getId());
        orderReq.setPaymentClient(ClientEnum.TENANT.name());


        // 用户下单请求
        UserPaymentOrderWrapper.UserPaymentOrder order = JSON.parseObject(orderReq.jsonString(), UserPaymentOrderWrapper.UserPaymentOrder.class);

        TenantStaff tenantStaff = tenantStaffService.getByUserId(sysUser.getId());
        if (Objects.isNull(tenantStaff)) {
            throw BizException.from("用户信息不存在");
        }
        if (orderReq.getPaymentCashAmount().compareTo(new BigDecimal(10000000))>0) {
            throw new com.yonge.toolset.base.exception.BizException("支付失败，下单金额超过最高上限");
        }

        order.setTenantId(tenantStaff.getTenantId());
        // 新增数据
        UserPaymentOrderWrapper.PaymentConfig paymentConfig = userPaymentCoreService.executeOrderCreate(order);
        if (Objects.isNull(paymentConfig)) {
            throw BizException.from("下单失败");
        }

        return R.from(paymentConfig);
    }

    @ApiOperation(value = "用户付款", notes = "用户付款")
    @PostMapping("/executePayment/v2")
    public R<UserPaymentOrderWrapper.PaymentReq> executePayment(@Validated @RequestBody UserPaymentOrderVo.PaymentReqConfig config, HttpServletRequest request) {
        // 设置下单用户信息
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (Objects.isNull(sysUser)) {
            throw BizException.from("用户信息不存在");
        }


        // 用户下单请求
        UserPaymentOrderWrapper.PaymentOrderReqConfig reqConfig = UserPaymentOrderWrapper.PaymentOrderReqConfig.from(config.jsonString());

        // 支付三方
        reqConfig.setPaymentVendor(config.getPaymentVendor());
        // 请示IP地址
        reqConfig.setIp(ServletUtil.getClientIP(request));
        // 创建用户支付数据
        UserPaymentOrderWrapper.PaymentReq paymentConfig = userPaymentCoreService.executePayment(JwtUserInfo.builder()
                .userId(sysUser.getId().toString()).clientType(ClientEnum.TENANT.getCode()).build(), reqConfig);
        if (Objects.isNull(paymentConfig)) {
            throw BizException.from("付款失败");
        }

        return R.from(paymentConfig);
    }


    @ApiOperation(value = "取消订单")
    @PostMapping("/orderCancel")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderNo", value = "订单号", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "reason", value = "取消说明", paramType = "query", dataType = "String")
    })
    public HttpResponseResult<Boolean> orderCancel(@ApiIgnore @RequestBody OrderPayReq payReq) {
        SysUser user = sysUserFeignService.queryUserInfo();
        if (user == null || null == user.getId()) {
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }
        if (StringUtil.isEmpty(payReq.getOrderNo())) {
            return failed("订单号不能为空");
        }
        payReq.setUserId(user.getId());

        UserOrder order = userOrderService.getByOrderNo(payReq.getOrderNo());
        if (null == order) {
            return failed("订单不存在");
        }
        if(order.getPaymentVersion().equals(EPaymentVersion.V2)){


            // 用户取消支付
            userPaymentCoreService.cancelPayment(JwtUserInfo.builder().userId(user.getId().toString()).clientType(ClientEnum.STUDENT.getCode()).build(), payReq.getOrderNo());
        } else {

            try {
                HttpResponseResult<Boolean> res = DistributedLock.of(redissonClient)
                        .runIfLockToFunction(CacheNameEnum.LOCK_EXECUTE_ORDER.getRedisKey(payReq.getOrderNo())
                                , userOrderService::orderCancel, payReq, 10L);
                if (null != res) {
                    return res;
                } else {
                    return HttpResponseResult.failed("取消订单失败");
                }
            } catch (com.yonge.toolset.base.exception.BizException e) {
                return HttpResponseResult.failed(e.getMessage());
            } catch (Exception e) {
                e.printStackTrace();
                return HttpResponseResult.failed("取消订单失败");
            }
        }
        return succeed();
    }

    @ApiOperation(value = "取消订单")
    @PostMapping("/orderCancel/v2")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderNo", value = "订单号", paramType = "query", dataType = "String", required = true),
            @ApiImplicitParam(name = "reason", value = "取消说明", paramType = "query", dataType = "String")
    })
    public HttpResponseResult<Boolean> orderCancelV2(@ApiIgnore @RequestBody OrderPayReq payReq) {
        SysUser user = sysUserFeignService.queryUserInfo();
        if (user == null || null == user.getId()) {
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }
        if (StringUtil.isEmpty(payReq.getOrderNo())) {
            return failed("订单号不能为空");
        }
        payReq.setUserId(user.getId());

        // 用户取消支付
        userPaymentCoreService.cancelPayment(JwtUserInfo.builder().userId(user.getId().toString()).clientType(ClientEnum.TENANT.getCode()).build(), payReq.getOrderNo());

        return HttpResponseResult.status(true);
    }


    @ApiOperation(value = "检测订单应该使用哪种支付方式")
    @PostMapping("/orderPayType")
    public HttpResponseResult<UserPaymentOrderWrapper.OrderPayTypeResp> orderPayType( @RequestBody UserPaymentOrderWrapper.OrderPayTypeReq payTypeReq) {
        SysUser user = sysUserFeignService.queryUserInfo();
        if (user == null || null == user.getId()) {
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }

        payTypeReq.setBuyId(user.getId());
        payTypeReq.setClientType(ClientEnum.TENANT);

        // 用户取消支付


        return succeed(userPaymentCoreService.orderPayType(payTypeReq));
    }

    /**
     * 查询单条
     */
    @GetMapping("/detailByOrderNo/{orderNo}")
    @ApiOperation(value = "通过订单号查询详情", notes = "传入orderNo")
    public HttpResponseResult<UserOrderVo> detailByOrderNo(@PathVariable("orderNo") String orderNo) {
        SysUser user = sysUserFeignService.queryUserInfo();
        if (user == null || null == user.getId()) {
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }
        UserOrder param = new UserOrder();
//        param.setUserId(user.getId());
        param.setOrderNo(orderNo);
        UserOrderVo detail = userOrderService.detailApp(param);
        return succeed(detail);
    }



}
