package com.mcwl.web.controller.pay.AliPay;

import cn.hutool.core.lang.UUID;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alipay.api.domain.AlipayAccount;
import com.alipay.easysdk.factory.Factory;
import com.mcwl.common.annotation.Anonymous;
import com.mcwl.common.constant.HttpStatus;
import com.mcwl.common.core.controller.BaseController;
import com.mcwl.common.core.domain.AjaxResult;
import com.mcwl.common.core.domain.R;
import com.mcwl.common.core.redis.RedisCache;
import com.mcwl.common.utils.SecurityUtils;
import com.mcwl.common.utils.ShareCodeUtils;
import com.mcwl.pay.config.AliConfig;
import com.mcwl.pay.domain.OrderTrade;
import com.mcwl.pay.domain.OrderTradeDto;
import com.mcwl.pay.domain.vo.PayVo;
import com.mcwl.pay.service.AliPayService;
import com.mcwl.pay.service.OrderTradeService;
import com.mcwl.system.domain.SysUserPayAccount;
import com.mcwl.system.service.ISysUserPayAccountService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.io.FileNotFoundException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * @Author：ChenYan
 * @Project：McWl
 * @Package：com.mcwl.web.controller.pay
 * @Filename：OrderTradeController
 * @Description 支付模块
 * @Date：2025/1/3 14:46
 */

@Controller
@RequestMapping("/ali/pay")
@Validated
@Api(tags = "支付模块")
public class AliPayController extends BaseController {

    @Autowired
    private OrderTradeService orderTradeService;

    @Autowired
    private ISysUserPayAccountService sysUserPayAccountService;

    @Autowired
    private AliPayService aliPayService;

    @Autowired
    private AliConfig aliConfig;


    @Autowired
    private RedisCache redisCache;

    @Value("${mall.mgt.aliPayConfig.bindUrl}")
    private String bindUrl;


    /**
     * 授权二维码
     *
     * @param response 响应
     * @throws Exception 抛出异常
     */
    @ApiOperation(value = "支付宝绑定")
    @GetMapping("/generateQrCode")
    @ResponseBody
    public R<String> generateQrCode(HttpServletResponse response) throws Exception {
        String scope = "auth_user"; // 需要获取用户信息
        String appId = aliConfig.getAppId();
        String state = ShareCodeUtils.idToCode(SecurityUtils.getUserId()); // 防止CSRF攻击

        String encodedRedirectUri = URLEncoder.encode(bindUrl, "UTF-8");
        String authUrl = String.format(aliConfig.getOauthUrl(),appId, scope, encodedRedirectUri, state);

//        QrCodeUtil.generate(authUrl, 300, 300, "png", response.getOutputStream());
        return R.ok(authUrl, "成功");
    }

    /**
     * 支付宝绑定状态查询
     */
    @GetMapping("/queryBindStatus")
    @ApiOperation(value = "支付宝绑定状态查询")
    @ResponseBody
    public R<Object> queryTradeStatus() throws Exception {

        return aliPayService.queryBindStatus();
    }

    /**
     * 授权回调
     *
     * @param authCode 授权码
     */
    @GetMapping("/callback")
    public String callback(@RequestParam("auth_code") String authCode, String state) throws FileNotFoundException {

        System.out.println("authCode = " + authCode);
        String result = aliPayService.bindingCallback(authCode, state);
        if ("success".equals(result)) {
            return "binding-success";
        } else {
            return "binding-fail";
        }
    }

//    /**
//     * 账户余额查询
//     */
//    @GetMapping("/balance")
//    @ResponseBody
//    public AjaxResult balance() throws AlipayApiException {
//        String balance = aliPayService.balance();
//        return AjaxResult.success(balance);
//    }


    /**
     * 支付接口
     *
     * @param orderTradeDto 订单实体
     * @param response      响应
     * @throws Exception
     */
    @Anonymous
    @PostMapping("/doPay")
    @ApiOperation(value = "支付宝支付")
    @ResponseBody
    public R<PayVo> doPay(@Valid
                          @RequestBody
                          OrderTradeDto orderTradeDto,
                          HttpServletResponse response) throws Exception {
        PayVo payVo = null;

        String type = orderTradeDto.getType();

        if ("member".equalsIgnoreCase(type)) {
            if (!Optional.ofNullable(orderTradeDto.getProductId()).isPresent()) {
                return R.fail(HttpStatus.SHOW_ERROR_MSG, "商品id不能为空");
            }
            payVo = aliPayService.memberPay(orderTradeDto);
//            QrCodeUtil.generate(payVo.getUrl(), 300, 300, "png", response.getOutputStream());
        } else if ("points".equalsIgnoreCase(type)) {
            payVo = aliPayService.pointsPay(orderTradeDto.getAmount());
//            QrCodeUtil.generate(payVo.getUrl(), 300, 300, "png", response.getOutputStream());
        } else if ("wallet".equalsIgnoreCase(type)) {
            // 充值金额只能是整数
            if (orderTradeDto.getAmount() % 1 != 0) {
                return R.fail(HttpStatus.SHOW_ERROR_MSG, "充值金额只能是整数");
            }
            payVo = aliPayService.walletPay(orderTradeDto.getAmount());
//            QrCodeUtil.generate(payVo.getUrl(), 300, 300, "png", response.getOutputStream());
        } else {
            return R.fail(HttpStatus.SHOW_ERROR_MSG, "订单类型错误");
        }

        return R.ok(payVo);
    }

