package com.gxwebsoft.payment.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.core.service.CertificateService;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.utils.WxNativeUtil;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.common.system.param.PaymentParam;
import com.gxwebsoft.common.system.service.PaymentService;
import com.gxwebsoft.payment.exception.PaymentException;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 微信支付配置服务
 * 负责管理微信支付的配置信息和证书
 *
 * @author 科技小王子
 * @since 2025-01-26
 */
@Slf4j
@Service
public class WxPayConfigService {

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private CertificateService certificateService;

    @Resource
    private CertificateProperties certificateProperties;

    @Resource
    private PaymentService paymentService;

    @Value("${spring.profiles.active:dev}")
    private String activeProfile;

    /**
     * 获取支付配置信息（Payment对象）- 公开方法
     *
     * @param tenantId 租户ID
     * @return 支付配置信息
     * @throws PaymentException 配置获取失败时抛出
     */
    public Payment getPaymentConfigForStrategy(Integer tenantId) throws PaymentException {
        if (tenantId == null) {
            throw PaymentException.paramError("租户ID不能为空");
        }
        return getPaymentConfig(tenantId);
    }

    /**
     * 获取微信支付配置
     *
     * @param tenantId 租户ID
     * @return 微信支付配置
     * @throws PaymentException 配置获取失败时抛出
     */
    public Config getWxPayConfig(Integer tenantId) throws PaymentException {
        if (tenantId == null) {
            throw PaymentException.paramError("租户ID不能为空");
        }

        // 先从缓存获取已构建的配置
        Config cachedConfig = WxNativeUtil.getConfig(tenantId);
        if (cachedConfig != null) {
            log.debug("从缓存获取微信支付配置成功，租户ID: {}", tenantId);
            return cachedConfig;
        }

        // 构建新的配置
        Config newConfig = buildWxPayConfig(tenantId);

        // 缓存配置
        WxNativeUtil.addConfig(tenantId, newConfig);
        log.info("微信支付配置创建并缓存成功，租户ID: {}", tenantId);

        return newConfig;
    }

