package com.fuyuanshen.equipment.utils;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HexFormat;

/**
 * 文件哈希工具类
 */
@Component  // 如果使用 Spring 可以注入
public class FileHashUtil {
    /* 算法常量 */
    private static final String ALGORITHM = "SHA-256";
    /* 缓冲区大小 8 KB */
    private static final int BUFFER_SIZE = 8192;

    /**
     * 计算上传文件的 SHA-256 十六进制哈希
     *
     * @param file 上传文件；不能为 null，且必须非空
     * @return 64 位小写十六进制字符串
     * @throws IllegalArgumentException 参数不合法
     * @throws IOException               流读取失败
     * @throws IllegalStateException     算法运行时异常（不会触发）
     */
    public String hash(MultipartFile file) throws IOException {
        validate(file);

        /* 每个请求新建实例，保证线程安全 */
        MessageDigest digest = newDigest();

        /* try-with-resources 自动关闭流 */
        try (InputStream in = file.getInputStream()) {
            byte[] buf = new byte[BUFFER_SIZE];
            int len;
            while ((len = in.read(buf)) != -1) {
                digest.update(buf, 0, len);
            }
        }

        /* JDK 17+ 的 HexFormat，比 Apache Commons 更快且无需额外依赖 */
        return HexFormat.of().formatHex(digest.digest());
    }

    /* -------------------- 私有辅助方法 -------------------- */

    private static void validate(MultipartFile file) {
        if (file == null) {
            throw new IllegalArgumentException("MultipartFile 不能为 null");
        }
        if (file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }
    }

    private static MessageDigest newDigest() {
        try {
            return MessageDigest.getInstance(ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            /* SHA-256 是 JDK 必现算法，走到这里说明 JDK 实现损坏 */
            throw new IllegalStateException("算法 " + ALGORITHM + " 不可用", e);
        }
    }

    /**
     * 获取文件的哈希值
     * // 或者使用特定算法
     * String md5Hash = getFileHash(audioFile, "MD5");
     * String sha256Hash = getFileHash(audioFile, "SHA-256");
     * @param file       文件
     * @param algorithm  哈希算法
     * @return 文件的哈希值
     * @throws Exception 获取文件哈希值时发生的异常
     */
    public String getFileHash(File file, String algorithm) throws Exception {
        MessageDigest md = MessageDigest.getInstance(algorithm);
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                md.update(buffer, 0, bytesRead);
            }
        }
        byte[] hashBytes = md.digest();
        StringBuilder sb = new StringBuilder();
        for (byte b : hashBytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

}
