package cn.iocoder.yudao.module.system.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;

@Slf4j
public class WechatUtils {
    /**
     * 验证签名
     */
    public static boolean checkSignature(String token, String timestamp, String nonce, String signature) {
        try {
            // 1. 将token、timestamp、nonce三个参数进行字典序排序
            String[] arr = new String[]{token, timestamp, nonce};
            Arrays.sort(arr);

            // 2. 将三个参数字符串拼接成一个字符串
            StringBuilder content = new StringBuilder();
            for (String s : arr) {
                content.append(s);
            }

            // 3. 进行sha1加密
            String encrypted = sha1(content.toString());

            // 4. 将加密后的字符串与signature对比
            return encrypted != null && encrypted.equals(signature);

        } catch (Exception e) {
            log.error("验证签名失败", e);
            return false;
        }
    }

    /**
     * SHA1加密
     */
    public static String sha1(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(str.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);
            }

            return hexString.toString();
        } catch (Exception e) {
            log.error("SHA1加密失败", e);
            return null;
        }
    }

    /**
     * 生成消息签名（用于安全模式）
     */
    public static String generateSignature(String token, String timestamp, String nonce, String encryptedMsg) {
        try {
            String[] arr = new String[]{token, timestamp, nonce, encryptedMsg};
            Arrays.sort(arr);

            StringBuilder sb = new StringBuilder();
            for (String a : arr) {
                sb.append(a);
            }

            return DigestUtils.sha1Hex(sb.toString());
        } catch (Exception e) {
            log.error("生成消息签名失败", e);
            return null;
        }
    }

    /**
     * 从HttpServletRequest中读取请求体
     */
    public static String getRequestBody(HttpServletRequest request) throws IOException {
        StringBuilder sb = new StringBuilder();
        String line;
        try (java.io.BufferedReader reader = request.getReader()) {
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        }
        return sb.toString();
    }

    /**
     * 从XML中解析事件类型
     */
    public static String parseEventType(String xml) {
        try {
            int start = xml.indexOf("<Event>");
            int end = xml.indexOf("</Event>");
            if (start != -1 && end != -1) {
                return xml.substring(start + 7, end);
            }
        } catch (Exception e) {
            log.error("解析事件类型失败", e);
        }
        return "";
    }

    /**
     * 从XML中解析OpenID
     */
    public static String parseOpenId(String xml) {
        try {
            int start = xml.indexOf("<FromUserName>");
            int end = xml.indexOf("</FromUserName>");
            if (start != -1 && end != -1) {
                return xml.substring(start + 14, end);
            }
        } catch (Exception e) {
            log.error("解析OpenID失败", e);
        }
        return "";
    }
}
