package com.dora.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import jakarta.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * Servlet适配器
 * 用于解决jakarta.servlet和javax.servlet的兼容性问题
 */
@Slf4j
@Component
public class ServletAdapter {

    /**
     * 将jakarta.servlet.HttpServletRequest转换为Map
     * 这样可以避免直接传递HttpServletRequest对象
     */
    public Map<String, String> convertRequestToMap(HttpServletRequest request) {
        Map<String, String> requestMap = new HashMap<>();
        
        try {
            // 获取所有请求参数
            Enumeration<String> paramNames = request.getParameterNames();
            while (paramNames.hasMoreElements()) {
                String paramName = paramNames.nextElement();
                String paramValue = request.getParameter(paramName);
                requestMap.put(paramName, paramValue);
            }
            
            // 获取请求体内容（XML格式）
            String requestBody = getRequestBody(request);
            if (requestBody != null && !requestBody.trim().isEmpty()) {
                requestMap.put("_requestBody", requestBody);
                
                // 解析XML内容到Map中
                parseXmlToMap(requestBody, requestMap);
            }
            
            // 添加一些基本信息
            requestMap.put("_method", request.getMethod());
            requestMap.put("_requestURI", request.getRequestURI());
            requestMap.put("_remoteAddr", request.getRemoteAddr());
            
            log.debug("转换请求参数完成，共{}个参数", requestMap.size());
            
        } catch (Exception e) {
            log.error("转换请求参数时发生错误: {}", e.getMessage(), e);
        }
        
        return requestMap;
    }
    
    /**
     * 获取请求体内容
     */
    private String getRequestBody(HttpServletRequest request) {
        try {
            InputStream inputStream = request.getInputStream();
            if (inputStream == null) {
                return null;
            }
            
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            return sb.toString();
            
        } catch (IOException e) {
            log.error("读取请求体时发生错误: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 解析XML内容到Map中
     */
    private void parseXmlToMap(String xml, Map<String, String> map) {
        try {
            if (xml == null || xml.trim().isEmpty()) {
                return;
            }
            
            // 使用正则表达式解析XML，支持CDATA和普通标签
            java.util.regex.Pattern cdataPattern = java.util.regex.Pattern.compile("<(\\w+)><!\\[CDATA\\[([^\\]]+)\\]\\]></\\1>");
            java.util.regex.Pattern normalPattern = java.util.regex.Pattern.compile("<(\\w+)>([^<]+)</\\1>");
            
            // 解析CDATA标签
            java.util.regex.Matcher cdataMatcher = cdataPattern.matcher(xml);
            while (cdataMatcher.find()) {
                String tagName = cdataMatcher.group(1);
                String value = cdataMatcher.group(2);
                map.put(tagName, value);
                log.debug("解析XML CDATA字段: {} = {}", tagName, value);
            }
            
            // 解析普通标签
            java.util.regex.Matcher normalMatcher = normalPattern.matcher(xml);
            while (normalMatcher.find()) {
                String tagName = normalMatcher.group(1);
                String value = normalMatcher.group(2);
                if (!map.containsKey(tagName)) { // 避免覆盖CDATA解析的结果
                    map.put(tagName, value);
                    log.debug("解析XML普通字段: {} = {}", tagName, value);
                }
            }
            
        } catch (Exception e) {
            log.error("解析XML时发生错误: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 验证微信支付回调签名
     * 这里实现一个简单的签名验证逻辑
     */
    public boolean verifyWxPayCallback(Map<String, String> requestMap, String mchKey) {
        try {
            // 获取微信返回的签名
            String sign = requestMap.get("sign");
            if (sign == null || sign.trim().isEmpty()) {
                log.warn("微信回调缺少签名");
                return false;
            }
            
            // 移除签名字段，重新计算签名
            Map<String, String> signMap = new HashMap<>(requestMap);
            signMap.remove("sign");
            
            // 按照微信支付规则重新计算签名
            String calculatedSign = calculateWxPaySign(signMap, mchKey);
            
            boolean isValid = sign.equalsIgnoreCase(calculatedSign);
            log.info("微信回调签名验证: {}", isValid ? "通过" : "失败");
            
            return isValid;
            
        } catch (Exception e) {
            log.error("验证微信支付回调签名时发生错误: {}", e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 计算微信支付签名
     */
    private String calculateWxPaySign(Map<String, String> params, String mchKey) {
        try {
            // 按照微信支付规则排序参数
            StringBuilder sb = new StringBuilder();
            
            // 过滤空值并排序
            params.entrySet().stream()
                .filter(entry -> entry.getValue() != null && !entry.getValue().trim().isEmpty())
                .filter(entry -> !entry.getKey().startsWith("_")) // 排除我们添加的内部字段
                .sorted(Map.Entry.comparingByKey())
                .forEach(entry -> {
                    sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
                });
            
            // 添加商户密钥
            sb.append("key=").append(mchKey);
            
            // 计算MD5
            String signStr = sb.toString();
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(signStr.getBytes(StandardCharsets.UTF_8));
            
            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : digest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            String md5Sign = hexString.toString().toUpperCase();
            
            log.debug("签名计算: {} -> {}", signStr, md5Sign);
            return md5Sign;
            
        } catch (Exception e) {
            log.error("计算微信支付签名时发生错误: {}", e.getMessage(), e);
            return "";
        }
    }
} 