package com.zjsgfa.project.zjsgfa.util;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class FileBase64Converter {


    /**
     * 将文件转换为Base64编码字符串
     * @param file 要转换的文件对象
     * @return Base64编码字符串
     * @throws IOException 读取文件时的IO异常
     */
    public static String fileToBase64(File file) throws IOException {
        // 1. 校验文件是否有效
        if (file == null || !file.exists() || !file.isFile()) {
            throw new IllegalArgumentException("文件不存在或不是有效文件");
        }
        // 2. 读取文件字节
        try (FileInputStream fis = new FileInputStream(file)) {
//            byte[] fileBytes = originalString.getBytes(StandardCharsets.UTF_8);
            byte[] fileBytes = new byte[(int) file.length()];
            fis.read(fileBytes);

            // 3. 编码为Base64字符串（使用URL安全的编码器，避免+、/等特殊字符问题）
//            return Base64.getUrlEncoder().encodeToString(fileBytes);
            return Base64.getEncoder().encodeToString(fileBytes);
        }
    }

    /**
     * 将文件转换为Base64编码字符串（无压缩、无截断）
     * @param file 要转换的文件对象
     * @return Base64编码字符串（标准编码，非URL安全，如需URL安全可替换为getUrlEncoder）
     * @throws IOException 读取文件时的IO异常
     */
    public static String fileToBase64Two(File file) throws IOException {
        // 1. 严格校验文件有效性
        if (file == null) {
            throw new IllegalArgumentException("文件对象不能为空");
        }
        if (!file.exists()) {
            throw new IllegalArgumentException("文件不存在：" + file.getAbsolutePath());
        }
        if (!file.isFile()) {
            throw new IllegalArgumentException("不是有效文件：" + file.getAbsolutePath());
        }
        if (file.length() > Integer.MAX_VALUE) {
            throw new IllegalArgumentException("文件过大（超过2GB），不支持转换：" + file.getAbsolutePath());
        }

        // 2. 读取文件所有字节（确保完整读取，避免read()单次读取不完整）
        // 2. 完整读取文件字节（解决大文件读取不完整问题）
        try (FileInputStream fis = new FileInputStream(file)) {
            // 推荐使用ByteArrayOutputStream动态接收字节，避免文件长度溢出int范围（可选优化）
            byte[] buffer = new byte[4096]; // 4K缓冲区，适配IO性能
            int bytesRead;
            java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
            while ((bytesRead = fis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            byte[] fileBytes = bos.toByteArray();

            // 3. 编码为Base64（URL安全，无压缩）
            // 若不需要URL安全，改用Base64.getEncoder()
            return Base64.getUrlEncoder().encodeToString(fileBytes);
        }
    }







    /**
     * 将Base64字符串转回文件（用于测试验证）
     * @param base64Str Base64编码字符串
     * @param outputFile 输出文件对象
     * @throws IOException 写入文件时的IO异常
     */
    public static void base64ToFile(String base64Str, File outputFile) throws IOException {
        // 解码Base64字符串为字节数组
        byte[] fileBytes = Base64.getUrlDecoder().decode(base64Str);

        // 写入文件
        try (FileOutputStream fos = new FileOutputStream(outputFile)) {
            fos.write(fileBytes);
        }
    }


    /**
     * 将 Base64 字符串转换为 Excel 文件
     * @param base64Str 有效的 Excel 文件 Base64 编码字符串
     * @param outputPath 生成 Excel 文件的完整路径（如：D:\\test.xlsx）
     * @throws IOException 文件写入异常
     * @throws IllegalArgumentException Base64 字符串为空/无效
     */
    public static void base64ToExcel(String base64Str, String outputPath) throws IOException {
        // 1. 校验入参有效性
        if (base64Str == null || base64Str.isEmpty()) {
            throw new IllegalArgumentException("Base64 字符串不能为空");
        }
        if (outputPath == null || outputPath.isEmpty()) {
            throw new IllegalArgumentException("Excel 文件输出路径不能为空");
        }

        File excelFile = new File(outputPath);
        // 确保输出目录存在（如果目录不存在则创建）
        File parentDir = excelFile.getParentFile();
        if (!parentDir.exists()) {
            boolean mkdirsSuccess = parentDir.mkdirs();
            if (!mkdirsSuccess) {
                throw new IOException("创建输出目录失败：" + parentDir.getAbsolutePath());
            }
        }

        try {
            // 2. 解码 Base64 字符串为字节数组（兼容 URL 安全的 Base64 编码）
            byte[] excelBytes = Base64.getDecoder().decode(base64Str);

            // 3. 将字节数组写入 Excel 文件（try-with-resources 自动关闭流）
            try (FileOutputStream fos = new FileOutputStream(excelFile)) {
                fos.write(excelBytes);
                System.out.println("Excel 文件生成成功：" + excelFile.getAbsolutePath());
            }
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("Base64 字符串格式无效，无法解码", e);
        }
    }



    /**
     * 计算文件MD5（用于验证文件一致性）
     * @param file 目标文件
     * @return MD5十六进制字符串
     * @throws IOException IO异常
     * @throws NoSuchAlgorithmException 加密算法不存在
     */
    public static String calculateFileMD5(File file) throws IOException, NoSuchAlgorithmException {
        if (file == null || !file.exists()) {
            return null;
        }
        MessageDigest md = MessageDigest.getInstance("MD5");
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                md.update(buffer, 0, bytesRead);
            }
        }
        byte[] mdBytes = md.digest();
        // 转换为十六进制字符串
        StringBuilder sb = new StringBuilder();
        for (byte b : mdBytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    /**
     * 文件转Base64（支持标准/URL安全编码）
     * @param file 目标文件
     * @param isUrlSafe 是否使用URL安全编码
     * @return Base64字符串
     * @throws IOException IO异常
     */
    public static String fileToBase64S(File file, boolean isUrlSafe) throws IOException {
        // 1. 校验文件有效性
        if (file == null || !file.exists() || !file.isFile()) {
            throw new IllegalArgumentException("文件不存在或不是有效文件");
        }
        // 2. 完整读取文件字节
        try (FileInputStream fis = new FileInputStream(file);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            byte[] fileBytes = bos.toByteArray();
            // 3. 选择编码方式
            Base64.Encoder encoder = isUrlSafe ? Base64.getUrlEncoder() : Base64.getEncoder();
            return encoder.encodeToString(fileBytes);
        }
    }



    public static void main(String[] args) throws IOException {

            // 测试将文件转换为 Base64
        File file = new File("D:\\qianhe\\file\\钻井施工智能优选\\解析\\XYL217X52钻井地质设计.pdf");
        String base64Str = fileToBase64(file);
//        System.out.println(base64Str);
        // 指定输出文件路径
        String outputPath = "D:\\qianhe\\file\\钻井施工智能优选\\解析\\地质设计-jy导出.txt";

        try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath))) {
            writer.write(base64Str);
        } catch (IOException e) {
            System.err.println("写入文件时出错: " + e.getMessage());
        }
//        File file1 =new File("D:\\qianhe\\file\\钻井施工智能优选\\解析\\XYL217X52.pdf");
//        base64ToFile(base64Str, file1);

        // 测试将文件转换为 Base64
//        File file = new File("D:\\qianhe\\file\\钻井施工智能优选\\解析\\XYL217X52钻井工程设计.pdf");
//        String base64Str = fileToBase64S(file,false);
//        System.out.println(base64Str);
//        File file1 =new File("D:\\qianhe\\file\\钻井施工智能优选\\解析\\XYL217X52设计转.pdf");
//        base64ToFile(base64Str, file1);

    }
}
