package com.example.demo.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.lang.NonNull;

import com.ijpay.alipay.AliPayApiConfig;
import com.ijpay.alipay.AliPayApiConfigKit;

/**
 * 支付配置类
 * 集成IJPay支付模块配置
 * 
 * 初始化IJPay的AliPayApiConfigKit，确保AliPayApi可以正常使用
 */
@Configuration
public class PaymentConfig implements ApplicationListener<ContextRefreshedEvent> {

    private static final Logger logger = LoggerFactory.getLogger(PaymentConfig.class);

    @Bean
    @ConfigurationProperties(prefix = "alipay")
    public AliPayConfig aliPayConfig() {
        return new AliPayConfig();
    }

    /**
     * 初始化IJPay配置
     * 在应用上下文完全初始化后执行，确保所有bean都已创建完成
     */
    @Override
    public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
        // 确保只在根上下文触发时初始化，避免子上下文重复触发
        if (event.getApplicationContext().getParent() != null) {
            return;
        }
        
        // 从ApplicationContext获取已创建的bean（此时所有bean都已创建完成）
        AliPayConfig aliPayConfig;
        try {
            aliPayConfig = event.getApplicationContext().getBean(AliPayConfig.class);
        } catch (Exception e) {
            logger.error("无法从ApplicationContext获取AliPayConfig bean", e);
            return;
        }
        
