package com.gxwebsoft.common.core.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.config.CertificateProperties;
import com.gxwebsoft.common.core.config.ConfigProperties;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.common.system.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 证书健康检查服务
 * 提供证书状态检查和健康监控功能
 *
 * @author 科技小王子
 * @since 2024-07-26
 */
@Slf4j
@Service
public class CertificateHealthService {

    private final CertificateService certificateService;
    private final CertificateProperties certificateProperties;

    @Resource
    private PaymentService paymentService;

    @Resource
    private ConfigProperties configProperties;

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

    public CertificateHealthService(CertificateService certificateService,
                                  CertificateProperties certificateProperties) {
        this.certificateService = certificateService;
        this.certificateProperties = certificateProperties;
    }

    /**
     * 获取当前租户ID
     */
    private Integer getCurrentTenantId() {
        try {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.getPrincipal() instanceof com.gxwebsoft.common.system.entity.User) {
                return ((com.gxwebsoft.common.system.entity.User) authentication.getPrincipal()).getTenantId();
            }
        } catch (Exception e) {
            log.warn("获取当前租户ID失败: {}", e.getMessage());
        }
        return 1; // 默认租户ID
    }

    /**
     * 自定义健康检查结果类
     */
    public static class HealthResult {
        private final String status;
        private final Map<String, Object> details;

        public HealthResult(String status, Map<String, Object> details) {
            this.status = status;
            this.details = details;
        }

        public String getStatus() {
            return status;
        }

        public Map<String, Object> getDetails() {
            return details;
        }

        public static HealthResult up(Map<String, Object> details) {
            return new HealthResult("UP", details);
        }

        public static HealthResult down(Map<String, Object> details) {
            return new HealthResult("DOWN", details);
        }
    }

    public HealthResult health() {
        try {
            Map<String, Object> details = new HashMap<>();
            boolean allHealthy = true;

            // 检查微信支付证书（配置文件模式）
            Map<String, Object> wechatHealth = checkWechatPayCertificates();
            details.put("wechatPay", wechatHealth);
            if (!(Boolean) wechatHealth.get("healthy")) {
                allHealthy = false;
            }

            // 检查支付宝证书（配置文件模式）
            Map<String, Object> alipayHealth = checkAlipayCertificates();
            details.put("alipay", alipayHealth);
            if (!(Boolean) alipayHealth.get("healthy")) {
                allHealthy = false;
            }

            // 检查数据库中的支付配置证书路径
            Map<String, Object> databaseCertHealth = checkDatabaseCertificates();
            details.put("databaseCertificates", databaseCertHealth);
            if (!(Boolean) databaseCertHealth.get("healthy")) {
                allHealthy = false;
            }

            // 添加系统信息
            details.put("loadMode", certificateProperties.getLoadMode());
            details.put("certRootPath", certificateProperties.getCertRootPath());
            details.put("currentEnvironment", active);

            if (allHealthy) {
                return HealthResult.up(details);
            } else {
                return HealthResult.down(details);
            }

        } catch (Exception e) {
            log.error("证书健康检查失败", e);
            Map<String, Object> errorDetails = new HashMap<>();
            errorDetails.put("error", e.getMessage());
            return HealthResult.down(errorDetails);
        }
    }

    /**
     * 检查微信支付证书健康状态
     */
    private Map<String, Object> checkWechatPayCertificates() {
        Map<String, Object> health = new HashMap<>();
        boolean healthy = true;
        Map<String, Object> certificates = new HashMap<>();

        CertificateProperties.WechatPayConfig wechatConfig = certificateProperties.getWechatPay();

        // 检查私钥证书
        String privateKeyFile = wechatConfig.getDev().getPrivateKeyFile();
        boolean privateKeyExists = certificateService.certificateExists("wechat", privateKeyFile);
        certificates.put("privateKey", Map.of(
                "file", privateKeyFile,
                "exists", privateKeyExists,
                "path", certificateService.getWechatPayCertPath(privateKeyFile)
        ));
        if (!privateKeyExists) healthy = false;

        // 检查商户证书
        String apiclientCertFile = wechatConfig.getDev().getApiclientCertFile();
        boolean apiclientCertExists = certificateService.certificateExists("wechat", apiclientCertFile);
        certificates.put("apiclientCert", Map.of(
                "file", apiclientCertFile,
                "exists", apiclientCertExists,
                "path", certificateService.getWechatPayCertPath(apiclientCertFile)
        ));
        if (!apiclientCertExists) healthy = false;

        // 检查微信支付平台证书
        String wechatpayCertFile = wechatConfig.getDev().getWechatpayCertFile();
        boolean wechatpayCertExists = certificateService.certificateExists("wechat", wechatpayCertFile);
        certificates.put("wechatpayCert", Map.of(
                "file", wechatpayCertFile,
                "exists", wechatpayCertExists,
                "path", certificateService.getWechatPayCertPath(wechatpayCertFile)
        ));
        if (!wechatpayCertExists) healthy = false;

        health.put("healthy", healthy);
        health.put("certificates", certificates);
        return health;
    }

    /**
     * 检查支付宝证书健康状态
     */
    private Map<String, Object> checkAlipayCertificates() {
        Map<String, Object> health = new HashMap<>();
        boolean healthy = true;
        Map<String, Object> certificates = new HashMap<>();

        CertificateProperties.AlipayConfig alipayConfig = certificateProperties.getAlipay();

        // 检查应用私钥
        String appPrivateKeyFile = alipayConfig.getAppPrivateKeyFile();
        boolean appPrivateKeyExists = certificateService.certificateExists("alipay", appPrivateKeyFile);
        certificates.put("appPrivateKey", Map.of(
                "file", appPrivateKeyFile,
                "exists", appPrivateKeyExists,
                "path", certificateService.getAlipayCertPath(appPrivateKeyFile)
        ));
        if (!appPrivateKeyExists) healthy = false;

        // 检查应用公钥证书
        String appCertPublicKeyFile = alipayConfig.getAppCertPublicKeyFile();
        boolean appCertExists = certificateService.certificateExists("alipay", appCertPublicKeyFile);
        certificates.put("appCertPublicKey", Map.of(
                "file", appCertPublicKeyFile,
                "exists", appCertExists,
                "path", certificateService.getAlipayCertPath(appCertPublicKeyFile)
        ));
        if (!appCertExists) healthy = false;

        // 检查支付宝公钥证书
        String alipayCertPublicKeyFile = alipayConfig.getAlipayCertPublicKeyFile();
        boolean alipayCertExists = certificateService.certificateExists("alipay", alipayCertPublicKeyFile);
        certificates.put("alipayCertPublicKey", Map.of(
                "file", alipayCertPublicKeyFile,
                "exists", alipayCertExists,
                "path", certificateService.getAlipayCertPath(alipayCertPublicKeyFile)
        ));
        if (!alipayCertExists) healthy = false;

        // 检查支付宝根证书
        String alipayRootCertFile = alipayConfig.getAlipayRootCertFile();
        boolean rootCertExists = certificateService.certificateExists("alipay", alipayRootCertFile);
        certificates.put("alipayRootCert", Map.of(
                "file", alipayRootCertFile,
                "exists", rootCertExists,
                "path", certificateService.getAlipayCertPath(alipayRootCertFile)
        ));
        if (!rootCertExists) healthy = false;

        health.put("healthy", healthy);
        health.put("certificates", certificates);
        return health;
    }

    /**
     * 获取详细的证书诊断信息
     */
    public Map<String, Object> getDiagnosticInfo() {
        Map<String, Object> diagnostic = new HashMap<>();

        try {
            // 基本系统信息
            diagnostic.put("loadMode", certificateProperties.getLoadMode());
            diagnostic.put("certRootPath", certificateProperties.getCertRootPath());
            diagnostic.put("devCertPath", certificateProperties.getDevCertPath());

            // 获取所有证书状态
            diagnostic.put("certificateStatus", certificateService.getAllCertificateStatus());

            // 健康检查结果
            HealthResult health = health();
            diagnostic.put("healthStatus", health.getStatus());
            diagnostic.put("healthDetails", health.getDetails());

        } catch (Exception e) {
            log.error("获取证书诊断信息失败", e);
            diagnostic.put("error", e.getMessage());
        }

        return diagnostic;
    }

    /**
     * 检查特定证书的详细信息
     */
    public Map<String, Object> checkSpecificCertificate(String certType, String fileName) {
        Map<String, Object> result = new HashMap<>();

        try {
            boolean exists = certificateService.certificateExists(certType, fileName);
            String path = certificateService.getCertificateFilePath(certType, fileName);

            result.put("certType", certType);
            result.put("fileName", fileName);
            result.put("exists", exists);
            result.put("path", path);

            if (exists && (fileName.endsWith(".crt") || fileName.endsWith(".pem"))) {
                // 尝试验证证书
                CertificateService.CertificateInfo certInfo =
                    certificateService.validateX509Certificate(certType, fileName);
                result.put("certificateInfo", certInfo);
            }

        } catch (Exception e) {
            log.error("检查证书失败: {}/{}", certType, fileName, e);
            result.put("error", e.getMessage());
        }

        return result;
    }

    /**
     * 检查数据库中存储的证书路径
     */
    public Map<String, Object> checkDatabaseCertificates() {
        Map<String, Object> health = new HashMap<>();
        boolean healthy = true;
        Map<String, Object> certificates = new HashMap<>();

        try {
            Integer tenantId = getCurrentTenantId();
            log.info("检查租户 {} 的数据库证书配置", tenantId);

            // 查询微信支付配置
            List<Payment> wechatPayments = paymentService.list(
                new LambdaQueryWrapper<Payment>()
                    .eq(Payment::getCode, "wxPay")
                    .eq(Payment::getStatus, true)
                    .eq(Payment::getTenantId, tenantId)
            );

            Map<String, Object> wechatDbCerts = new HashMap<>();
            if (!wechatPayments.isEmpty()) {
                Payment wechatPayment = wechatPayments.get(0);
                log.info("找到微信支付配置: 商户号={}, 序列号={}", wechatPayment.getMchId(), wechatPayment.getMerchantSerialNumber());

                // 检查微信支付证书路径
                String apiclientKey = wechatPayment.getApiclientKey();
                String apiclientCert = wechatPayment.getApiclientCert();

                if (apiclientKey != null && !apiclientKey.isEmpty()) {
                    String keyPath = getAbsoluteCertPath(apiclientKey);
                    boolean keyExists = new File(keyPath).exists();
                    wechatDbCerts.put("privateKey", Map.of(
                        "relativePath", apiclientKey,
                        "absolutePath", keyPath,
                        "exists", keyExists
                    ));
                    log.info("微信支付私钥证书 - 相对路径: {}, 绝对路径: {}, 存在: {}", apiclientKey, keyPath, keyExists);
                    if (!keyExists) healthy = false;
                } else {
                    wechatDbCerts.put("privateKey", Map.of("error", "私钥路径未配置"));
                    healthy = false;
                }

                if (apiclientCert != null && !apiclientCert.isEmpty()) {
                    String certPath = getAbsoluteCertPath(apiclientCert);
                    boolean certExists = new File(certPath).exists();
                    wechatDbCerts.put("certificate", Map.of(
                        "relativePath", apiclientCert,
                        "absolutePath", certPath,
                        "exists", certExists
                    ));
                    log.info("微信支付证书 - 相对路径: {}, 绝对路径: {}, 存在: {}", apiclientCert, certPath, certExists);
                    if (!certExists) healthy = false;
                } else {
                    wechatDbCerts.put("certificate", Map.of("error", "证书路径未配置"));
                    healthy = false;
                }

                wechatDbCerts.put("merchantId", wechatPayment.getMchId());
                wechatDbCerts.put("serialNumber", wechatPayment.getMerchantSerialNumber());
                wechatDbCerts.put("apiV3Key", wechatPayment.getApiKey() != null ? "已配置" : "未配置");

            } else {
                wechatDbCerts.put("error", "未找到微信支付配置");
                healthy = false;
                log.warn("租户 {} 未找到微信支付配置", tenantId);
            }

            certificates.put("wechatPay", wechatDbCerts);

            // 查询支付宝配置（如果有的话）
            List<Payment> alipayPayments = paymentService.list(
                new LambdaQueryWrapper<Payment>()
                    .eq(Payment::getCode, "alipay")
                    .eq(Payment::getStatus, true)
                    .eq(Payment::getTenantId, tenantId)
            );

            Map<String, Object> alipayDbCerts = new HashMap<>();
            if (!alipayPayments.isEmpty()) {
                Payment alipayPayment = alipayPayments.get(0);
                log.info("找到支付宝配置: 应用ID={}", alipayPayment.getAppId());

                // 这里可以添加支付宝证书路径检查逻辑
                alipayDbCerts.put("appId", alipayPayment.getAppId());
                alipayDbCerts.put("status", "支付宝配置存在，但证书路径检查需要根据具体字段实现");
            } else {
                alipayDbCerts.put("status", "未找到支付宝配置");
                log.info("租户 {} 未找到支付宝配置", tenantId);
            }

            certificates.put("alipay", alipayDbCerts);

        } catch (Exception e) {
            log.error("检查数据库证书配置失败", e);
            certificates.put("error", e.getMessage());
            healthy = false;
        }

        health.put("healthy", healthy);
        health.put("certificates", certificates);
        return health;
    }

    /**
     * 获取证书的完整绝对路径
     */
    private String getAbsoluteCertPath(String relativePath) {
        if (relativePath == null || relativePath.isEmpty()) {
            return "";
        }

        // 如果是生产环境，证书存储在上传目录
        if (!"dev".equals(active)) {
            String uploadPath = configProperties.getUploadPath();
            // 修改路径拼接规则：uploadPath + "file" + 数据库存储的相对路径
            String fullPath = uploadPath + "file" + relativePath;
            log.debug("生产环境证书路径构建 - 上传根路径: {}, 相对路径: {}, 完整路径: {}",
                     uploadPath, relativePath, fullPath);
            return fullPath;
        } else {
            // 开发环境，可能需要不同的处理逻辑
            log.debug("开发环境证书路径: {}", relativePath);
            return relativePath;
        }
    }
}
