package com.ruoyi.common.utils.file;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.sign.Base64;
import lombok.SneakyThrows;
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.mock.web.MockMultipartFile;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 图片处理工具类
 *
 * @author ruoyi
 */
public class ImageUtils
{
    private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);

    public static byte[] getImage(String imagePath)
    {
        InputStream is = getFile(imagePath);
        try
        {
            return IOUtils.toByteArray(is);
        }
        catch (Exception e)
        {
            log.error("图片加载异常 {}", e);
            return null;
        }
        finally
        {
            IOUtils.closeQuietly(is);
        }
    }

    public static InputStream getFile(String imagePath)
    {
        try
        {
            byte[] result = readFile(imagePath);
            result = Arrays.copyOf(result, result.length);
            return new ByteArrayInputStream(result);
        }
        catch (Exception e)
        {
            log.error("获取图片异常 {}", e);
        }
        return null;
    }

    /**
     * 读取文件为字节数据
     * 
     * @param url 地址
     * @return 字节数据
     */
    public static byte[] readFile(String url)
    {
        InputStream in = null;
        try
        {
            if (url.startsWith("http"))
            {
                // 网络地址
                URL urlObj = new URL(url);
                URLConnection urlConnection = urlObj.openConnection();
                urlConnection.setConnectTimeout(30 * 1000);
                urlConnection.setReadTimeout(60 * 1000);
                urlConnection.setDoInput(true);
                in = urlConnection.getInputStream();
            }
            else
            {
                // 本机地址
                String localPath = RuoYiConfig.getProfile();
                String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
                in = new FileInputStream(downloadPath);
            }
            return IOUtils.toByteArray(in);
        }
        catch (Exception e)
        {
            log.error("获取文件路径异常 {}", e);
            return null;
        }
        finally
        {
            IOUtils.closeQuietly(in);
        }
    }

    /**
     * 根据指定大小压缩图片
     *
     * @param image  源图片字节数组
     * @param desFileSize 指定图片大小，单位kb
     * @param
     * @return 压缩质量后的图片字节数组
     */
    @SneakyThrows
    public static MultipartFile compressPictureForScale(MultipartFile image, long desFileSize) {
        if (Objects.isNull(image) || image.getSize() < desFileSize * 1024 ){
            return image;
        }
        byte[] imageBytes = image.getBytes();
        long srcSize = imageBytes.length;
        double accuracy = getAccuracy(srcSize / 1024);
        try {
            while (imageBytes.length > desFileSize * 1024) {
                ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
                Thumbnails.of(inputStream).scale(accuracy).outputQuality(accuracy).toOutputStream(outputStream);
                imageBytes = outputStream.toByteArray();
            }
            log.info("【图片压缩】imageId={} | 图片原大小={}kb | 压缩后大小={}kb", image.getOriginalFilename(), srcSize / 1024,
                    imageBytes.length / 1024);
        } catch (Exception e) {
            log.error("【图片压缩】msg=图片压缩失败!", e);
        }
        return new MockMultipartFile(image.getOriginalFilename(),image.getOriginalFilename(),image.getContentType(), imageBytes);
    }


    /**
     * 创建多行文本水印图片
     *
     * @param textLines       文本行列表
     * @param font            字体
     * @param color           文字颜色
     * @param backgroundColor 背景颜色（可以为null表示透明背景）
     * @param padding         内边距
     * @return 水印图片
     */
    public static BufferedImage createMultilineTextWatermark(List<String> textLines,
                                                             Font font,
                                                             Color color,
                                                             Color backgroundColor,
                                                             int padding) {
        // 创建临时图片来计算文本尺寸
        BufferedImage tempImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D tempG2d = tempImage.createGraphics();
        tempG2d.setFont(font);
        FontMetrics fm = tempG2d.getFontMetrics();

        // 计算最大宽度和总高度
        int maxWidth = 0;
        int lineHeight = fm.getHeight();
        int totalHeight = lineHeight * textLines.size();

        for (String line : textLines) {
            int lineWidth = fm.stringWidth(line);
            maxWidth = Math.max(maxWidth, lineWidth);
        }
        tempG2d.dispose();

        // 创建实际的水印图片
        int imageWidth = maxWidth + padding * 2;
        int imageHeight = totalHeight + padding * 2;

        BufferedImage watermarkImage = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = watermarkImage.createGraphics();

        // 设置抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        // 设置背景色（如果指定）
        if (backgroundColor != null) {
            g2d.setColor(backgroundColor);
            g2d.fillRect(0, 0, imageWidth, imageHeight);
        }

        // 设置字体和颜色
        g2d.setFont(font);
        g2d.setColor(color);

        // 绘制每一行文字
        int y = padding + fm.getAscent();
        for (String line : textLines) {
            g2d.drawString(line, padding, y);
            y += lineHeight;
        }

        g2d.dispose();
        return watermarkImage;
    }

    /**
     * 使用Thumbnailator添加多行文本水印
     */
    @SneakyThrows
    public static MultipartFile addMultilineTextWatermark(MultipartFile image, List<String> textLines, Positions position, float opacity) {
        // 创建字体
        Font font = new Font("Arial", Font.BOLD, 24);
        // 创建多行文本水印图片
        BufferedImage watermarkImage = createMultilineTextWatermark(
                textLines,
                font,
                Color.WHITE,        // 主文字颜色
                null,
                10                  // 内边距
        );
        byte[] imageBytes = image.getBytes();
        ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);

        // 使用Thumbnailator添加水印
        Thumbnails.of(inputStream)
                .scale(1.0)
                .watermark(position, watermarkImage, opacity)
                .toOutputStream(outputStream);
        imageBytes = outputStream.toByteArray();
        return new MockMultipartFile(image.getOriginalFilename(), image.getOriginalFilename(), image.getContentType(), imageBytes);
    }
    /**
     * 自动调节精度(经验数值)
     *
     * @param size 源图片大小
     * @return 图片压缩质量比
     */
    private static double getAccuracy(long size) {
        double accuracy;
        if (size < 1024) {
            accuracy = 0.9;
        } else if (size < 2047) {
            accuracy = 0.75;
        } else if (size < 3275) {
            accuracy = 0.6;
        } else {
            accuracy = 0.5;
        }
        return accuracy;
    }

    @SneakyThrows
    public static String multiplePartFileToBase64(MultipartFile multipartFile)
    {
        return Base64.encode(multipartFile.getBytes());
    }
}
