package com.zhongshu.card.server.core.util;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.Security;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Set;

import static org.apache.tomcat.util.buf.HexUtils.toHexString;

@Slf4j
public class AesUtils {

    @SneakyThrows
    public static String signData(String json_data) {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.reset();
        md.update(json_data.getBytes("utf-8"));
        return toHexString(md.digest());
    }

    public static String encryptAuth(Set<String> auth) {
        try {
            if (auth != null && auth.size() > 0) {
                return encrypt(String.join(",", auth), "lIllIIIllIIIllIl");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String encrypt(String data, String SECRET_KEY) throws Exception {
        Cipher cipher = Cipher.getInstance("AES");
        SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes());
        return new String(Base64.getEncoder().encode(encryptedBytes));
    }

    /**
     * aes 解密
     *
     * @param data
     * @param SECRET_KEY
     * @return
     * @throws Exception
     */
    public static String decryptAes(String data, String SECRET_KEY) throws Exception {
        Cipher cipher = Cipher.getInstance("AES");
        SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes());
        return new String(Base64.getDecoder().decode(encryptedBytes));
    }

    @SneakyThrows
    public static String signMacSHA256(String str, String key) {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(key.getBytes("utf-8"), "HmacSHA256"));
        mac.update(str.getBytes("utf-8"));
        byte[] arr = mac.doFinal();
        return Base64.getEncoder().encodeToString(arr);
    }

    public static String getMD5Str(String s) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
//            byte[] digest = md.digest(s.getBytes());
//            StringBuilder sb = new StringBuilder();
//            for (byte b : digest) {
//                sb.append(String.format("%02x", b));
//            }
//            return sb.toString();
            byte[] bytes = md.digest(s.getBytes("utf-8"));
            return toHex(bytes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String toHex(byte[] bytes) {
        final char[] HEX_DIGITS = "0123456789ABCDEF".toCharArray();
        StringBuilder ret = new StringBuilder(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            ret.append(HEX_DIGITS[(bytes[i] >> 4) & 0x0f]);
            ret.append(HEX_DIGITS[bytes[i] & 0x0f]);
        }
        return ret.toString();
    }

    public static String base64Encode(String str) {
        if (StringUtils.isNotEmpty(str)) {
            try {
                byte[] encoded = Base64.getEncoder().encode(str.getBytes("utf-8"));
                return new String(encoded);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return str;
    }

    public static String base64Decode(String str) {
        if (StringUtils.isNotEmpty(str)) {
            try {
                byte[] decoded = Base64.getDecoder().decode(str.getBytes("utf-8"));
                return new String(decoded);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return str;
    }

    /**
     * 文件base64内容
     *
     * @param file
     * @return
     */
    public static String turnMultipartFileToBase64(MultipartFile file) {
        if (file != null) {
            try {
                return Base64.getEncoder().encodeToString(toByteArray(file.getInputStream()));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "";
    }

    /**
     * 文件转为字符串
     *
     * @param file
     * @return
     */
    public static String turnMultipartFileToString(MultipartFile file) {
        if (file != null) {
            try {
                return new String(toByteArray(file.getInputStream()), StandardCharsets.UTF_8);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return "";
    }

    public static byte[] toByteArray(InputStream inputStream) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        byte[] data = new byte[8192];
        int nRead;
        while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, nRead);
        }
        return buffer.toByteArray();
    }

    public static PublicKey initializeSM3WithSM2PublicKey(String publicKeyStr) throws Exception {
        // 将字节转换为PublicKey
        Security.addProvider(new BouncyCastleProvider());
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(base64Decode(publicKeyStr).getBytes(StandardCharsets.UTF_8));
        KeyFactory keyFactory = KeyFactory.getInstance("ECDSA", "BC");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

}
