package com.yc.ship.module.trade.framework.common.ota;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class AesUtil {
    private static final String AES = "AES";
//    private static final String UTF8 = "UTF-8";

    /**
     * AES加密
     *
     * @param content
     * @param pkey
     * @return
     * @throws DecoderException
     */
    private static byte[] encrypt(String content, String pkey) {
        try {
            String private_key = pkey;
            byte[] encodeFormat = null;
            try {
                //秘钥 Hex解码为什么秘钥要进行解码，因为秘钥是某个秘钥明文进行了Hex编码后的值，所以在使用的时候要进行解码
                encodeFormat = Hex.decodeHex(private_key.toCharArray());
            } catch (DecoderException e) {
                e.printStackTrace();
            }
            SecretKeySpec key = new SecretKeySpec(encodeFormat, AES);
            // Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            // 加密内容进行编码
            byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, key);
            // 正式执行加密操作
            byte[] result = cipher.doFinal(byteContent);
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 加密方法
     *
     * @param encData   要加密的数据
     * @param secretKey 密钥，16位的数字和字母
     * @param vector    初始化向量，16位的数字和字母
     * @return
     * @throws Exception
     */
    public static String encrypt(String encData, String secretKey, String vector) {
        try {
            byte[] raw = secretKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            // "算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            // 使用CBC模式，需要一个向量iv，可增加加密算法的强度
            IvParameterSpec iv = new IvParameterSpec(vector.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(encData.getBytes(StandardCharsets.UTF_8));
            return encodeBytes(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 转16进制
     *
     * @param bytes
     * @return
     */
    public static String encodeBytes(byte[] bytes) {
        StringBuilder strBuf = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a')));
            strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a')));
        }
        return strBuf.toString();
    }

    /**
     * AES解密
     *
     * @param contents
     * @param password
     * @return
     * @throws DecoderException
     */
    private static byte[] decrypt(String contents, String password) throws DecoderException {
        try {
            //密文使用Hex解码
            byte[] content = Hex.decodeHex(contents.toCharArray());
            //秘钥 Hex解码为什么秘钥要进行解码，因为秘钥是某个秘钥明文进行了Hex编码后的值，所以在使用的时候要进行解码
            byte[] encodeFormat = Hex.decodeHex(password.toCharArray());
            SecretKeySpec key = new SecretKeySpec(encodeFormat, AES);
            // Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance(AES);
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, key);
            // 正式执行解密操作
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密方法
     *
     * @param decData   要解密的数据
     * @param secretKey 密钥，16位的数字和字母
     * @param vector    初始化向量，16位的数字和字母
     * @return
     * @throws Exception
     */
    public static String decrypt(String decData, String secretKey, String vector) {
        try {
            byte[] raw = secretKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(vector.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = decodeBytes(decData);
            byte[] original = cipher.doFinal(encrypted1);
            return new String(original, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 转字节数组
     *
     * @param str
     * @return
     */
    public static byte[] decodeBytes(String str) {
        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length(); i += 2) {
            char c = str.charAt(i);
            bytes[i / 2] = (byte) ((c - 'a') << 4);
            c = str.charAt(i + 1);
            bytes[i / 2] += (c - 'a');
        }
        return bytes;
    }

    /**
     * Aes加密
     *
     * @param context     明文
     * @param private_key 秘钥
     * @return
     */
    public static String encryption(String context, String private_key) {
        try {
            //加密后的明文也就变成了密文
            byte[] encryptResult = encrypt(context, private_key);
            //密码文Hex编码
            String encryptResultStr = Hex.encodeHexString(encryptResult);
            return encryptResultStr;
        } catch (Exception e) {
            System.out.println(e.toString());
            return null;
        }
    }

    /**
     * Aes解密
     *
     * @param context     密文
     * @param private_key 秘钥
     * @return
     * @throws DecoderException
     * @throws UnsupportedEncodingException
     */
    public static String decryption(String context, String private_key) {
        try {
            //这里的密文解密前先进行了Hex解码
            byte[] decryptResult = decrypt(context, private_key);
            String result = new String(decryptResult, StandardCharsets.UTF_8);
            return result;
        } catch (DecoderException e) {
            System.out.println(e.toString());
            return null;
        }
    }

    // 加密
    public static String encryptBase64(String sSrc, String sKey) {
        try {
            if (sKey == null) {
                System.out.print("Key为空null");
                return null;
            }
            // 判断Key是否为16位
            if (sKey.length() != 16) {
                System.out.print("Key长度不是16位");
                return null;
            }
            byte[] raw = sKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(sSrc.getBytes(StandardCharsets.UTF_8));

            return new Base64().encodeToString(encrypted);//此处使用BASE64做转码功能，同时能起到2次加密的作用。
        } catch (Exception e) {
            System.out.println(e.toString());
            return null;
        }
    }

    // 解密
    public static String decryptBase64(String sSrc, String sKey) {
        try {
            // 判断Key是否正确
            if (sKey == null) {
                System.out.print("Key为空null");
                return null;
            }
            // 判断Key是否为16位
            if (sKey.length() != 16) {
                System.out.print("Key长度不是16位");
                return null;
            }
            byte[] raw = sKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            byte[] encrypted1 = new Base64().decode(sSrc);//先用base64解密
            try {
                byte[] original = cipher.doFinal(encrypted1);
                String originalString = new String(original, StandardCharsets.UTF_8);
                return originalString;
            } catch (Exception e) {
                System.out.println(e.toString());
                return null;
            }
        } catch (Exception ex) {
            System.out.println(ex.toString());
            return null;
        }
    }

    /**
     * HEX加密
     *
     * @param encData   明文，待加密的内容
     * @param secretKey 密码，加密的密码
     * @return 返回密文，加密后得到的内容。加密错误返回null
     */
    public static String encryptHex(String encData, String secretKey, String vector) {
        try {
            // 1 获取加密密文字节数组
            byte[] cipherTextBytes = encrypt(encData.getBytes(StandardCharsets.UTF_8), pwdHandler(secretKey), pwdHandler(vector));
            // 2 对密文字节数组进行 转换为 HEX输出密文
            String cipherText = byte2hex(cipherTextBytes);
            // 3 返回 HEX输出密文
            return cipherText;
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 加密错误返回null
        return null;
    }

    /**
     * 密码处理方法
     * 如果加解密出问题，
     * 请先查看本方法，排除密码长度不足补"0",导致密码不一致
     *
     * @param password 待处理的密码
     * @return
     */
    private static byte[] pwdHandler(String password) {
        byte[] data = null;
        if (password == null) {
            password = "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append(password);
        while (sb.length() < 16) {
            sb.append("0");
        }
        data = sb.toString().getBytes(StandardCharsets.UTF_8);
        return data;

    }

    /*字节数组转成16进制字符串  */
    public static String byte2hex(byte[] bytes) { // 一个字节的数，
        StringBuffer sb = new StringBuffer(bytes.length * 2);
        String tmp = "";
        for (int n = 0; n < bytes.length; n++) {
            // 整数转成十六进制表示
            tmp = (Integer.toHexString(bytes[n] & 0XFF));
            if (tmp.length() == 1) {
                sb.append("0");
            }
            sb.append(tmp);
        }
        return sb.toString().toUpperCase(); // 转成大写
    }

    /**
     * 原始加密
     *
     * @param clearTextBytes 明文字节数组，待加密的字节数组
     * @param pwdBytes       加密密码字节数组
     * @return 返回加密后的密文字节数组，加密错误返回null
     */
    public static byte[] encrypt(byte[] clearTextBytes, byte[] pwdBytes, byte[] vector) {
        try {
            SecretKeySpec keySpec = new SecretKeySpec(pwdBytes, "AES");
            // "算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
            // 使用CBC模式，需要一个向量iv，可增加加密算法的强度
            IvParameterSpec iv = new IvParameterSpec(vector);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
            byte[] cipherTextBytes = cipher.doFinal(clearTextBytes);
            // 5 返回密文字符集
            return cipherTextBytes;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * HEX解密
     *
     * @param decData   密文，带解密的内容
     * @param secretKey 密码，解密的密码
     * @return 返回明文，解密后得到的内容。解密错误返回null
     */
    public static String decryptHex(String decData, String secretKey, String vector) {
        try {
            // 1 将HEX输出密文 转为密文字节数组
            byte[] cipherTextBytes = hex2byte(decData);

            // 2 将密文字节数组进行解密 得到明文字节数组
            byte[] clearTextBytes = decrypt(cipherTextBytes, pwdHandler(secretKey), pwdHandler(vector));

            // 3 根据 CHARACTER 转码，返回明文字符串
            return new String(clearTextBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 解密错误返回null
        return null;
    }

    /**
     * 将hex字符串转换成字节数组
     *
     * @param str
     * @return
     */
    private static byte[] hex2byte(String str) {
        if (str == null || str.length() < 2) {
            return new byte[0];
        }
        str = str.toLowerCase();
        int l = str.length() / 2;
        byte[] result = new byte[l];
        for (int i = 0; i < l; ++i) {
            String tmp = str.substring(2 * i, 2 * i + 2);
            result[i] = (byte) (Integer.parseInt(tmp, 16) & 0xFF);
        }
        return result;
    }

    /**
     * 原始解密
     *
     * @param cipherTextBytes 密文字节数组，待解密的字节数组
     * @param pwdBytes        解密密码字节数组
     * @return 返回解密后的明文字节数组，解密错误返回null
     */
    public static byte[] decrypt(byte[] cipherTextBytes, byte[] pwdBytes, byte[] vector) {
        try {
            // 1 获取解密密钥
            SecretKeySpec keySpec = new SecretKeySpec(pwdBytes, "AES");
            // 2 获取Cipher实例
            Cipher cipher = Cipher.getInstance("AES/CBC/ISO10126Padding");
            // 3.使用CBC模式，需要一个向量iv，可增加加密算法的强度
            IvParameterSpec iv = new IvParameterSpec(vector);
            // 4.初始化Cipher实例。设置执行模式以及加密密钥
            cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
            // 5.执行
            byte[] clearTextBytes = cipher.doFinal(cipherTextBytes);
            // 6.返回明文字符集
            return clearTextBytes;
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 解密错误 返回null
        return null;
    }

    public static void main(String[] args) {
        //加密内容
        String content = "mhfiodbpjneiakfffjmdiploobjdgjohcfomcpkbdobdilldcnnldmoioieimbidgeplbeheflpnjmokofdfgnpklfbjeenmhlogmlnhcnicpfoenmammhenkjclejoodngodffmjcbjjemfjmoicblboajohfcgfmenpcaemgfnggjnbdfedadbcphecdjopneopniefjnnadhjabpbnohkaildckcooiocoodgmmjpcmpcpijadofjomadfamdncilehgieblbnheeddaeefocbppgfgefffhcndmpcnmkjmgkmabiiaibambpkcbofmannfndnpdcejhlcfbobhdniimbbdiikmacgeakpoemfhbcboldfhpieboiiclidakedcpjkijjblikmiebmjekddgkajbjbpbhalbloefhejfijpckpnllgofkojnpcfplfgchlkgpjajlckddkmgdjehnoiclhebncnicdomdjadjofjmjiffdppgbkabphbfglfbgdpjaknlfdiemfhkpfmmohahfcofaifokneadebcooffiiclbabmfemdcohdcbgjlbphoknampnopeepjlniokmepodoginnemineiaacapcefkggemenjdpihdpaadfpgkklkladmoogjkbgkgljgdelakkijfiemhdpmhcanannijfbjagokondegdkediljflikniihbpfnpkdfkbedbknhjbnplllbpcmjpopnjkcbgcchnegkhjnkmogkkafcpdphijhkgblialgceaifogfmbokbahbdbjpccnpgndpmfbmchdgmnieddhbacnccehdbkmmfbpjhmgfblnpjmejedebfaohmalponapepfiadgboakhgkdlkphggiocenhafndofckdafjcgpkoephjckbjgolcpjdciohogaamcmccpdmofolacoocpiiejhmdknamghckigdljceninagkblhnonajljcamfcoafcmkfnoagnjnnpoeojenmmpkddcedmlklkhleencbjlpphdamhllgfikaaabomfcldanpcdfbaeobniibmaiblcfohjfcgncimfanefhkjabpcffgbigpfajhbdfiopfjmngaamhelkapgpaeljipcmmjehklhjnjcbgioobapclmmafkcgjhcgekbcijalmbggjnefjkoolhhjedkgpdacgehpkjpnjjlgloecoidbcpollflgaibkgolmmpdcjijpmjifdlfkbjbcncdiekiebmhkpdgomlnbfelogkhbanglgedoiajnioajddhhbbkipmedalgjegjjcddfaenhkimcebdenpeibiocllmhdmpkfdggmndpcokeacmeekokepbjjkdikhhpojcfdboopjlnfkganjdeambablpbfffjlkmjenakdbeppidfllckaaegopfkjfpbkhgniaimcpdjljohnppcinmmkejjjmhkmnkhoeonlfhfhkpggaeandlkdhekjiomhinjbpageoapgdhllkimnolbkdilcaehmdbicpcgdmklajbpklcpmjedpmoakifciajcpcaemdmnphfienagdbciifijbaekkljbokpcnimiohflejmbmlbgjkcjagdnfhdkngdhfpodndajicgdchckjjcecdbdaifdgfcilaappedillplaonlediglojiglomjplegiiipmhogaopacdebagcfdellappjcbjhkcclbfcklmleenppihjbgbafpjooognncbfjmlgmajhkklmacedilheafmoolaifnjaafhcaameomnikinlekdolhnmfkjnohbmfaegladdggjcldcoiibkbjccmjcagchggfdlddnodhncochcmephjogpanimpndobnehcdjckdjindcmdjnapdackndpoffnjadbionppmnfcelhngegnjohhfnkihboonihckljplfgbjljglknhincndkgbiibjaehnfjiopnfndcgcepeeolmdloadpplbjnjaibgnlaojegkfjignbjmbkbffhhdgfjamcjfcmejclegfecbbhdlmapffeijgaahelefgidjfnmfngpdaanbnmbgdekplkgffmlopnmegjhhajfdjidkihbnjpbhoihnfhaoeaaokbmgcncjppaecadaghaddidnpapjciofgfacolllmkmiamolmhiancihmcbipbeegnglncnhmnhigocfjkdphlbgodcojlfoahmccmpgeehcbpclinlpmembmpgekjobjinedgpabpnlcilmdmjhncanhpfgdfogjpmceannaekibjhhlpflmdfhnnpbffkcipfkpdnjafkbnohfolifejdmfhhkihhncmngkfdldhoibccmlglnilippjjaoieldfnkdipofgnndkfiicjdoiljbnbjlndofecopcijnblfobnfbocainkoaamnhhhampninedlbmhelokegjbnafeidckdbfbooebbnihlobnkgpmjlkfkdegipihlaokpfnnnjmeoempccfkegdinlkidlgmdklpmpaoeifindfkcbmapjbboeofgiohbpnkkhijkjlbjkfaiomokkddmbmlalgjeeldagjjcidkgelceelkkhibacicmilpecfgeaadlfipbdeamknelnnepajhlndgclhajilgikceahekdcbgibpbddlieiiadnfnggeblbpmbeganfmfpbeeldflecpbfkgiplcifiiiikipecpghmkfeajdlijlidghnmbilbf";
        // 调用加密方法
        String encryptResultStr = decrypt(content, "f39d3ee09255ff44","6db63bafb1e9f548");
        System.out.println("加密后：" + encryptResultStr);

        String s = "{\"orderLastConfirmTime\":\"2025-12-21 11:25:56\",\"coupons\":[],\"otaOrderId\":\"T4-00118-1128134116736729\",\"sequenceId\":\"T4-00118-1128134116736788-1417787216\",\"confirmType\":2,\"items\":[{\"passengers\":[{\"cardIssuePlace\":\"\",\"cardIssueCountry\":\"\",\"shoeSize\":0.0,\"gender\":\"M\",\"cardIssueDate\":\"1900-01-01\",\"intlCode\":\"86\",\"nationalityName\":\"\",\"mobile\":\"17854251354\",\"cardType\":\"1\",\"weight\":0.0,\"myopiaDegreeL\":0.0,\"cardNo\":\"513021199505161850\",\"birthDate\":\"1900-01-01\",\"ageType\":\"ADU\",\"myopiaDegreeR\":0.0,\"birthPlace\":\"\",\"nationalityCode\":\"\",\"name\":\"吴育树\",\"passengerId\":\"527457596\",\"cardValidDate\":\"1900-01-01\",\"height\":0.0}],\"cost\":100.00,\"quantity\":1,\"salePrice\":138.00000,\"useEndDate\":\"2025-12-22\",\"locale\":\"zh-CN\",\"useStartDate\":\"2025-12-21\",\"itemId\":\"4656300118\",\"lastConfirmTime\":\"2025-12-21 11:25:56\",\"priceCurrency\":\"CNY\",\"adjunctions\":[],\"price\":138.0,\"PLU\":\"1862827537978253314\",\"deposit\":{},\"distributionChannel\":\"\",\"costCurrency\":\"CNY\",\"salePriceCurrency\":\"CNY\",\"expressDelivery\":{\"type\":\"1\"}}],\"contacts\":[{\"intlCode\":\"86\",\"name\":\"吴育树\",\"mobile\":\"17854251354\",\"optionalMobile\":\"\",\"optionalIntlCode\":\"\",\"email\":\"\"}]}";
        String encryptResultStr2 = encrypt(s, "f39d3ee09255ff44","6db63bafb1e9f548");
        System.out.println(encryptResultStr2);
    }
}
