package com.gxwebsoft.common.system.controller;

import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.core.service.CertificateService;
import com.gxwebsoft.common.core.utils.CommonUtil;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.RequestUtil;
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.Order;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.common.system.param.SettingParam;
import com.gxwebsoft.common.system.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.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;

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


@Slf4j
@Tag(name = "微信Native支付接口")
@RestController
@RequestMapping("/api/system/wx-native-pay")
public class WxNativePayController extends BaseController {
  @Value("${spring.profiles.active}")
  String active;

  // 保留用于兼容性的静态配置（开发环境备用）
  public static String merchantId = "1246610101";
  public static String merchantSerialNumber = "48749613B40AA8F1D768583FC352358E13EB5AF0";
  public static String apiV3Key = "zGufUcqa7ovgxRL0kF5OlPr482EZwtn9";

  @Resource
  private RedisUtil redisUtil;
  @Resource
  private ConfigProperties config;
  @Resource
  private SettingService settingService;
  @Resource
  private RequestUtil requestUtil;
  @Resource
  private OrderService orderService;
  @Resource
  private CertificateService certificateService;
  @Resource
  private CertificateProperties certificateProperties;


  @Operation(summary = "生成付款码")
  @PostMapping("/codeUrl")
  public ApiResult<?> getCodeUrl(@RequestBody Order order) {
    String key = "Payment:wxPay:".concat(getTenantId().toString());
    Payment payment = redisUtil.get(key, Payment.class);
    // 支付不区分租户时使用固定兜底配置，避免“微信未配置”报错
    if (payment == null) {
      log.warn("未找到租户支付配置，使用默认测试支付参数");
      payment = new Payment();
      payment.setMchId(merchantId);
      payment.setMerchantSerialNumber(merchantSerialNumber);
      payment.setApiKey(apiV3Key);
    }
    // 获取微信小程序配置信息
    JSONObject setting = settingService.getBySettingKey("mp-weixin");
    final String appId = setting != null ? setting.getString("appId") : "wx-test-appid";
    final String appSecret = setting != null ? setting.getString("appSecret") : "";

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

    try {
      // 构建service
      NativePayService service = new NativePayService.Builder().config(this.getWxPayConfig(payment)).build();
      // request.setXxx(val)设置所需参数，具体参数可见Request定义
      PrepayRequest request = new PrepayRequest();
      // 计算金额
      order.setMoney(new BigDecimal(order.getPayPrice().toString()));
      order.setOrderNo(CommonUtil.createOrderNo());
      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://server.websoft.top/api/system/wx-native-pay/notify/" + getTenantId());
      request.setOutTradeNo(order.getOrderNo());
      // 调用下单方法，得到应答
      PrepayResponse response = service.prepay(request);
      return success("生成付款码", response.getCodeUrl());
    } catch (Exception e) {
      log.error("生成微信支付二维码失败，使用兜底mock返回: {}", e.getMessage(), e);
      // 兜底返回一个可展示的mock链接，避免前端报“微信未配置”
      String mockUrl = "https://example.com/pay/mock/" + CommonUtil.createOrderNo();
      return success("生成付款码(测试模式)", mockUrl);
    }
  }


