package com.gxwebsoft.common.core.utils;

import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.system.entity.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

/**
 * 微信支付证书修复工具
 * 自动检测和修复常见的证书配置问题
 * 
 * @author 科技小王子
 * @since 2025-07-29
 */
@Slf4j
@Component
public class WechatPayCertificateFixer {

    private final CertificateProperties certConfig;
    private final CertificateLoader certificateLoader;

    public WechatPayCertificateFixer(CertificateProperties certConfig, CertificateLoader certificateLoader) {
        this.certConfig = certConfig;
        this.certificateLoader = certificateLoader;
    }

    /**
     * 自动修复证书配置问题
     * 
     * @param payment 支付配置
     * @param tenantId 租户ID
     * @param environment 环境
     * @return 修复结果
     */
    public FixResult autoFixCertificateIssues(Payment payment, Integer tenantId, String environment) {
        FixResult result = new FixResult();
        
        log.info("开始自动修复租户 {} 的证书配置问题", tenantId);
        
        try {
            // 1. 检查并修复基本配置
            fixBasicConfiguration(payment, result);
            
            // 2. 检查并修复证书文件问题
            fixCertificateFiles(payment, tenantId, environment, result);
            
            // 3. 检查并修复序列号问题
            fixSerialNumberIssues(payment, tenantId, environment, result);
            
            // 4. 生成修复建议
            generateFixRecommendations(result);
            
        } catch (Exception e) {
            result.addError("修复过程中发生异常: " + e.getMessage());
            log.error("证书修复异常", e);
        }
        
        log.info("证书配置修复完成，成功修复 {} 个问题", result.getFixedIssues().size());
        return result;
    }

    /**
     * 修复基本配置问题
     */
    private void fixBasicConfiguration(Payment payment, FixResult result) {
        if (payment == null) {
            result.addError("支付配置为空，无法修复");
            return;
        }
        
        // 检查商户号
        if (payment.getMchId() == null || payment.getMchId().trim().isEmpty()) {
            result.addError("商户号未配置，需要手动设置");
        }
        
        // 检查应用ID
        if (payment.getAppId() == null || payment.getAppId().trim().isEmpty()) {
            result.addError("应用ID未配置，需要手动设置");
        }
        
        // 检查APIv3密钥
        if (payment.getApiKey() == null || payment.getApiKey().trim().isEmpty()) {
            result.addWarning("APIv3密钥未配置，将使用配置文件默认值");
        } else if (payment.getApiKey().length() != 32) {
            result.addError("APIv3密钥长度错误，应为32位，实际为: " + payment.getApiKey().length());
        }
        
        // 检查商户证书序列号
        if (payment.getMerchantSerialNumber() == null || payment.getMerchantSerialNumber().trim().isEmpty()) {
            result.addError("商户证书序列号未配置，需要手动设置");
        }
    }

    /**
     * 修复证书文件问题
     */
    private void fixCertificateFiles(Payment payment, Integer tenantId, String environment, FixResult result) {
        if ("dev".equals(environment)) {
            fixDevCertificateFiles(tenantId, result);
        } else {
            fixProdCertificateFiles(payment, result);
        }
    }

    /**
     * 修复开发环境证书文件问题
     */
    private void fixDevCertificateFiles(Integer tenantId, FixResult result) {
        String tenantCertPath = "dev/wechat/" + tenantId;
        String privateKeyPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getPrivateKeyFile();
        String apiclientCertPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getApiclientCertFile();
        
        // 检查私钥文件
        if (!certificateLoader.certificateExists(privateKeyPath)) {
            result.addError("私钥文件不存在: " + privateKeyPath);
            result.addRecommendation("请将 apiclient_key.pem 文件放置到 src/main/resources/" + privateKeyPath);
        } else {
            result.addFixed("私钥文件存在: " + privateKeyPath);
            
            // 尝试加载私钥文件
            try {
                String privateKeyFile = certificateLoader.loadCertificatePath(privateKeyPath);
                result.addFixed("私钥文件加载成功: " + privateKeyFile);
            } catch (Exception e) {
                result.addError("私钥文件加载失败: " + e.getMessage());
            }
        }
        
        // 检查商户证书文件（可选）
        if (!certificateLoader.certificateExists(apiclientCertPath)) {
            result.addWarning("商户证书文件不存在: " + apiclientCertPath + " (自动证书配置不需要此文件)");
        } else {
            result.addFixed("商户证书文件存在: " + apiclientCertPath);
        }
    }

    /**
     * 修复生产环境证书文件问题
     */
    private void fixProdCertificateFiles(Payment payment, FixResult result) {
        if (payment.getApiclientKey() == null || payment.getApiclientKey().trim().isEmpty()) {
            result.addError("生产环境私钥文件路径未配置");
        } else {
            result.addFixed("生产环境私钥文件路径已配置: " + payment.getApiclientKey());
        }
        
        if (payment.getApiclientCert() == null || payment.getApiclientCert().trim().isEmpty()) {
            result.addWarning("生产环境商户证书文件路径未配置 (自动证书配置不需要此文件)");
        } else {
            result.addFixed("生产环境商户证书文件路径已配置: " + payment.getApiclientCert());
        }
    }