        try {
            logger.info("=== 初始化IJPay配置 ===");
            
            // 详细的配置验证
            boolean configValid = validateAlipayConfig(aliPayConfig);
            if (!configValid) {
                logger.error("支付宝配置验证失败，请检查配置");
                return;
            }
            
            logger.info("应用ID: {}", aliPayConfig.getAppId());
            logger.info("网关地址: {}", aliPayConfig.getServerUrl());
            logger.info("字符集: {}", aliPayConfig.getCharset());
            logger.info("签名类型: {}", aliPayConfig.getSignType());
            logger.info("通知URL: {}", aliPayConfig.getNotifyUrl());
            logger.info("返回URL: {}", aliPayConfig.getReturnUrl());
            
            // HTTP超时时间已在应用启动时设置（DemoApplication.main方法中）
            // 连接超时：30秒，读取超时：120秒
            logger.info("HTTP超时设置：连接超时30秒，读取超时120秒（已在应用启动时设置）");

            // 构建AliPayApiConfig对象
            // 注意：DefaultAlipayClient会在build()方法中创建，此时会使用上面设置的系统属性
            AliPayApiConfig apiConfig = AliPayApiConfig.builder()
                .setAppId(aliPayConfig.getAppId())
                .setPrivateKey(aliPayConfig.getPrivateKey())
                .setAliPayPublicKey(aliPayConfig.getPublicKey())
                .setServiceUrl(aliPayConfig.getServerUrl())
                .setCharset(aliPayConfig.getCharset() != null ? aliPayConfig.getCharset() : "UTF-8")
                .setSignType(aliPayConfig.getSignType() != null ? aliPayConfig.getSignType() : "RSA2")
                .build();

            // 验证配置中的serviceUrl是否正确
            logger.info("=== 验证IJPay配置中的网关地址 ===");
            logger.info("配置中的serviceUrl: {}", apiConfig.getServiceUrl());
            logger.info("配置中的appId: {}", apiConfig.getAppId());
            
            // 保存配置到静态变量，供AlipayService使用（备用方案）
            AliPayApiConfigHolder.setConfig(apiConfig);
            
            // 设置到AliPayApiConfigKit中，供AliPayApi使用
            // 根据IJPay源码，正确的方法是 putApiConfig
            try {
                AliPayApiConfigKit.putApiConfig(apiConfig);
                logger.info("IJPay配置已成功设置到AliPayApiConfigKit");
                
                // 验证从AliPayApiConfigKit获取的配置
                AliPayApiConfig retrievedConfig = AliPayApiConfigKit.getAliPayApiConfig();
                logger.info("从AliPayApiConfigKit获取的serviceUrl: {}", retrievedConfig.getServiceUrl());
                logger.info("从AliPayApiConfigKit获取的appId: {}", retrievedConfig.getAppId());
                
                logger.info("IJPay配置初始化完成");
            } catch (Exception e) {
                logger.error("设置IJPay配置到AliPayApiConfigKit时发生异常", e);
                // 不抛出异常，允许应用启动，配置将在调用时动态设置
                logger.warn("IJPay配置设置失败，但应用将继续启动，配置将在调用时动态设置");
            }
        } catch (Exception e) {
            logger.error("IJPay配置初始化失败", e);
            // 不抛出异常，允许应用启动，配置将在调用时动态设置
            logger.warn("IJPay配置初始化失败，但应用将继续启动，配置将在调用时动态设置");
        }
    }

    /**
     * 验证支付宝配置
     * @param config 支付宝配置
     * @return 验证结果
     */
    private boolean validateAlipayConfig(AliPayConfig config) {
        logger.info("=== 开始验证支付宝配置 ===");
        
        boolean isValid = true;
        StringBuilder errors = new StringBuilder();
        
        // 1. 验证应用ID
        if (config.getAppId() == null || config.getAppId().isEmpty()) {
            logger.error("❌ 应用ID (app-id) 为空");
            errors.append("应用ID为空; ");
            isValid = false;
        } else {
            // 验证appId格式（应该是16位数字）
            String appId = config.getAppId().trim();
            if (!appId.matches("^\\d{16}$")) {
                logger.warn("⚠️  应用ID格式可能不正确: {} (应该是16位数字)", appId);
            } else {
                logger.info("✅ 应用ID格式正确: {}", appId);
            }
        }
        
        // 2. 验证私钥
        if (config.getPrivateKey() == null || config.getPrivateKey().isEmpty()) {
            logger.error("❌ 应用私钥 (private-key) 为空");
            errors.append("应用私钥为空; ");
            isValid = false;
        } else {
            String privateKey = config.getPrivateKey().trim();
            // 验证私钥格式（RSA私钥通常以BEGIN PRIVATE KEY或BEGIN RSA PRIVATE KEY开头）
            if (!privateKey.startsWith("MII") && !privateKey.contains("BEGIN")) {
                logger.warn("⚠️  私钥格式可能不正确（应该以MII开头或包含BEGIN PRIVATE KEY）");
                logger.debug("私钥前20个字符: {}", privateKey.substring(0, Math.min(20, privateKey.length())));
            }
            // 验证私钥长度（RSA私钥通常至少1000字符）
            if (privateKey.length() < 500) {
                logger.error("❌ 私钥长度过短: {} 字符（RSA私钥通常至少500字符）", privateKey.length());
                errors.append("私钥长度过短; ");
                isValid = false;
            } else {
                logger.info("✅ 私钥长度: {} 字符", privateKey.length());
                // 隐藏敏感信息，只显示前后部分
                String maskedKey = privateKey.substring(0, 20) + "..." + privateKey.substring(privateKey.length() - 20);
                logger.debug("私钥摘要: {}", maskedKey);
            }
        }
        
        // 3. 验证公钥
        if (config.getPublicKey() == null || config.getPublicKey().isEmpty()) {
            logger.error("❌ 支付宝公钥 (public-key) 为空");
            errors.append("支付宝公钥为空; ");
            isValid = false;
        } else {
            String publicKey = config.getPublicKey().trim();
            // 验证公钥格式（RSA公钥通常以MII开头）
            if (!publicKey.startsWith("MII") && !publicKey.contains("BEGIN")) {
                logger.warn("⚠️  公钥格式可能不正确（应该以MII开头或包含BEGIN PUBLIC KEY）");
            }
            // 验证公钥长度（RSA公钥通常至少200字符）
            if (publicKey.length() < 200) {
                logger.error("❌ 公钥长度过短: {} 字符（RSA公钥通常至少200字符）", publicKey.length());
                errors.append("公钥长度过短; ");
                isValid = false;
            } else {
                logger.info("✅ 公钥长度: {} 字符", publicKey.length());
                // 隐藏敏感信息，只显示前后部分
                String maskedKey = publicKey.substring(0, 20) + "..." + publicKey.substring(publicKey.length() - 20);
                logger.debug("公钥摘要: {}", maskedKey);
            }
        }
        
        // 4. 验证网关地址
        if (config.getServerUrl() == null || config.getServerUrl().isEmpty()) {
            logger.error("❌ 网关地址 (server-url) 为空");
            errors.append("网关地址为空; ");
            isValid = false;
        } else {
            String serverUrl = config.getServerUrl().trim();
            if (!serverUrl.startsWith("https://")) {
                logger.error("❌ 网关地址格式不正确: {} (应该以https://开头)", serverUrl);
                errors.append("网关地址格式不正确; ");
                isValid = false;
            } else if (!serverUrl.contains("alipay")) {
                logger.warn("⚠️  网关地址可能不正确: {} (应该包含alipay)", serverUrl);
            } else {
                logger.info("✅ 网关地址: {}", serverUrl);
            }
        }
        
        // 5. 验证字符集
        String charset = config.getCharset();
        if (charset == null || charset.isEmpty()) {
            logger.warn("⚠️  字符集未设置，将使用默认值: UTF-8");
        } else if (!charset.equalsIgnoreCase("UTF-8")) {
            logger.warn("⚠️  字符集不是UTF-8: {} (建议使用UTF-8)", charset);
        } else {
            logger.info("✅ 字符集: {}", charset);
        }
        
        // 6. 验证签名类型
        String signType = config.getSignType();
        if (signType == null || signType.isEmpty()) {
            logger.warn("⚠️  签名类型未设置，将使用默认值: RSA2");
        } else if (!signType.equalsIgnoreCase("RSA2")) {
            logger.warn("⚠️  签名类型不是RSA2: {} (建议使用RSA2)", signType);
        } else {
            logger.info("✅ 签名类型: {}", signType);
        }
        
        // 7. 验证通知URL
        if (config.getNotifyUrl() == null || config.getNotifyUrl().isEmpty()) {
            logger.error("❌ 通知URL (notify-url) 为空");
            errors.append("通知URL为空; ");
            isValid = false;
        } else {
            String notifyUrl = config.getNotifyUrl().trim();
            if (!notifyUrl.startsWith("https://")) {
                logger.error("❌ 通知URL格式不正确: {} (应该以https://开头)", notifyUrl);
                errors.append("通知URL格式不正确; ");
                isValid = false;
            } else {
                logger.info("✅ 通知URL: {}", notifyUrl);
            }
        }
        
        // 8. 验证返回URL
        if (config.getReturnUrl() == null || config.getReturnUrl().isEmpty()) {
            logger.error("❌ 返回URL (return-url) 为空");
            errors.append("返回URL为空; ");
            isValid = false;
        } else {
            String returnUrl = config.getReturnUrl().trim();
            if (!returnUrl.startsWith("https://")) {
                logger.error("❌ 返回URL格式不正确: {} (应该以https://开头)", returnUrl);
                errors.append("返回URL格式不正确; ");
                isValid = false;
            } else {
                logger.info("✅ 返回URL: {}", returnUrl);
            }
        }
        
        // 总结验证结果
        if (isValid) {
            logger.info("=== 支付宝配置验证通过 ===");
        } else {
            logger.error("=== 支付宝配置验证失败 ===");
            logger.error("错误详情: {}", errors.toString());
            logger.error("请检查 application-dev.properties 或 payment.properties 文件中的支付宝配置");
        }
        
        return isValid;
    }
    
    /**
     * IJPay配置持有者
     * 用于保存配置，供AlipayService在调用时动态设置
     */
    public static class AliPayApiConfigHolder {
        private static AliPayApiConfig config;
        
        public static void setConfig(AliPayApiConfig config) {
            AliPayApiConfigHolder.config = config;
        }
        
        public static AliPayApiConfig getConfig() {
            return config;
        }
    }

    /**
     * 支付宝配置
     */
    public static class AliPayConfig {
        private String appId;
        private String privateKey;
        private String publicKey;
        private String serverUrl;
        private String gatewayUrl;
        private String domain;
        private String charset;
        private String signType;
        private String notifyUrl;
        private String returnUrl;
        private String appCertPath;
        private String aliPayCertPath;
        private String aliPayRootCertPath;

        // Getters and Setters
        public String getAppId() { return appId; }
        public void setAppId(String appId) { this.appId = appId; }
        
        public String getPrivateKey() { return privateKey; }
        public void setPrivateKey(String privateKey) { this.privateKey = privateKey; }
        
        public String getPublicKey() { return publicKey; }
        public void setPublicKey(String publicKey) { this.publicKey = publicKey; }
        
        public String getServerUrl() { return serverUrl; }
        public void setServerUrl(String serverUrl) { this.serverUrl = serverUrl; }
        
        public String getGatewayUrl() { return gatewayUrl; }
        public void setGatewayUrl(String gatewayUrl) { this.gatewayUrl = gatewayUrl; }
        
        public String getDomain() { return domain; }
        public void setDomain(String domain) { this.domain = domain; }
        
        public String getCharset() { return charset; }
        public void setCharset(String charset) { this.charset = charset; }
        
        public String getSignType() { return signType; }
        public void setSignType(String signType) { this.signType = signType; }
        
        public String getNotifyUrl() { return notifyUrl; }
        public void setNotifyUrl(String notifyUrl) { this.notifyUrl = notifyUrl; }
        
        public String getReturnUrl() { return returnUrl; }
        public void setReturnUrl(String returnUrl) { this.returnUrl = returnUrl; }
        
        public String getAppCertPath() { return appCertPath; }
        public void setAppCertPath(String appCertPath) { this.appCertPath = appCertPath; }
        
        public String getAliPayCertPath() { return aliPayCertPath; }
        public void setAliPayCertPath(String aliPayCertPath) { this.aliPayCertPath = aliPayCertPath; }
        
        public String getAliPayRootCertPath() { return aliPayRootCertPath; }
        public void setAliPayRootCertPath(String aliPayRootCertPath) { this.aliPayRootCertPath = aliPayRootCertPath; }
    }

}
