package com.gxwebsoft.shop.controller;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.WxNativeUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.common.system.entity.Setting;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.entity.Order;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.common.system.param.SettingParam;
import com.gxwebsoft.shop.service.OrderService;
import com.gxwebsoft.common.system.service.SettingService;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Map;


@Api(tags = "微信Native支付接口")
@RestController
@RequestMapping("/api/shop/wx-native-pay")
public class WxNativePayController extends BaseController {
  @Value("${spring.profiles.active}")
  String active;
  public static String merchantId = "1246610101";
  public static String privateKeyPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.core/src/main/resources/cert/apiclient_key.pem";
  public static String merchantSerialNumber = "48749613B40AA8F1D768583FC352358E13EB5AF0";
  public static String apiV3Key = "zGufUcqa7ovgxRL0kF5OlPr482EZwtn9";
  @Resource
  private RedisUtil redisUtil;
  private Config wxPayConfig;
  @Resource
  private ConfigProperties config;
  @Resource
  private SettingService settingService;
  @Resource
  private OrderService orderService;


  @ApiOperation("生成付款码")
  @PostMapping("/codeUrl")
  public ApiResult<?> getCodeUrl(@RequestBody Order order) {
    final User loginUser = getLoginUser();
    if(loginUser == null){
      return fail("请先登录");
    }
    String key = "Payment:wxPay:".concat(getTenantId().toString());
    final Payment payment = redisUtil.get(key, Payment.class);
    if (payment == null) {
      return fail("微信支付未配置");
    }
    // 获取微信小程序配置信息
    final String string = redisUtil.get("mp-weixin:".concat(getTenantId().toString()));
    if(string == null){
      return fail("微信小程序未配置");
    }
    final JSONObject jsonObject = JSONObject.parseObject(string);
    final String appId = jsonObject.getString("appId");

    // 处理订单数据
    order.setTenantId(loginUser.getTenantId());
    order.setUserId(loginUser.getUserId());
    order.setRealName(loginUser.getRealName());
    order.setPhone(loginUser.getPhone());
    order.setExpirationTime(DateUtil.offset(DateUtil.date(), DateField.MONTH, order.getTotalNum()));

    // 使用自动更新平台证书的RSA配置
    // 一个商户号只能初始化一个配置，否则会因为重复的下载任务报错

    // 构建service
    NativePayService service = new NativePayService.Builder().config(this.getWxPayConfig()).build();
    // request.setXxx(val)设置所需参数，具体参数可见Request定义
    PrepayRequest request = new PrepayRequest();
    // 计算金额
    order.setMoney(new BigDecimal("0.01"));  // order.getPayPrice().toString()
    long orderNo = IdUtil.getSnowflakeNextId();
    order.setOrderNo(Long.toString(orderNo));
    BigDecimal decimal = order.getMoney();
    final BigDecimal multiply = decimal.multiply(new BigDecimal(100));
    // 将 BigDecimal 转换为 Integer
    Integer money = multiply.intValue();
    Amount amount = new Amount();
    amount.setTotal(money);
    request.setAmount(amount);
    request.setAppid(appId);
    request.setMchid(payment.getMchId());
    request.setDescription(order.getComments());
    request.setNotifyUrl("https://modules.gxwebsoft.com/api/shop/wx-native-pay/notify/" + getTenantId());
    request.setOutTradeNo(order.getOrderNo());
    // 调用下单方法，得到应答
    PrepayResponse response = service.prepay(request);
    // 使用微信扫描 code_url 对应的二维码，即可体验Native支付
//    System.out.println(response.getCodeUrl());
    // 生成指定url对应的二维码到文件，宽和高都是300像素
//    QrCodeUtil.generate(response.getCodeUrl(), 300, 300, FileUtil.file("/Users/gxwebsoft/Documents/uploads/wx-native-qrcode.jpg"));
    orderService.save(order);

    return success("生成付款码", response.getCodeUrl());
  }


  private Config getWxPayConfig() {
    // 获取租户ID
    final Integer tenantId = getTenantId();
    Config build = WxNativeUtil.getConfig(tenantId);
    if (build != null) {
      return build;
    }
    String key = "Payment:wxPay:".concat(tenantId.toString());
    final Payment payment = redisUtil.get(key, Payment.class);
    System.out.println("payment = " + payment);
    String apiclientKey = config.getUploadPath().concat("/file").concat(payment.getApiclientKey());
    // 开发环境配置
    if(active.equals("dev")){
      apiclientKey = privateKeyPath;
    }
    Config config = new RSAAutoCertificateConfig.Builder()
      .merchantId(payment.getMchId())
      .privateKeyFromPath(apiclientKey)
      .merchantSerialNumber(payment.getMerchantSerialNumber())
      .apiV3Key(payment.getApiKey())
      .build();
    System.out.println("config = " + config);
    WxNativeUtil.addConfig(tenantId, config);
    return config;
  }

  @ApiModelProperty("异步通知")
  @PostMapping("/notify/{tenantId}")
  public String wxNotify(@RequestHeader Map<String, String> header, @RequestBody String body, @PathVariable("tenantId") Integer tenantId) {
    System.out.println("异步通知*************** = ");
    System.out.println("request header = " + header);
    System.out.println("request body = " + body);
    System.out.println("tenantId = " + tenantId);

    // 获取支付配置信息用于解密
    final SettingParam param = new SettingParam();
    param.setSettingKey("payment");
    param.setTenantId(tenantId);
    final String uploadPath = config.getUploadPath();   // 服务器本地路径

    return "fail";
  }
}
