package com.sifang.modules.ginlang.utils;

import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.itextpdf.text.pdf.codec.Base64;
import com.sifang.modules.ginlang.constant.GinLangConstan;
import org.slf4j.LoggerFactory;

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

/**
 * 锦浪云接口公共类
 * auth:祁军亮
 */
public class GinLangUtils {
    private static final org.slf4j.Logger log = LoggerFactory.getLogger(GinLangUtils.class);

    /**
     * 编码格式
     */
    private static String HMAC_SHA1 = "HmacSHA1";


    /**
     * 锦浪云加密body
     * @param test
     * @return
     */
    private static String getDigest(String test) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(test.getBytes());
            byte[] b = md.digest();
            return Base64.encodeBytes(b);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }




    /**
     * 使用 MD5算法加密生成32位md5码
     * @param str
     * @return
     */
    public static String string2MD5(String str) {
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(
                    str.getBytes());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有md5这个算法！");
        }
        String md5code = new BigInteger(1, secretBytes).toString(16);// 16进制数字
        // 如果生成数字未满32位，需要前面补0
        for (int i = 0; i < 32 - md5code.length(); i++) {
            md5code = "0" + md5code;
        }
        return md5code;
    }

    /**
     * 	可逆的加密解密算法,执行一次加密,两次解密
     * @param str
     * @return
     */
    public static String convertMD5(String str){

        char[] a = str.toCharArray();
        for (int i = 0; i < a.length; i++){
            a[i] = (char) (a[i] ^ 't');
        }
        String s = new String(a);
        return s;

    }



    /**
     * 锦浪云获取当前时间
     * @return
     */
    private static String getGMTTime() {
        Calendar cd = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        return sdf.format(cd.getTime());
    }

    /**
     * 锦浪云authorization加密
     * @param contentMd5
     * @param date
     * @param url
     * @param apiSecret
     * @param apiId
     * @return
     */
    private static String getAuthorization(String contentMd5, String date, String url, String apiSecret, String apiId) {
        log.info("get authorization, content.md5: {}, date: {}, url: {}", contentMd5, date, url);
        StringBuilder sb = new StringBuilder();
        sb.append("POST\n");
        sb.append(contentMd5).append("\n");
        sb.append("application/json\n");
        sb.append(date).append("\n");
        sb.append(url.substring(GinLangConstan.url.length()));
        byte[] bytes = genHMAC(sb.toString(), apiSecret);
        return "API " + apiId + ":" + Base64.encodeBytes(bytes);
    }

    /**
     * 锦浪云genHMAC
     * @param data
     * @param key
     * @return
     */
    private static byte[] genHMAC(String data, String key) {
        try {
            SecretKeySpec signinKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8),HMAC_SHA1);
            Mac mac = Mac.getInstance(HMAC_SHA1);
            mac.init(signinKey);
            return mac.doFinal(data.getBytes());
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 锦浪云请求公共方法
     * @param req  请求参数
     * @param url  请求接口
     * @return response
     */
    public static String HttpRequest(Map<String,Object> req,String url,String apiSecret,String apiId){
        Map<String,String> headers=new HashMap<>();
        log.info(" HttpRequest,",req, url);
        url = GinLangConstan.url +url;
        String body = JSONUtil.toJsonStr(req);
        String md5 = getDigest(body);
        String gmtTime = getGMTTime();
        String authorization = getAuthorization(md5, gmtTime, url, apiSecret, apiId);
        headers.put("Content-type","application/json;charset=UTF-8");
        headers.put("Authorization",authorization);
        headers.put("Content-MD5",md5);
        headers.put("Date",gmtTime);
        String response= HttpUtil.createPost(url).addHeaders(headers).body(body).execute().body();
        return response;
    }
}
