package com.sckw.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sckw.core.model.constant.Global;
import jakarta.servlet.http.HttpServletRequest;
import org.bouncycastle.util.encoders.Hex;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.*;

/**
 * @author dengyinghui
 * @create 2019-02-27
 * @description 加密工具类
 */
public class EncryUtil {
    /**可调用EncryUtil.generatorPriKey()方法生成*/
    public static final String PRI_KEY = "127f0400ff8a8b7a20d91dfc60a39725";
    /**API签名铭文*/
    public static final String SIGN_KEY = "sign";
    /**API签名公钥*/
    public static final String ACCESS_KEY = "accessKey";
    /**API签名私钥*/
    public static final String ACCESS_SECRET = "accessSecret";

    /**
     * 私钥生成器
     * @author dengyinghui
     * #date 2019/02/27
     * @return
     */
    public static String generatorPriKey() throws Exception{
        //生成Key
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128);
        SecretKey secretKey = keyGenerator.generateKey();
        byte[] keyBytes = secretKey.getEncoded();
        String priKey = toHexString(keyBytes);
        return priKey;
    }


    /**
     * 加密
     * @param appSecret 私钥
     * @param orginStr 原始加密参数
     * @author dengyinghui
     * #date 2019/02/27
     * @return
     */
    public static String encry(String appSecret, String orginStr) throws Exception{
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        Key key = new SecretKeySpec(toByteArray(appSecret), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encodeResult = cipher.doFinal(orginStr.getBytes());
        return Hex.toHexString(encodeResult);
    }


    /**
     * 加密
     * @param appSecret 私钥
     * @param jsonObject 原始加密参数
     * @author dengyinghui
     * #date 2019/02/27
     * @return
     */
    public static String encry(String appSecret, JSONObject jsonObject) throws Exception{
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        Key key = new SecretKeySpec(toByteArray(appSecret), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encodeResult = cipher.doFinal(jsonObject.toJSONString().getBytes());
        return Hex.toHexString(encodeResult);
    }


    /**
     * 加密
     * @param appSecret 私钥
     * @param orginStr 原始加密参数
     * @author dengyinghui
     * #date 2019/02/27
     * @return
     */
    public static String encryV1(String appSecret, String orginStr){
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            Key key = new SecretKeySpec(toByteArray(appSecret), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encodeResult = cipher.doFinal(orginStr.getBytes());
            return Hex.toHexString(encodeResult);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     *  字节数组转成16进制表示格式的字符串
     * @author dengyinghui
     * #date 2019/02/27
     * @return
     */
    public static String toHexString(byte[] byteArray) {
        if (byteArray == null || byteArray.length < 1){
            throw new IllegalArgumentException("this byteArray must not be null or empty");
        }

        final StringBuilder hexString = new StringBuilder();
        for (int i = 0; i < byteArray.length; i++) {
            if ((byteArray[i] & 0xff) < 0x10){
                hexString.append("0");
            }

            hexString.append(Integer.toHexString(0xFF & byteArray[i]));
        }
        return hexString.toString().toLowerCase();
    }


    /**
     *  16进制的字符串表示转成字节数组
     * @author dengyinghui
     * #date 2019/02/27
     * @return
     */
    public static byte[] toByteArray(String hexString) {
        if (org.apache.commons.lang3.StringUtils.isEmpty(hexString)){
            throw new IllegalArgumentException("this hexString must not be empty");
        }

        hexString = hexString.toLowerCase();
        final byte[] byteArray = new byte[hexString.length() / 2];
        int k = 0;
        //因为是16进制，最多只会占用4位，转换成字节需要两个16进制的字符，高位在先
        for (int i = 0; i < byteArray.length; i++) {
            byte high = (byte) (Character.digit(hexString.charAt(k), 16) & 0xff);
            byte low = (byte) (Character.digit(hexString.charAt(k + 1), 16) & 0xff);
            byteArray[i] = (byte) (high << 4 | low);
            k += 2;
        }
        return byteArray;
    }


    /**
     * 解密
     * @param appSecret 私钥
     * @param encryStr 加密了的字符串
     * @author dengyinghui
     * #date 2019/02/27
     * @return
     */
    public synchronized static String descry(String appSecret, String encryStr) throws Exception {
        Key key = new SecretKeySpec(toByteArray(appSecret), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decodeResult = cipher.doFinal(org.apache.commons.codec.binary.Hex.decodeHex(encryStr));
        return new String(decodeResult);
    }


    /**
     * 解密
     * @param appSecret 私钥
     * @param encryStr 加密了的字符串
     * @author dengyinghui
     * #date 2019/02/27
     * @return
     */
    public synchronized static String descryV1(String appSecret, String encryStr) {
        try {
            Key key = new SecretKeySpec(toByteArray(appSecret), "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decodeResult = cipher.doFinal(org.apache.commons.codec.binary.Hex.decodeHex(encryStr));
            return new String(decodeResult);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 解密
     * @param appSecret 私钥
     * @param encryStr 加密了的字符串
     * @author dengyinghui
     * #date 2019/02/27
     * @return
     */
    public synchronized static Map<String, Object> descryV2(String appSecret, String encryStr) {
        try {
            Key key = new SecretKeySpec(toByteArray(appSecret), "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decodeResult = cipher.doFinal(org.apache.commons.codec.binary.Hex.decodeHex(encryStr));
            String decodeStr = new String(decodeResult);

            return JSON.parseObject(decodeStr, HashMap.class);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 解密
     * @param appSecret 私钥
     * @param encryStr 加密了的字符串
     * @author dengyinghui
     * #date 2019/02/27
     * @return
     */
    public static JSONObject descryJson(String appSecret, String encryStr) throws Exception {
        String json = EncryUtil.descry(Global.PRI_KEY, encryStr);
        return JSON.parseObject(json);
    }


    /**
     * @description 校验
     * @author zk
     * @date 2020/8/15 15:15
     * @param
     * @return
     **/
    public static boolean checkSign(Map<String, Object> data, String accessSecret) {
        String originSign = null;
        Map params = CollectionUtils.createHashMap();
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            if (SIGN_KEY.equals(entry.getKey())){
                originSign = StringUtils.objectStr(entry.getValue());
                continue;
            }
            if (ACCESS_KEY.equals(entry.getKey())){
                continue;
            }
            params.put(entry.getKey(), entry.getValue());
        }

        String sign = createSign(params, accessSecret);
        return sign.equals(originSign);
    }


    /**
     * @description 校验
     * @author zk
     * @date 2020/8/17 17:45
     * @param
     * @return
     **/
    public static boolean checkSign(HttpServletRequest request, String accessSecret) {
        Enumeration<?> pNames = request.getParameterNames();
        Map<String, Object> params = new HashMap<>(Global.NUMERICAL_SIXTEEN);
        while (pNames.hasMoreElements()) {
            String pName = (String) pNames.nextElement();
            if (SIGN_KEY.equals(pName)) {
                continue;
            }
            Object pValue = request.getParameter(pName);
            params.put(pName, pValue);
        }

        return checkSign(params, accessSecret);
    }


    /**
     * @description 生成签名
     * @author zk
     * @date 2020/8/15 15:14
     * @param {params：请求参数，accessSecret 私钥}
     * @return
     **/
    public static String createSign(Map<String, Object> params, String accessSecret) {
        Set<String> keysSet = params.keySet();
        Object[] keys = keysSet.toArray();
        Arrays.sort(keys);
        StringBuilder temp = new StringBuilder();
        boolean first = true;
        for (Object key : keys) {
            if (first) {
                first = false;
            } else {
                temp.append("&");
            }
            temp.append(key).append("=");
            Object value = params.get(key);
            String valueString = "";
            if (null != value) {
                valueString = String.valueOf(value);
            }
            temp.append(valueString);
        }
        temp.append("&").append(ACCESS_SECRET).append("=").append(accessSecret);
        //LogUtil.debug("参数:" + temp.toString());
        return PasswordUtils.md5(temp.toString()).toUpperCase();
    }

    public static void main(String [] age)  {
        long timeStamp = System.currentTimeMillis();
        Map<String, Object> params = CollectionUtils.createHashMap();
        params.put("subtaskId", "SDT2008020000301");
        params.put("goodsName", "工业级碳酸乙烯酯");
        params.put("grossWeight", "47.7800");
        params.put("netWeight", "17.6800");
        params.put("weight", "30.0000");
        params.put("timeStamp", "1597890005658");
        String singStr = createSign(params, "xinyuan20200819");
        System.out.println("sign:" +singStr);
        System.out.println("timeStamp:" +timeStamp);
    }
}