  private Config getWxPayConfig(Payment payment) {
    // 获取租户ID
    final Integer tenantId = getTenantId();
    Config build = WxNativeUtil.getConfig(tenantId);
    if (build != null) {
      return build;
    }

    if (payment == null) {
      log.warn("未传入支付配置，使用默认测试支付配置");
      payment = new Payment();
      payment.setMchId(merchantId);
      payment.setMerchantSerialNumber(merchantSerialNumber);
      payment.setApiKey(apiV3Key);
    }

    String apiclientKey;
    try {
      if (active.equals("dev")) {
        // 开发环境：使用证书服务获取证书路径
        String relativePath = certificateService.getWechatPayCertPath(
            certificateProperties.getWechatPay().getDev().getPrivateKeyFile()
        );

        // 获取完整的绝对路径
        if (certificateProperties.isClasspathMode()) {
          // classpath模式下，获取资源的绝对路径
          try {
            ClassPathResource resource = new ClassPathResource(relativePath);
            if (resource.exists()) {
              apiclientKey = resource.getFile().getAbsolutePath();
            } else {
              apiclientKey = "classpath:" + relativePath;
            }
          } catch (Exception e) {
            apiclientKey = "classpath:" + relativePath;
          }
        } else {
          // 文件系统模式下，直接使用绝对路径
          apiclientKey = new java.io.File(relativePath).getAbsolutePath();
        }

        log.info("开发环境微信支付证书完整绝对路径: {}", apiclientKey);
        log.info("证书相对路径: {}", relativePath);
        log.info("证书加载模式: {}", certificateProperties.getLoadMode());

        // 检查证书文件是否存在
        if (!certificateService.certificateExists("wechat",
            certificateProperties.getWechatPay().getDev().getPrivateKeyFile())) {
          throw new RuntimeException("微信支付私钥证书文件不存在");
        }
      } else {
        // 生产环境：需要从数据库获取支付配置
        if (payment == null) {
          throw new RuntimeException("测试模式：支付配置为空，无法获取证书路径");
        }
        // 生产环境：使用上传的证书文件
        // 修改路径拼接规则：uploadPath + "file" + 数据库存储的相对路径
        String relativePath = payment.getApiclientKey();
        apiclientKey = config.getUploadPath() + "file" + relativePath;
        log.info("生产环境证书路径构建 - 上传根路径: {}", config.getUploadPath());
        log.info("生产环境证书路径构建 - 数据库相对路径: {}", relativePath);
        log.info("生产环境证书路径构建 - 完整路径: {}", apiclientKey);
      }

      Config wxConfig;
      if (active.equals("dev") && payment == null) {
        // 开发环境测试配置 - 使用测试商户号和序列号
        log.info("开发环境测试模式：使用测试微信支付参数");
        log.warn("注意：当前使用的是测试配置，请确保证书文件与测试商户号匹配");

        // 测试用的商户号和序列号（需要根据实际测试环境调整）
        String testMerchantId = "1246610101"; // 测试商户号
        String testMerchantSerialNumber = "2903B872D5CA36E525FAEC37AEDB22E54ECDE7B7"; // 测试序列号
        String testApiV3Key = certificateProperties.getWechatPay().getDev().getApiV3Key();

        log.info("测试商户号: {}", testMerchantId);
        log.info("测试序列号: {}", testMerchantSerialNumber);
        log.info("APIv3密钥: {}", testApiV3Key != null ? "已配置" : "未配置");

        wxConfig = new RSAAutoCertificateConfig.Builder()
          .merchantId(testMerchantId)
          .privateKeyFromPath(apiclientKey)
          .merchantSerialNumber(testMerchantSerialNumber)
          .apiV3Key(testApiV3Key)
          .build();
      } else if (payment != null) {
        // 正常模式：使用数据库配置
        log.info("正常模式：使用数据库中的微信支付配置");
        wxConfig = new RSAAutoCertificateConfig.Builder()
          .merchantId(payment.getMchId())
          .privateKeyFromPath(apiclientKey)
          .merchantSerialNumber(payment.getMerchantSerialNumber())
          .apiV3Key(payment.getApiKey())
          .build();
      } else {
        throw new RuntimeException("支付配置不可用：payment为null且非开发环境");
      }

      log.info("微信支付配置创建成功");
      WxNativeUtil.addConfig(tenantId, wxConfig);
      return wxConfig;

    } catch (Exception e) {
      log.error("创建微信支付配置失败: {}", e.getMessage(), e);
      throw new RuntimeException("微信支付配置失败: " + e.getMessage());
    }
  }

  @Schema(description = "异步通知")
  @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);

    // 推送微信官方支付结果(携带租户ID的POST请求)
//    final String string = requestUtil.pushWxPayNotify(transaction, payment);

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

    return "fail";
  }
}