    /**
     * 提现接口
     */
    @Anonymous
    @GetMapping("/fetch")
    @ResponseBody
    @ApiOperation(value = "提现")
    public R<String> fetch(@Valid
                           @NotNull(message = "提现金额不能为空")
                           @Pattern(regexp = "^(0|(?!0\\d)[1-9]\\d*)(\\.\\d{1,2})?$", message = "金额格式错误（必须保留两位小数）")
                           String amount) throws Exception {

        SysUserPayAccount sysUserPayAccount = sysUserPayAccountService.lambdaQuery()
                .eq(SysUserPayAccount::getUserId, SecurityUtils.getUserId())
                .eq(SysUserPayAccount::getType, 0)
                .one();

        if (Objects.isNull(sysUserPayAccount)) {
            return R.fail(HttpStatus.SHOW_ERROR_MSG, "请先绑定支付宝");
        }


        if (Double.parseDouble(amount) < 0.1) {
            return R.fail(HttpStatus.SHOW_ERROR_MSG, "提现金额最小为0.1");
        }

        return aliPayService.fetch(amount);
    }


    /**
     * 支付回调接口
     *
     * @param request
     * @return
     * @throws Exception
     */
    @Anonymous
    @PostMapping("/notify")  // 注意这里必须是POST接口
    @ResponseBody
    public String payNotify(HttpServletRequest request) throws Exception {


        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
            System.out.println("=========支付宝异步回调========");

            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
                // System.out.println(name + " = " + request.getParameter(name));
            }

            // 支付宝验签
            if (Factory.Payment.Common().verifyNotify(params)) {
//                System.out.println("交易名称: " + params.get("subject"));
//                System.out.println("交易状态: " + params.get("trade_status"));
//                System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
//                System.out.println("商户订单号: " + params.get("out_trade_no"));
//                System.out.println("交易金额: " + params.get("total_amount"));
//                System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
//                System.out.println("买家付款时间: " + params.get("gmt_payment"));
//                System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));
                // 验签通过

                String code = params.get("out_trade_no"); // 商户订单号
                OrderTrade orderTrade = orderTradeService.lambdaQuery()
                        .eq(OrderTrade::getCode, code)
                        .one();
                if (Objects.isNull(orderTrade)) {
                    return "failure";
                }
                // 获取订单后缀
                String suffix = code.substring(code.lastIndexOf("_") + 1);

                orderTradeService.orderHandler(orderTrade, suffix, params);

                // 更新订单状态
//                if (!StringUtils.isEmpty(orderTradeJson)) {
//                    OrderTrade orderTrade = JSONUtil.toBean(orderTradeJson, OrderTrade.class);
//                    // 支付宝交易凭证号
//                    orderTrade.setPaymentMethod(params.get("trade_no"));
//                    orderTrade.setTransactionId(1);
//                    orderTrade.setOrderTime(DateUtils.parseDate(params.get("gmt_payment")));
//                    orderTrade.setOrderStatus(3);
//                    orderTrade.setPayStatus(2);
//                    String totalAmountStr = params.get("total_amount");
//                    if (totalAmountStr != null && !totalAmountStr.isEmpty()) {
//                        BigDecimal totalAmount = new BigDecimal(totalAmountStr);
//                        orderTrade.setTotalAmount(totalAmount.intValue());
//                    }
//                    String buyerPayAmountStr = params.get("buyer_pay_amount");
//                    if (buyerPayAmountStr != null && !buyerPayAmountStr.isEmpty()) {
//                        BigDecimal buyerPayAmount = new BigDecimal(buyerPayAmountStr);
//                        orderTrade.setPaymentAmount(buyerPayAmount.intValue());
//                    }
//                    orderTradeService.save(orderTrade);
//                }
            } else {
                // 验签失败
                System.out.println("验签失败");
            }
        } else {
            // 验签失败
            System.out.println("验签失败");
        }

        return "success";
    }


}
