package com.gxwebsoft.common.core.controller;

import com.gxwebsoft.common.core.utils.WechatPayCertificateDiagnostic;
import com.gxwebsoft.common.core.utils.WechatPayConfigChecker;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.system.entity.Payment;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付诊断控制器
 * 用于诊断和解决微信支付证书相关问题
 *
 * @author 科技小王子
 * @since 2025-07-29
 */
@Slf4j
@RestController
@RequestMapping("/system/wechat-pay-diagnostic")
@Tag(name = "微信支付诊断", description = "微信支付证书诊断和问题排查")
public class WechatPayDiagnosticController extends com.gxwebsoft.common.core.web.BaseController {

    @Autowired
    private WechatPayCertificateDiagnostic certificateDiagnostic;

    @Autowired
    private com.gxwebsoft.common.core.service.PaymentCacheService paymentCacheService;

    @Autowired
    private WechatPayConfigChecker configChecker;

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

    @Operation(summary = "诊断租户微信支付证书配置")
    @GetMapping("/diagnose/{tenantId}")
    @PreAuthorize("hasAuthority('system:payment:view')")
    public ApiResult<Map<String, Object>> diagnoseTenantCertificate(
            @Parameter(description = "租户ID", example = "10550") @PathVariable Integer tenantId) {

        try {
            log.info("开始诊断租户 {} 的微信支付证书配置", tenantId);

            // 获取支付配置 (微信支付类型为0)
            Payment payment = paymentCacheService.getWechatPayConfig(tenantId);
            if (payment == null) {
                Map<String, Object> errorResponse = new HashMap<>();
                errorResponse.put("tenantId", tenantId);
                errorResponse.put("error", "支付配置不存在");
                return fail("租户 " + tenantId + " 的微信支付配置不存在", errorResponse);
            }

            // 执行诊断
            WechatPayCertificateDiagnostic.DiagnosticResult result =
                certificateDiagnostic.diagnoseCertificateConfig(payment, tenantId, activeProfile);

            Map<String, Object> response = new HashMap<>();
            response.put("tenantId", tenantId);
            response.put("environment", activeProfile);
            response.put("hasErrors", result.hasErrors());
            response.put("errors", result.getErrors());
            response.put("warnings", result.getWarnings());
            response.put("info", result.getInfo());
            response.put("recommendations", result.getRecommendations());
            response.put("fullReport", result.getFullReport());

            if (result.hasErrors()) {
                return fail("诊断发现问题", response);
            } else {
                return success("诊断完成", response);
            }

        } catch (Exception e) {
            log.error("诊断租户 {} 证书配置时发生异常", tenantId, e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("tenantId", tenantId);
            errorResponse.put("exception", e.getMessage());
            return fail("诊断过程中发生异常: " + e.getMessage(), errorResponse);
        }
    }

    @Operation(summary = "获取证书问题解决方案")
    @GetMapping("/solutions")
    @PreAuthorize("hasAuthority('system:payment:view')")
    public ApiResult<Map<String, Object>> getCertificateSolutions() {
        Map<String, Object> solutions = new HashMap<>();

        solutions.put("commonIssues", Map.of(
            "X509Certificate.getSerialNumber() null", "证书对象为空，通常是自动证书配置失败导致",
            "404错误", "商户平台未开启API安全功能或未申请使用微信支付公钥",
            "证书序列号错误", "请检查商户平台中的证书序列号是否正确",
            "APIv3密钥错误", "请确认APIv3密钥是否正确设置",
            "私钥文件不存在", "请检查私钥文件路径是否正确",
            "网络连接问题", "请检查网络连接是否正常"
        ));

        solutions.put("stepByStepSolutions", Map.of(
            "开启API安全", "登录微信商户平台 -> 账户中心 -> API安全 -> 申请使用微信支付公钥",
            "获取证书序列号", "在API安全页面查看或重新下载证书",
            "设置APIv3密钥", "在API安全页面设置APIv3密钥（32位字符串）",
            "检查私钥文件", "确保apiclient_key.pem文件存在且路径正确",
            "使用自动证书配置", "推荐使用RSAAutoCertificateConfig，可自动管理平台证书"
        ));

        solutions.put("configurationAdvice", Map.of(
            "开发环境", "证书文件放在 src/main/resources/dev/wechat/{tenantId}/ 目录下",
            "生产环境", "证书文件放在 Docker 挂载卷或指定的文件系统路径",
            "证书文件要求", "需要 apiclient_key.pem（私钥）和 apiclient_cert.pem（商户证书）",
            "自动配置优势", "无需手动管理微信支付平台证书，自动下载和更新"
        ));

        solutions.put("troubleshootingSteps", new String[]{
            "1. 检查商户平台是否已开启API安全功能",
            "2. 确认已申请使用微信支付公钥",
            "3. 验证商户证书序列号是否正确",
            "4. 检查APIv3密钥是否为32位字符串",
            "5. 确认私钥文件路径正确且文件存在",
            "6. 测试网络连接是否正常",
            "7. 查看详细错误日志进行进一步诊断"
        });

        return success("获取解决方案成功", solutions);
    }

    @Operation(summary = "测试证书配置")
    @PostMapping("/test/{tenantId}")
    @PreAuthorize("hasAuthority('system:payment:edit')")
    public ApiResult<Map<String, Object>> testCertificateConfig(
            @Parameter(description = "租户ID", example = "10550") @PathVariable Integer tenantId) {

        try {
            log.info("开始测试租户 {} 的证书配置", tenantId);

            // 获取支付配置 (微信支付类型为0)
            Payment payment = paymentCacheService.getWechatPayConfig(tenantId);
            if (payment == null) {
                Map<String, Object> errorResponse = new HashMap<>();
                errorResponse.put("tenantId", tenantId);
                errorResponse.put("error", "支付配置不存在");
                return fail("租户 " + tenantId + " 的微信支付配置不存在", errorResponse);
            }

            // 执行诊断
            WechatPayCertificateDiagnostic.DiagnosticResult result =
                certificateDiagnostic.diagnoseCertificateConfig(payment, tenantId, activeProfile);

            Map<String, Object> testResult = new HashMap<>();
            testResult.put("tenantId", tenantId);
            testResult.put("configurationValid", !result.hasErrors());
            testResult.put("testTime", System.currentTimeMillis());
            testResult.put("environment", activeProfile);

            if (result.hasErrors()) {
                testResult.put("status", "FAILED");
                testResult.put("errors", result.getErrors());
                testResult.put("recommendations", result.getRecommendations());
                return fail("证书配置测试失败", testResult);
            } else {
                testResult.put("status", "SUCCESS");
                testResult.put("message", "证书配置正常");
                return success("证书配置测试通过", testResult);
            }

        } catch (Exception e) {
            log.error("测试租户 {} 证书配置时发生异常", tenantId, e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("tenantId", tenantId);
            errorResponse.put("exception", e.getMessage());
            return fail("测试过程中发生异常: " + e.getMessage(), errorResponse);
        }
    }

    @Operation(summary = "获取环境信息")
    @GetMapping("/environment")
    @PreAuthorize("hasAuthority('system:payment:view')")
    public ApiResult<Map<String, Object>> getEnvironmentInfo() {
        Map<String, Object> envInfo = new HashMap<>();
        envInfo.put("activeProfile", activeProfile);
        envInfo.put("javaVersion", System.getProperty("java.version"));
        envInfo.put("osName", System.getProperty("os.name"));
        envInfo.put("userDir", System.getProperty("user.dir"));
        envInfo.put("timestamp", System.currentTimeMillis());

        return success("获取环境信息成功", envInfo);
    }

    @Operation(summary = "获取证书配置指南")
    @GetMapping("/guide")
    public ApiResult<Map<String, Object>> getCertificateGuide() {
        Map<String, Object> guide = new HashMap<>();

        guide.put("overview", "微信支付证书配置完整指南");

        guide.put("prerequisites", new String[]{
            "1. 拥有微信支付商户账号",
            "2. 已完成商户入驻和资质审核",
            "3. 具备开发者权限"
        });

        guide.put("merchantPlatformSteps", new String[]{
            "1. 登录微信商户平台 (pay.weixin.qq.com)",
            "2. 进入【账户中心】->【API安全】",
            "3. 点击【申请使用微信支付公钥】",
            "4. 下载商户证书（apiclient_cert.pem 和 apiclient_key.pem）",
            "5. 设置APIv3密钥（32位字符串）",
            "6. 记录商户证书序列号"
        });

        guide.put("developmentSetup", new String[]{
            "1. 在项目中创建证书目录：src/main/resources/dev/wechat/{tenantId}/",
            "2. 将 apiclient_key.pem 放入该目录",
            "3. 将 apiclient_cert.pem 放入该目录（可选，自动配置不需要）",
            "4. 在数据库中配置支付信息：商户号、应用ID、证书序列号、APIv3密钥"
        });

        guide.put("productionSetup", new String[]{
            "1. 将证书文件上传到服务器指定目录",
            "2. 确保应用有读取证书文件的权限",
            "3. 在数据库中配置正确的证书文件路径",
            "4. 测试证书配置是否正常"
        });

        guide.put("bestPractices", new String[]{
            "1. 使用RSAAutoCertificateConfig自动证书配置",
            "2. 定期检查证书有效期",
            "3. 妥善保管私钥文件",
            "4. 使用HTTPS传输敏感信息",
            "5. 定期更新微信支付SDK版本"
        });

        return success("获取配置指南成功", guide);
    }

    @Operation(summary = "快速检查租户配置状态")
    @GetMapping("/check/{tenantId}")
    @PreAuthorize("hasAuthority('system:payment:view')")
    public ApiResult<Map<String, Object>> quickCheckConfig(
            @Parameter(description = "租户ID", example = "10547") @PathVariable Integer tenantId) {

        try {
            log.info("快速检查租户 {} 的配置状态", tenantId);

            WechatPayConfigChecker.ConfigStatus status = configChecker.checkTenantConfig(tenantId);

            Map<String, Object> response = new HashMap<>();
            response.put("tenantId", status.tenantId);
            response.put("environment", status.environment);
            response.put("configMode", status.configMode);
            response.put("configComplete", status.configComplete);
            response.put("hasError", status.hasError);
            response.put("errorMessage", status.errorMessage);
            response.put("recommendation", status.recommendation);
            response.put("issues", status.issues);

            // 详细配置信息
            Map<String, Object> configDetails = new HashMap<>();
            configDetails.put("merchantId", status.merchantId);
            configDetails.put("appId", status.appId);
            configDetails.put("serialNumber", status.serialNumber);
            configDetails.put("hasApiKey", status.hasApiKey);
            configDetails.put("apiKeyLength", status.apiKeyLength);
            configDetails.put("hasPublicKey", status.hasPublicKey);
            configDetails.put("publicKeyFile", status.publicKeyFile);
            configDetails.put("publicKeyId", status.publicKeyId);
            configDetails.put("publicKeyExists", status.publicKeyExists);
            configDetails.put("privateKeyExists", status.privateKeyExists);
            configDetails.put("merchantCertExists", status.merchantCertExists);
            response.put("configDetails", configDetails);

            if (status.hasError || !status.configComplete) {
                return fail("配置检查发现问题", response);
            } else {
                return success("配置检查通过", response);
            }

        } catch (Exception e) {
            log.error("检查租户 {} 配置状态时发生异常", tenantId, e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("tenantId", tenantId);
            errorResponse.put("exception", e.getMessage());
            return fail("检查过程中发生异常: " + e.getMessage(), errorResponse);
        }
    }

    @Operation(summary = "获取配置建议")
    @GetMapping("/advice/{tenantId}")
    @PreAuthorize("hasAuthority('system:payment:view')")
    public ApiResult<Map<String, Object>> getConfigAdvice(
            @Parameter(description = "租户ID", example = "10547") @PathVariable Integer tenantId) {

        try {
            String advice = configChecker.generateConfigAdvice(tenantId);

            Map<String, Object> response = new HashMap<>();
            response.put("tenantId", tenantId);
            response.put("advice", advice);
            response.put("timestamp", System.currentTimeMillis());

            return success("获取配置建议成功", response);

        } catch (Exception e) {
            log.error("获取租户 {} 配置建议时发生异常", tenantId, e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("tenantId", tenantId);
            errorResponse.put("exception", e.getMessage());
            return fail("获取建议过程中发生异常: " + e.getMessage(), errorResponse);
        }
    }
}
