package com.search.supersearch.util;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.http.Header;
import org.apache.http.message.BasicHeader;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 喜欢番茄火锅
 * @date 2023/11/7 10:01
 */
public class WpsUtil {
    /**
     * 按照文档中台的要求构造WPS-4签名
     *
     * @param ak_str  AK
     * @param sk_str  SK
     * @param content GET传URI，POST传Body
     * @return 返回符合要求的Header List
     * @throws Exception
     */
    public static List<Header> configOpendocAPIHeader_WPS4(String ak_str, String sk_str, String content, String url_str, String httpMethod) {
        List<Header> headerList = new ArrayList<>();
        // 设置 Content-Type: 目前固定为: application/json
        String contentType = "application/json";
        headerList.add(new BasicHeader("Content-Type", contentType));
        // 设置 Wps-Docs-Date： RFC1123格式当前时间
        SimpleDateFormat format = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String dateString = String.format("%s %s", format.format(new Date()), "GMT");
        headerList.add(new BasicHeader("Wps-Docs-Date", dateString));
        // 设置 Wps-Authorization："WPS-4 $access_key:$Signature"
        // 设置HTTP Body中数据的sha256值十六进制表达方式，如果body为空，则取"";
        String httpBody_sha256 = "";
        if (StringUtils.isBlank(content)) {
            httpBody_sha256 = "";
        } else {
            httpBody_sha256 = getSHA256StrJava(content);
        }

        // WPS-4的签名规则如下：
        // Signature：hmac-sha256(secret_key, Ver + HttpMethod + URI + Content-Ty+ Wps-Date + sha256(HttpBody))
        String signature = sha256_HMAC(sk_str, String.format("WPS-4%s%s%s%s%s", httpMethod, url_str, contentType, dateString, httpBody_sha256));
        headerList.add(new BasicHeader("Wps-Docs-Authorization", String.format("WPS-4 %s:%s", ak_str, signature)));
        return headerList;
    }

    /**
     * 工具类：sha256_HMAC加密
     *
     * @param secret  秘钥
     * @param message 消息
     * @return 加密后字符串
     */
    private static String sha256_HMAC(String secret, String message) {
        String hash = "";
        try {
            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);
            byte[] bytes = sha256_HMAC.doFinal(message.getBytes());
            hash = byteArrayToHexString(bytes);
            System.out.println(hash);
        } catch (Exception e) {
            System.out.println("Error HmacSHA256 ===========" + e.getMessage());
        }
        return hash;
    }

    /**
     * 工具类：将加密后的字节数组转换成字符串
     *
     * @param b 字节数组
     * @return 字符串
     */
    private static String byteArrayToHexString(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp;
        for (int n = 0; b != null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1) {
                hs.append('0');
            }
            hs.append(stmp);
        }
        return hs.toString().toLowerCase();
    }

    /**
     * 利用java原生的摘要实现SHA256加密
     *
     * @param str 加密后的报文
     * @return
     */
    public static String getSHA256StrJava(String str) {
        MessageDigest messageDigest;
        String encodeStr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(str.getBytes(StandardCharsets.UTF_8));
            encodeStr = byte2Hex(messageDigest.digest());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return encodeStr.toLowerCase();
    }

    /**
     * 工具类：将byte转为16进制
     *
     * @param bytes
     * @return
     */
    private static String byte2Hex(byte[] bytes) {
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i = 0; i < bytes.length; i++) {
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length() == 1) {
//1得到一位的进行补0操作
                stringBuffer.append("0");
            }
            stringBuffer.append(temp);
        }
        return stringBuffer.toString();
    }
}
