package com.shanghaichengdi.ghjgitem.util;

import com.alibaba.fastjson.JSONObject;
import com.shanghaichengdi.ghjgitem.exception.AesDecodeException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.springframework.util.StringUtils;

public class Encodes {

  private static final String AES = "AES";
  private static final String AES_CBC = "AES/CBC/PKCS5Padding";

  public static byte[] decodeBase64(String input) {
    return Base64.decodeBase64(input.getBytes());
  }

  /**
   * 使用 HMAC-MD5 签名方法对对encryptText进行签名
   *
   * @param encryptText 被签名的字符串
   * @param encryptKey  密钥
   * @return
   * @throws Exception
   */
  public static byte[] HmacMD5Encrypt(String encryptText, String encryptKey) throws Exception {
    byte[] data = encryptKey.getBytes("UTF-8");
    // 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
    SecretKey secretKey = new SecretKeySpec(data, "HmacMD5");
    // 生成一个指定 Mac 算法 的 Mac 对象
    Mac mac = Mac.getInstance("HmacMD5");
    // 用给定密钥初始化 Mac 对象
    mac.init(secretKey);

    byte[] text = encryptText.getBytes("UTF-8");
    // 完成 Mac 操作
    return mac.doFinal(text);
  }

  public static String sign(Map<String, String> paramValues, String secret) {
    try {
      StringBuilder sb = new StringBuilder();
      for (String value : paramValues.values()) {
        if (StringUtils.hasLength(value)) {
          sb.append(value);
        }
      }
      byte[] md5Digest = HmacMD5Encrypt(sb.toString(), secret);
      String result = encodeHex(md5Digest).toUpperCase();
      return result;
    } catch (Exception e) {
      //throw new PlatformException("数据签名出错", e);
      throw new RuntimeException(e);
    }
  }

  /**
   * Hex编码.
   */
  public static String encodeHex(byte[] input) {
    return new String(Hex.encodeHex(input));
  }

  /**
   * Base64编码.
   */
  public static String encodeBase64(byte[] input) {
    return new String(Base64.encodeBase64(input));
  }

  public static byte[] aesEncrypt(byte[] input, byte[] key, byte[] iv) {
    return aes(input, key, iv, Cipher.ENCRYPT_MODE);
  }

  /**
   * 使用AES加密或解密无编码的原始字节数组, 返回无编码的字节数组结果.
   *
   * @param input 原始字节数组
   * @param key   符合AES要求的密钥
   * @param iv    初始向量
   * @param mode  Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
   */
  private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
    try {
      SecretKey secretKey = new SecretKeySpec(key, AES);
      IvParameterSpec ivSpec = new IvParameterSpec(iv);
      Cipher cipher = Cipher.getInstance(AES_CBC);
      cipher.init(mode, secretKey, ivSpec);
      return cipher.doFinal(input);
    } catch (GeneralSecurityException e) {
      throw new AesDecodeException("传入参数不符合规范要求");
    }
  }


  /**
   * 使用AES解密字符串, 返回原始字符串.
   *
   * @param input Hex编码的加密字符串
   * @param key   符合AES要求的密钥
   * @param iv    初始向量
   */
  public static byte[] aesDecrypt(byte[] input, byte[] key, byte[] iv) {
    return aes(input, key, iv, Cipher.DECRYPT_MODE);
  }

  public static void main(String[] args) {
    // 注意:"ghThreeDataShare"字符串为加密解密的key字符串,必须用该字符串进行加密和解密
    List<String> stringList = new ArrayList<>();
    stringList.add("test");
    stringList.add("test1");
    stringList.add("encodesKey");
    String jsonString = JSONObject.toJSONString(stringList);
    String encodedData = Encodes.encodeBase64(
        Encodes.aesEncrypt(jsonString.getBytes(StandardCharsets.UTF_8),
            "ghThreeDataShare".getBytes(),
            "ghThreeDataShare".getBytes()));
    System.out.println(encodedData);
    String data = new String(Encodes.aesDecrypt(
        Encodes.decodeBase64(encodedData),
        "ghThreeDataShare".getBytes(),
        "ghThreeDataShare".getBytes()), StandardCharsets.UTF_8);
    System.out.println(data);
    // 对请求参数进行加密
    JSONObject sysUserReq = new JSONObject();
//    sysUserReq.put("pageIndex", "1");
//    sysUserReq.put("pageSize", "10");
//    sysUserReq.put("startTime", "2024-06-12");
//    sysUserReq.put("endTime", "2024-06-12");
    sysUserReq.put("shipName", "宁高鹏182");
    String string = JSONObject.toJSONString(sysUserReq);
    String mvData = Encodes.encodeBase64(
        Encodes.aesEncrypt(string.getBytes(StandardCharsets.UTF_8),
            "ghThreeDataShare".getBytes(),
            "ghThreeDataShare".getBytes()));
    System.out.println(mvData);
    String testResult = "lz2Vi0lKGCyW8bnmWgxCWfD1+LALstWPzTihMN4Ntflr10BU79HbPrx01eYSKV9M0nh/qnMBXEOvRl8margpwnugAzI+OIS3dUywqEPM0T2rFO4CD+KKVa+6UKCxCCFlDSl0sAk/XsCjXVAcOtVFBoYvM3VhVrGnIKNWnUpiQPVnBuaju87T3rIejmJEFY02Uy44m0v8wpIKxNAik69P0W+YmUSiCYGBGBac/5YYEi0dYK5WmEHl6vqm/nvwr6ntNwDJSJ0CG2K2R6qTXT0200r2sPPsvsvWjrviJyoF8g7zjmXn9oH5oZgiC13Gmeh3SPNje/lGl8LqFaCoorTjnUfSnQJf2PD6Hu+zCPa8vn9Nww7sbySDKOZGhy6dLQyAbf0nNgt/JGuE8F+he8Unp9OGN7gwGiBKKck/4Vy8KJvmPJvNyCSZnw2/pRjkEJ4xOrDFfI4OR4nIsY4VawX3ZctEm0tOL1awym2xls4UxBs=";
    String testDecodeResult = new String(Encodes.aesDecrypt(
        Encodes.decodeBase64(testResult),
        "ghThreeDataShare".getBytes(),
        "ghThreeDataShare".getBytes()), StandardCharsets.UTF_8);
    System.out.println(testDecodeResult);
  }
}
