package com.gic.haoban.manage.service.context.combined;

import com.gic.haoban.manage.api.qdto.combined.CombinedQDTO;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by wangzubo on 2024/10/27.
 */
public class ImageCombined {

    private static final Logger logger = LoggerFactory.getLogger(ImageCombined.class);

    private static final Cache<String, BufferedImage> imageCache = Caffeine.newBuilder()
            .maximumWeight(50 * 1024 * 1024) // 50MB
            .weigher((String key, BufferedImage image) -> image.getWidth() * image.getHeight() / 4)
            .expireAfterAccess(30, TimeUnit.MINUTES) // 可设置失效时间
            .build();

    public static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
            10,
            30,
            60L,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(100),
            new ThreadPoolExecutor.AbortPolicy()
    );

    public static final String IMAGE_REDIS_KEY = "haoban-manage3-service:combined_image:";

    private static final int MAX_HEIGHT_NO_WHITE_SPACE = 1500;
    private static final int MAX_HEIGHT_WITH_WHITE_SPACE = 1340;
    private static final int MIN_WIDTH = 500;
    private static final int WHITE_SPACE_HEIGHT = 160;
    private static final int QR_WIDTH_REFERENCE = 136;


    private static final String LARGE_IMAGE_URL = "https://jhdmyx-1251519181.cos.ap-shanghai.myqcloud.com/image/material_content-191564494842458980f5c5ae685d3440.jpg?imageView2/2/w/1080/h/10800/format/jpg";
    private static final String QR_CODE_URL = "https://gicinner-1251519181.cos.ap-shanghai.myqcloud.com/image/material_content-4ffc77073ca1476fb264bf1be9f11383.png";
    private static final String STORE_NAME = "门店CCA门店CCA门店CCA门店CCA门店CCA门店CCA";
    private static final String GUIDE_NAME = "宇智222为您推荐门店CCA门店CCA门店CCA门店CCA门店CCA";
    private static final String OUTPUT_PATH = "/Users/wang/Downloads/output_image5.jpg";

    static {
        ImageIO.scanForPlugins();  // 初始化图像插件
    }
    public static void main(String[] args) throws Exception{
        BufferedImage largeImage = loadImageWithCache(LARGE_IMAGE_URL);
        BufferedImage qrCodeImage = ImageIO.read(new URL(QR_CODE_URL));

        int showStyle = 0;

        BufferedImage combinedImage = generateImage(largeImage, qrCodeImage, showStyle,STORE_NAME, GUIDE_NAME);
        ImageIO.write(combinedImage, "jpg", new File(OUTPUT_PATH));
    }

    public static byte[] getCombinedImage(CombinedQDTO combinedQDTO) throws Exception{
        String imageUrl = combinedQDTO.getImageUrl();
        String qrCodeUrl = combinedQDTO.getQrCodeUrl();
        Integer showStyle = combinedQDTO.getShowStyle();
        String lineOne = combinedQDTO.getLineOne();
        String lineTwo = combinedQDTO.getLineTwo();
        if(imageUrl.contains("?")) {
            logger.info("url有参数={}",imageUrl);
            imageUrl = imageUrl.split("\\?")[0] ;
        }
        //压缩图片的参数
        imageUrl = imageUrl + "?imageView2/2/w/1080/h/10800/format/jpg";
        BufferedImage largeImage = loadImageWithCache(imageUrl);
        BufferedImage qrCodeImage = loadImageWithReader(qrCodeUrl);
        if (largeImage == null || qrCodeImage == null) {
            return null;
        }
        BufferedImage combinedImage = generateImage(largeImage, qrCodeImage, showStyle, lineOne, lineTwo);

//        ImageIO.write(combinedImage, "jpg", new File(OUTPUT_PATH));
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            ImageIO.write(combinedImage, "jpg", baos);
            // 返回字节数组
            return baos.toByteArray();
        }finally {
            qrCodeImage.flush();
            combinedImage.flush();
        }
    }

    private static BufferedImage loadImageWithReader(String url) {
        try {
            URL imageUrl = new URL(url);
            ImageInputStream input = ImageIO.createImageInputStream(imageUrl.openStream());
            Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
            if (readers.hasNext()) {
                ImageReader reader = readers.next();
                reader.setInput(input, true);
                return reader.read(0);
            }
        } catch (IOException e) {
            logger.error("读取异常: {}", url, e);
        }
        return null;
    }


    /**
     * 从缓存中加载图像
     */
    private static BufferedImage loadImageWithCache(String url) {
        return imageCache.get(url, key -> {
            try {
                logger.info("加载图片buffered:{},key:{}", url, key);
                return loadImageWithReader(key);  // 使用读取器方法
            } catch (Exception e) {
                logger.error("获取图片异常", e);
                return null;
            }
        });
    }

    private static BufferedImage generateImage(BufferedImage image, BufferedImage qrCode, int showStyle,String lineOne,String lineTwo) throws Exception {

        logger.info("合成图片开始");
        int width = image.getWidth();
        int height = image.getHeight();
        int qrWidth = QR_WIDTH_REFERENCE;
        if (showStyle == 1) {
            if (height > MAX_HEIGHT_NO_WHITE_SPACE) {
                width = width * MAX_HEIGHT_NO_WHITE_SPACE / height;
                height = MAX_HEIGHT_NO_WHITE_SPACE;
            }
        } else {
            if (height > MAX_HEIGHT_WITH_WHITE_SPACE) {
                width = width * MAX_HEIGHT_WITH_WHITE_SPACE / height;
                height = MAX_HEIGHT_WITH_WHITE_SPACE;
            }
            width = Math.max(width, MIN_WIDTH);
        }
        int finalHeight = height + (showStyle == 1 ? 0 : WHITE_SPACE_HEIGHT);

        BufferedImage combinedImage = new BufferedImage(width, finalHeight, BufferedImage.TYPE_INT_RGB);

        BufferedImage resizedImage = Thumbnails.of(image)
                .size(width, height).asBufferedImage();

        Graphics2D g = combinedImage.createGraphics();
        g.setColor(Color.WHITE);
        g.drawImage(resizedImage, 0, 1, null);
        if (showStyle == 1) {
            qrWidth = width * QR_WIDTH_REFERENCE / 750;
        }
        BufferedImage resizedQRCode = Thumbnails.of(qrCode).size(qrWidth, qrWidth).asBufferedImage();

        if (showStyle == 1) {
            // 不需要留白时，QR码距离底部20px
            g.drawImage(resizedQRCode, width - qrWidth - 20, finalHeight - qrWidth - 20, null);
        } else {
            // 需要留白时
            addWhiteSpace(g, width, finalHeight, resizedQRCode, qrWidth, lineOne, lineTwo);
        }

        g.dispose();
        logger.info("合成图片结束");
        return combinedImage;
    }

    private static void addWhiteSpace(Graphics2D g, int width, int finalHeight, BufferedImage qrCode, int qrWidth,String lineOne,String lineTwo) {
        // 添加白色背景
        g.setColor(Color.WHITE);
        g.fillRect(0, finalHeight - WHITE_SPACE_HEIGHT, width, WHITE_SPACE_HEIGHT);

        // 添加门店名称，距底部88px
        g.setColor(new Color(36, 40, 53));
        g.setFont(new Font("Arial", Font.PLAIN, 30));
        drawSingleLineText(g, lineOne, 30, finalHeight - WHITE_SPACE_HEIGHT + 72, width - 196); // 留出左右边距

        // 添加推荐人信息，距底部40px
        g.setColor(new Color(151, 155, 165));
        g.setFont(new Font("Arial", Font.PLAIN, 26));
        drawSingleLineText(g, lineTwo, 30, finalHeight - WHITE_SPACE_HEIGHT + 120, width - 196); // 留出左右边距

        // 添加二维码，距底部12px
        int qrBottomPadding = 12;
        g.drawImage(qrCode, width - qrWidth - qrBottomPadding, finalHeight - qrWidth - qrBottomPadding, null);
    }

    private static void drawSingleLineText(Graphics2D g, String text, int x, int y, int maxWidth) {
        FontMetrics metrics = g.getFontMetrics(g.getFont());
        String truncatedText = text;

        // 计算文本宽度并进行截断
        if (metrics.stringWidth(text) > maxWidth) {
            while (metrics.stringWidth(truncatedText + "...") > maxWidth && !truncatedText.isEmpty()) {
                truncatedText = truncatedText.substring(0, truncatedText.length() - 2);
            }
            truncatedText += "..."; // 添加省略号
        }

        g.drawString(truncatedText, x, y);
    }

}