    /**
     * 构建微信支付配置
     */
    private Config buildWxPayConfig(Integer tenantId) throws PaymentException {
        try {
            // 获取支付配置信息
            Payment payment = getPaymentConfig(tenantId);

            // 获取证书文件路径
            String certificatePath = getCertificatePath(tenantId, payment);

            // 创建微信支付配置对象
            return createWxPayConfig(payment, certificatePath);

        } catch (Exception e) {
            if (e instanceof PaymentException) {
                throw e;
            }
            throw PaymentException.systemError("构建微信支付配置失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取支付配置信息
     * 优先从缓存获取，缓存没有则查询数据库，最后兜底到开发环境测试配置
     */
    private Payment getPaymentConfig(Integer tenantId) throws PaymentException {
        String cacheKey = "Payment:wxPay:" + tenantId;
        Payment payment = redisUtil.get(cacheKey, Payment.class);
        System.out.println("payment = " + payment);
        if (payment != null) {
            log.debug("从缓存获取支付配置成功，租户ID: {}", tenantId);
//            return payment;
        }

        // 缓存中没有，尝试从数据库查询
        try {
            final PaymentParam paymentParam = new PaymentParam();
            paymentParam.setType(102);
            paymentParam.setTenantId(tenantId);

            log.debug("查询数据库支付配置，参数: type=102, tenantId={}", tenantId);
            payment = paymentService.getByType(paymentParam);
            log.debug("数据库查询结果: {}", payment != null ? "找到配置" : "未找到配置");

            if (payment != null) {
                log.info("从数据库获取支付配置成功，租户ID: {}，将缓存配置", tenantId);
                // 将查询到的配置缓存起来，缓存1天
                redisUtil.set(cacheKey, payment, 1L, TimeUnit.DAYS);
                return payment;
            } else {
                log.warn("数据库中未找到支付配置，租户ID: {}, type: 102", tenantId);
            }
        } catch (Exception e) {
            log.error("从数据库查询支付配置失败，租户ID: {}，错误: {}", tenantId, e.getMessage(), e);
            // 抛出更详细的异常信息
            throw PaymentException.systemError("查询支付配置失败，租户ID: " + tenantId + "，错误: " + e.getMessage(), e);
        }

        // 数据库也没有配置
        if (!"dev".equals(activeProfile)) {
            throw PaymentException.systemError("微信支付配置未找到，租户ID: " + tenantId + "，请检查数据库配置", null);
        }

        log.debug("开发环境模式，将使用测试配置，租户ID: {}", tenantId);
        // 开发环境返回测试Payment配置
        return createDevTestPayment(tenantId);
    }

    /**
     * 获取证书文件路径
     */
    private String getCertificatePath(Integer tenantId, Payment payment) throws PaymentException {
        if ("dev".equals(activeProfile)) {
            return getDevCertificatePath(tenantId);
        } else {
            return getProdCertificatePath(payment);
        }
    }

    /**
     * 获取开发环境证书路径
     */
    private String getDevCertificatePath(Integer tenantId) throws PaymentException {
        try {
            // 根据租户ID构建证书路径
            String certPath = "dev/wechat/" + tenantId + "/apiclient_key.pem";
            ClassPathResource resource = new ClassPathResource(certPath);

            if (!resource.exists()) {
                throw PaymentException.systemError("开发环境微信支付证书文件不存在: " + certPath, null);
            }

            String absolutePath = resource.getFile().getAbsolutePath();
            log.debug("开发环境证书路径: {}", absolutePath);
            return absolutePath;

        } catch (IOException e) {
            throw PaymentException.systemError("获取开发环境证书路径失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取生产环境证书路径
     */
    private String getProdCertificatePath(Payment payment) throws PaymentException {
        if (payment == null || payment.getApiclientKey() == null || payment.getApiclientKey().trim().isEmpty()) {
            throw PaymentException.systemError("生产环境支付配置或证书密钥文件为空", null);
        }

        try {
            // 使用微信支付证书路径
            String certificatePath = certificateService.getWechatPayCertPath(payment.getApiclientKey());
            if (certificatePath == null) {
                throw PaymentException.systemError("证书文件路径获取失败，证书文件: " + payment.getApiclientKey(), null);
            }

            log.debug("生产环境证书路径: {}", certificatePath);
            return certificatePath;

        } catch (Exception e) {
            throw PaymentException.systemError("获取生产环境证书路径失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建微信支付配置对象
     */
    private Config createWxPayConfig(Payment payment, String certificatePath) throws PaymentException {
        try {
            if ("dev".equals(activeProfile) && payment == null) {
                // 开发环境测试配置
                return createDevTestConfig(certificatePath);
            } else if (payment != null) {
                // 正常配置
                return createNormalConfig(payment, certificatePath);
            } else {
                throw PaymentException.systemError("无法创建微信支付配置：配置信息不完整", null);
            }
        } catch (Exception e) {
            if (e instanceof PaymentException) {
                throw e;
            }
            throw PaymentException.systemError("创建微信支付配置对象失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建开发环境测试Payment配置
     */
    private Payment createDevTestPayment(Integer tenantId) {
        Payment testPayment = new Payment();
        testPayment.setTenantId(tenantId);
        testPayment.setType(102); // Native支付
        testPayment.setAppId("wxa67c676fc445590e"); // 开发环境测试AppID
        testPayment.setMchId("1246610101"); // 开发环境测试商户号
        testPayment.setMerchantSerialNumber("48749613B40AA8F1D768583FC352358E13EB5AF0");
        testPayment.setApiKey(certificateProperties.getWechatPay().getDev().getApiV3Key());
        testPayment.setNotifyUrl("http://frps-10550.s209.websoft.top/api/payment/notify");
        testPayment.setName("微信Native支付-开发环境");
        testPayment.setStatus(true); // 启用

        log.info("创建开发环境测试Payment配置，租户ID: {}, AppID: {}, 商户号: {}",
            tenantId, testPayment.getAppId(), testPayment.getMchId());

        return testPayment;
    }

    /**
     * 创建开发环境测试配置
     */
    private Config createDevTestConfig(String certificatePath) throws PaymentException {
        String testMerchantId = "1246610101";
        String testMerchantSerialNumber = "48749613B40AA8F1D768583FC352358E13EB5AF0";
        String testApiV3Key = certificateProperties.getWechatPay().getDev().getApiV3Key();

        if (testApiV3Key == null || testApiV3Key.trim().isEmpty()) {
            throw PaymentException.systemError("开发环境APIv3密钥未配置", null);
        }

        log.info("使用开发环境测试配置");
        log.debug("测试商户号: {}", testMerchantId);
        log.debug("测试序列号: {}", testMerchantSerialNumber);

        return new RSAAutoCertificateConfig.Builder()
                .merchantId(testMerchantId)
                .privateKeyFromPath(certificatePath)
                .merchantSerialNumber(testMerchantSerialNumber)
                .apiV3Key(testApiV3Key)
                .build();
    }

    /**
     * 创建正常配置
     */
    private Config createNormalConfig(Payment payment, String certificatePath) throws PaymentException {
        // 验证配置完整性
        validatePaymentConfig(payment);

        log.info("使用数据库支付配置");
        log.debug("商户号: {}", payment.getMchId());

        return new RSAAutoCertificateConfig.Builder()
                .merchantId(payment.getMchId())
                .privateKeyFromPath(certificatePath)
                .merchantSerialNumber(payment.getMerchantSerialNumber())
                .apiV3Key(payment.getApiKey())
                .build();
    }

    /**
     * 验证支付配置完整性
     */
    private void validatePaymentConfig(Payment payment) throws PaymentException {
        if (payment == null) {
            throw PaymentException.systemError("支付配置为空", null);
        }

        if (payment.getMchId() == null || payment.getMchId().trim().isEmpty()) {
            throw PaymentException.systemError("商户号(mchId)未配置", null);
        }

        if (payment.getMerchantSerialNumber() == null || payment.getMerchantSerialNumber().trim().isEmpty()) {
            throw PaymentException.systemError("商户证书序列号(merchantSerialNumber)未配置", null);
        }

        if (payment.getApiKey() == null || payment.getApiKey().trim().isEmpty()) {
            throw PaymentException.systemError("APIv3密钥(apiKey)未配置", null);
        }

        if (payment.getApiclientKey() == null || payment.getApiclientKey().trim().isEmpty()) {
            throw PaymentException.systemError("证书文件名(apiclientKey)未配置", null);
        }

        log.debug("支付配置验证通过，租户ID: {}, 商户号: {}", payment.getTenantId(), payment.getMchId());
    }

    /**
     * 清除指定租户的配置缓存
     *
     * @param tenantId 租户ID
     */
    public void clearConfigCache(Integer tenantId) {
        WxNativeUtil.addConfig(tenantId, null);
        log.info("清除微信支付配置缓存，租户ID: {}", tenantId);
    }
}
