package com.hr.util;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.MemoryCacheImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.Base64;
import java.util.Iterator;

public class ImageUtils {

    public static String imageUrlToBase64(String imageUrl) throws Exception {
        // 1. 下载图片
        BufferedImage originalImage = downloadImage(imageUrl);

        // 2. 获取原始图片的字节大小
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        String formatName = getFormatName(imageUrl);
        ImageIO.write(originalImage, formatName, baos);
        baos.flush();
        byte[] imageBytes = baos.toByteArray();
        baos.close();

        // 3. 如果图片大于500K，进行压缩
        if (imageBytes.length > 500 * 1024) {
            baos = new ByteArrayOutputStream();
            if ("jpg".equalsIgnoreCase(formatName) || "jpeg".equalsIgnoreCase(formatName)) {
                imageBytes = compressJpgUntilUnderSize(originalImage, formatName, baos, 500 * 1024);
            } else if ("png".equalsIgnoreCase(formatName)) {
                BufferedImage compressedImage = originalImage;
                while (imageBytes.length > 500 * 1024 && !isTooSmall(compressedImage)) {
                    compressedImage = compressPng(compressedImage);
                    baos.reset(); // 重置 ByteArrayOutputStream
                    ImageIO.write(compressedImage, formatName, baos);
                    baos.flush();
                    imageBytes = baos.toByteArray();
                }
            }
            baos.close();
        }

        // 4. 将图片字节数组转换为Base64编码
        return Base64.getEncoder().encodeToString(imageBytes);
    }

    private static BufferedImage downloadImage(String imageUrl) throws Exception {
        URL url = new URL(imageUrl);
        try (InputStream is = url.openStream()) {
            return ImageIO.read(is);
        }
    }

    private static String getFormatName(String imageUrl) {
        if (imageUrl.toLowerCase().endsWith(".png")) {
            return "png";
        } else if (imageUrl.toLowerCase().endsWith(".jpg") || imageUrl.toLowerCase().endsWith(".jpeg")) {
            return "jpg";
        } else {
            throw new IllegalArgumentException("Unsupported image format: " + imageUrl);
        }
    }

    private static byte[] compressJpgUntilUnderSize(BufferedImage image, String formatName, ByteArrayOutputStream baos, int targetSize) throws Exception {
        float quality = 0.8f; // 初始压缩质量
        byte[] imageBytes;

        do {
            baos.reset(); // 重置 ByteArrayOutputStream
            compressJpg(image, baos, formatName, quality);
            baos.flush();
            imageBytes = baos.toByteArray();
            quality -= 0.05f; // 每次降低5%的质量
        } while (imageBytes.length > targetSize && quality > 0.05f); // 最低质量为 5%

        return imageBytes;
    }

    private static void compressJpg(BufferedImage image, ByteArrayOutputStream baos, String formatName, float quality) throws Exception {
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
        if (!writers.hasNext()) {
            throw new IllegalStateException("No writers found for format: " + formatName);
        }
        ImageWriter writer = writers.next();
        try (MemoryCacheImageOutputStream outputStream = new MemoryCacheImageOutputStream(baos)) {
            writer.setOutput(outputStream);
            ImageWriteParam param = writer.getDefaultWriteParam();
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            param.setCompressionQuality(quality); // 设置压缩质量
            writer.write(null, new IIOImage(image, null, null), param);
        } finally {
            writer.dispose();
        }
    }

    private static BufferedImage compressPng(BufferedImage originalImage) {
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();

        // 每次缩小尺寸的比例 (80%)
        int targetWidth = (int) (width * 0.8);
        int targetHeight = (int) (height * 0.8);

        BufferedImage resizedImage = new BufferedImage(targetWidth, targetHeight, originalImage.getType());
        Graphics2D g2d = resizedImage.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
        g2d.dispose();
        return resizedImage;
    }

    private static boolean isTooSmall(BufferedImage image) {
        // 设置一个最小的宽度或高度，防止图像压缩得过小
        int minDimension = 50; // 可调整的最小宽度或高度限制
        return image.getWidth() <= minDimension || image.getHeight() <= minDimension;
    }

    public static void main(String[] args) {
        try {
//            String imageUrl = "http://loansm.oss-cn-hangzhou.aliyuncs.com/2024-03-24/d2b8e2be-e93e-42ca-863f-0b522e4039ac.png";
            String imageUrl = "https://pic3.zhimg.com/80/v2-5f609f8d84b8d5f0381eff6b444e057e_1440w.png";
            String base64Image = imageUrlToBase64(imageUrl);
            System.out.println("Base64 Image: " + base64Image);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