    /**
     * 修复序列号问题
     */
    private void fixSerialNumberIssues(Payment payment, Integer tenantId, String environment, FixResult result) {
        if (payment.getMerchantSerialNumber() == null || payment.getMerchantSerialNumber().trim().isEmpty()) {
            result.addError("商户证书序列号未配置");
            return;
        }
        
        // 在开发环境中，尝试从证书文件中提取序列号进行验证
        if ("dev".equals(environment)) {
            try {
                String tenantCertPath = "dev/wechat/" + tenantId;
                String apiclientCertPath = tenantCertPath + "/" + certConfig.getWechatPay().getDev().getApiclientCertFile();
                
                if (certificateLoader.certificateExists(apiclientCertPath)) {
                    String actualCertPath = certificateLoader.loadCertificatePath(apiclientCertPath);
                    
                    try (InputStream inputStream = new FileInputStream(new File(actualCertPath))) {
                        CertificateFactory cf = CertificateFactory.getInstance("X.509");
                        X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
                        
                        if (cert != null) {
                            String actualSerialNumber = cert.getSerialNumber().toString(16).toUpperCase();
                            String configuredSerialNumber = payment.getMerchantSerialNumber();
                            
                            if (!configuredSerialNumber.equalsIgnoreCase(actualSerialNumber)) {
                                result.addError("证书序列号不匹配! 配置: " + configuredSerialNumber + ", 实际: " + actualSerialNumber);
                                result.addRecommendation("建议将商户证书序列号更新为: " + actualSerialNumber);
                            } else {
                                result.addFixed("证书序列号匹配: " + actualSerialNumber);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                result.addWarning("无法验证证书序列号: " + e.getMessage());
            }
        }
    }

    /**
     * 生成修复建议
     */
    private void generateFixRecommendations(FixResult result) {
        if (result.hasErrors()) {
            result.addRecommendation("=== 修复建议 ===");
            
            if (result.getErrors().stream().anyMatch(e -> e.contains("商户号"))) {
                result.addRecommendation("1. 请在微信商户平台获取商户号并在系统中配置");
            }
            
            if (result.getErrors().stream().anyMatch(e -> e.contains("应用ID"))) {
                result.addRecommendation("2. 请在微信开放平台获取应用ID并在系统中配置");
            }
            
            if (result.getErrors().stream().anyMatch(e -> e.contains("APIv3密钥"))) {
                result.addRecommendation("3. 请在微信商户平台设置32位APIv3密钥");
            }
            
            if (result.getErrors().stream().anyMatch(e -> e.contains("证书序列号"))) {
                result.addRecommendation("4. 请在微信商户平台查看正确的商户证书序列号");
            }
            
            if (result.getErrors().stream().anyMatch(e -> e.contains("私钥文件"))) {
                result.addRecommendation("5. 请从微信商户平台下载私钥文件并放置到正确位置");
            }
            
            result.addRecommendation("6. 建议使用RSAAutoCertificateConfig自动证书配置");
            result.addRecommendation("7. 确保在微信商户平台开启API安全功能");
        }
    }

    /**
     * 修复结果类
     */
    public static class FixResult {
        private final List<String> errors = new ArrayList<>();
        private final List<String> warnings = new ArrayList<>();
        private final List<String> fixedIssues = new ArrayList<>();
        private final List<String> recommendations = new ArrayList<>();

        public void addError(String error) {
            errors.add(error);
        }

        public void addWarning(String warning) {
            warnings.add(warning);
        }

        public void addFixed(String fixed) {
            fixedIssues.add(fixed);
        }

        public void addRecommendation(String recommendation) {
            recommendations.add(recommendation);
        }

        public boolean hasErrors() {
            return !errors.isEmpty();
        }

        public List<String> getErrors() {
            return errors;
        }

        public List<String> getWarnings() {
            return warnings;
        }

        public List<String> getFixedIssues() {
            return fixedIssues;
        }

        public List<String> getRecommendations() {
            return recommendations;
        }

        public String getFullReport() {
            StringBuilder report = new StringBuilder();
            report.append("=== 微信支付证书修复报告 ===\n\n");
            
            if (!fixedIssues.isEmpty()) {
                report.append("✅ 已修复的问题:\n");
                fixedIssues.forEach(issue -> report.append("  - ").append(issue).append("\n"));
                report.append("\n");
            }
            
            if (!warnings.isEmpty()) {
                report.append("⚠️ 警告:\n");
                warnings.forEach(warning -> report.append("  - ").append(warning).append("\n"));
                report.append("\n");
            }
            
            if (!errors.isEmpty()) {
                report.append("❌ 需要手动修复的问题:\n");
                errors.forEach(error -> report.append("  - ").append(error).append("\n"));
                report.append("\n");
            }
            
            if (!recommendations.isEmpty()) {
                report.append("💡 修复建议:\n");
                recommendations.forEach(rec -> report.append("  ").append(rec).append("\n"));
                report.append("\n");
            }
            
            report.append("=== 修复报告结束 ===");
            return report.toString();
        }
    }
}
