package com.skr.mdm.util;

import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import net.dongliu.apk.parser.ApkFile;
import net.dongliu.apk.parser.bean.ApkMeta;
import net.dongliu.apk.parser.bean.Icon;
import net.dongliu.apk.parser.bean.IconFace;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.cert.Certificate;
import java.util.List;
import java.util.Objects;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author nfq
 * @date 2022/11/24 10:42
 */
@Slf4j
public class ApkUtil {

    public static String iconPath = "";

    /**
     * 获取apk的包名、版本名、版本号、图标等信息
     * @param file
     * @return
     */
    public static ApkMeta getApkInfo(File file) {
        iconPath = "";
        return getApkMeta(file);
    }

    public static ApkMeta getApkInfo(MultipartFile file) {
        File apkFile = FileUtils.multipartFileToFile(file);
        ApkMeta apkInfo = getApkInfo(apkFile);
        boolean isDelete = apkFile.delete();
        log.info("apkFile本地文件是否删除：{}", isDelete);
        return apkInfo;
    }

    /**
     * 获取APK签名
     * @param file
     * @return
     */
    public static String getApkSign(MultipartFile file) {
        File apkFile = FileUtils.multipartFileToFile(file);
        byte[] signaturesFromApk = getSignaturesFromApk(apkFile);
        boolean isDelete = apkFile.delete();
        log.info("apkFile本地文件是否删除：{}", isDelete);
        return hexDigest(signaturesFromApk);
    }

    private static ApkMeta getApkMeta(File file) {
        try (ApkFile apkFile = new ApkFile(file)) {
            List<IconFace> allIcons = apkFile.getAllIcons();
            String iconFilePath = ServerSystemUtil.userDir() + File.separator + "icon.png";
            IconFace iconFace = allIcons.get(0);
            if (iconFace instanceof Icon && iconFace.getData() != null) {
                FileUtil.writeBytes(Objects.requireNonNull(iconFace.getData()), iconFilePath);
                ApkUtil.iconPath = iconFilePath;
            }
            if (file.exists()) {
                file.delete();
            }
            return apkFile.getApkMeta();
        } catch (IOException e) {
            log.error("apk解析失败", e);
        }
        return null;
    }

    public static String hexDigest(byte[] bytes) {
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        byte[] md5Bytes = md5.digest(bytes);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }

    public static void deleteIconFile() {
        if (StringUtils.isNotBlank(iconPath)) {
            File iconFile = new File(iconPath);
            if (iconFile.delete()) {
                log.info("APK图标本地缓存删除成功");
            }
        }
    }

    /**
     * 从APK中读取签名
     *
     * @param file
     * @return
     * @throws IOException
     */
    private static byte[] getSignaturesFromApk(File file) {
        try {
            JarFile jarFile = new JarFile(file);
            JarEntry je = jarFile.getJarEntry("AndroidManifest.xml");
            byte[] readBuffer = new byte[8192];
            Certificate[] certs = loadCertificates(jarFile, je, readBuffer);
            if (certs != null) {
                for (Certificate c : certs) {
                    return c.getEncoded();
                }
            }
            jarFile.close();
            if (file.exists()) {
                boolean isDelete = file.delete();
                log.info("apkFile本地文件是否删除：{}", isDelete);
            }
        } catch (Exception e) {
            log.error("APK获取签名异常", e);
        }
        return null;
    }

    /**
     * 加载签名
     *
     * @param jarFile
     * @param je
     * @param readBuffer
     * @return
     */
    private static Certificate[] loadCertificates(JarFile jarFile, JarEntry je, byte[] readBuffer) {
        try {
            InputStream is = jarFile.getInputStream(je);
            while (is.read(readBuffer, 0, readBuffer.length) != -1) {
            }
            is.close();
            jarFile.close();
            return je != null ? je.getCertificates() : null;
        } catch (IOException e) {
            log.error("加载签名异常", e);
        }
        return null;
    }

}


