package com.rj.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;

import com.rj.service.MinIOService;
import com.rj.utils.ImageConversionUtil;

import java.util.*;
import java.util.List;
import java.util.ArrayList;

/**
 * 阿里云背景生成API测试类
 * <p>
 * 测试阿里云背景生成服务的API调用功能
 *
 * @author 系统生成
 * @version 1.0
 * @date 2025/1/30
 */
@Slf4j
@SpringBootTest
public class AliyunBackgroundGenerationTest {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private MinIOService minIOService;

    @Autowired
    private ImageConversionUtil imageConversionUtil;

    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 测试阿里云背景生成API调用
     */
    @Test
    public void testAliyunBackgroundGeneration() {
        try {
            log.info("开始测试阿里云背景生成API");

            // 1. 构建请求URL
            String apiUrl = "https://dashscope.aliyuncs.com/api/v1/services/aigc/background-generation/generation/";

            // 2. 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("X-DashScope-Async", "enable");
            headers.set("Authorization", "Bearer " + System.getenv("DASHSCOPE_API_KEY"));
            headers.setContentType(MediaType.APPLICATION_JSON);

            // 3. 构建请求体
            Map<String, Object> requestBody = buildRequestBody();

            // 4. 创建HTTP实体
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

            // 5. 发送请求
            log.info("发送请求到阿里云API: {}", apiUrl);
            log.info("请求体: {}", objectMapper.writeValueAsString(requestBody));

            ResponseEntity<String> response = restTemplate.exchange(
                    apiUrl,
                    HttpMethod.POST,
                    requestEntity,
                    String.class
            );

            // 6. 处理响应
            log.info("响应状态码: {}", response.getStatusCode());
            log.info("响应头: {}", response.getHeaders());
            log.info("响应体: {}", response.getBody());

            // 7. 解析响应 
            if (response.getStatusCode() == HttpStatus.OK) {
                @SuppressWarnings("unchecked")
                Map<String, Object> responseMap = objectMapper.readValue(response.getBody(), Map.class);
                log.info("解析后的响应: {}", responseMap);

                // 提取任务ID 90eeef29-19f7-44a4-894b-7c694cc55b5d
                String taskId = (String) responseMap.get("taskId");
                if (taskId != null) {
                    log.info("任务ID: {}", taskId);
                }
            }

        } catch (Exception e) {
            log.error("测试阿里云背景生成API失败", e);
        }
    }

    /**
     * 构建请求体
     *
     * @return 请求体Map
     */
    private Map<String, Object> buildRequestBody() {
        Map<String, Object> requestBody = new HashMap<>();

        // 设置模型
        requestBody.put("model", "wanx-background-generation-v2");

        // 构建input参数
        Map<String, Object> input = new HashMap<>();
        // 阿里云的原始图片，可以生成，是正确的
//        input.put("base_image_url", "https://vision-poster.oss-cn-shanghai.aliyuncs.com/lllcho.lc/data/test_data/images/main_images/new_main_img/a.png");
//        input.put("base_image_url", "http://101.35.52.237:19005/car/1760605862400_e3a319ba13184fdd9f4a08cdc3e3b30e.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20251016%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251016T091103Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=a2b4ae679552b6cfebcfeee228b84497a6eb458dc061dbf244f533fed41356b0");
        // 转换后的 图片
        input.put("base_image_url", "http://101.35.52.237:19005/car/1760607939127_e5af1be2272f4e5eaab6970d1dddb8e0.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20251016%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251016T094539Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=891cc2b70bfed8425a43edb2f742bbd95e19cce2ff16ed7e6171fc6e312ed7c8");
        input.put("ref_image_url", "http://vision-poster.oss-cn-shanghai.aliyuncs.com/lllcho.lc/data/test_data/images/ref_images/c5e50d27be534709817b2ab080b0162f_0.jpg");
        input.put("ref_prompt", "山脉和晚霞");

        // 构建reference_edge参数
        Map<String, Object> referenceEdge = new HashMap<>();

        // 前景边缘
        java.util.List<String> foregroundEdge = Arrays.asList(
                "https://vision-poster.oss-cn-shanghai.aliyuncs.com/lllcho.lc/data/test_data/images/huaban_soft_edge/6cdd13941cef1b11d885aea1717b983ae566b8efc9094-vcsvxa_fw658webp.png",
                "http://vision-poster.oss-cn-shanghai.aliyuncs.com/lllcho.lc/data/test_data/images/ref_edge/2c36cc4b7da027279e87311dac48fc2d5d784b1e72c0e-x4f1wC_fw658webp.png"
        );
        referenceEdge.put("foreground_edge", foregroundEdge);

        // 背景边缘
        java.util.List<String> backgroundEdge = Arrays.asList(
                "http://vision-poster.oss-cn-shanghai.aliyuncs.com/lllcho.lc/data/test_data/images/ref_edge/0718a9741e07c52ca5506e75c4f2b99e22fff68a4c7d3-P9WGLr_fw658webp.png"
        );
        referenceEdge.put("background_edge", backgroundEdge);

        // 前景边缘提示词
        java.util.List<String> foregroundEdgePrompt = Arrays.asList(
                "粉色桃花",
                "可爱小狗"
        );
        referenceEdge.put("foreground_edge_prompt", foregroundEdgePrompt);

        // 背景边缘提示词
        java.util.List<String> backgroundEdgePrompt = Arrays.asList(
                "树叶"
        );
        referenceEdge.put("background_edge_prompt", backgroundEdgePrompt);

        // input.put("reference_edge", referenceEdge);
        requestBody.put("input", input);

        // 构建parameters参数
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("n", 4);
        parameters.put("ref_prompt_weight", 0.5);
        parameters.put("model_version", "v3");
        requestBody.put("parameters", parameters);

        return requestBody;
    }

    /**
     * 测试简化的背景生成API调用（不包含reference_edge）
     */
    @Test
    public void testSimpleBackgroundGeneration() {
        try {
            log.info("开始测试简化的阿里云背景生成API");

            // 1. 构建请求URL
            String apiUrl = "https://dashscope.aliyuncs.com/api/v1/services/aigc/background-generation/generation/";

            // 2. 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("X-DashScope-Async", "enable");
            headers.set("Authorization", "Bearer " + System.getenv("DASHSCOPE_API_KEY"));
            headers.setContentType(MediaType.APPLICATION_JSON);

            // 3. 构建简化的请求体
            Map<String, Object> requestBody = buildSimpleRequestBody();

            // 4. 创建HTTP实体
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

            // 5. 发送请求
            log.info("发送简化请求到阿里云API: {}", apiUrl);
            log.info("请求体: {}", objectMapper.writeValueAsString(requestBody));

            ResponseEntity<String> response = restTemplate.exchange(
                    apiUrl,
                    HttpMethod.POST,
                    requestEntity,
                    String.class
            );

            // 6. 处理响应
            log.info("响应状态码: {}", response.getStatusCode());
            log.info("响应体: {}", response.getBody());

        } catch (Exception e) {
            log.error("测试简化的阿里云背景生成API失败", e);
        }
    }

    /**
     * 构建简化的请求体（不包含reference_edge）
     *
     * @return 简化的请求体Map
     */
    private Map<String, Object> buildSimpleRequestBody() {
        Map<String, Object> requestBody = new HashMap<>();

        // 设置模型
        requestBody.put("model", "wanx-background-generation-v2");

        // 构建input参数
        Map<String, Object> input = new HashMap<>();
        input.put("base_image_url", "https://vision-poster.oss-cn-shanghai.aliyuncs.com/lllcho.lc/data/test_data/images/main_images/new_main_img/a.png");
        input.put("ref_image_url", "http://vision-poster.oss-cn-shanghai.aliyuncs.com/lllcho.lc/data/test_data/images/ref_images/c5e50d27be534709817b2ab080b0162f_0.jpg");
        input.put("ref_prompt", "山脉和晚霞");

        requestBody.put("input", input);

        // 构建parameters参数
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("n", 1);
        parameters.put("ref_prompt_weight", 0.5);
        parameters.put("model_version", "v3");
        requestBody.put("parameters", parameters);

        return requestBody;
    }

    /**
     * 测试RGBA转换后的背景生成API调用
     */
    @Test
    public void testBackgroundGenerationWithRGBAConversion() {
        try {
            log.info("开始测试带RGBA转换的背景生成API");

            // 模拟使用转换后的RGBA图像URL
            String convertedRefImageUrl = "https://your-minio-domain.com/converted-rgba-image.png?token=xxx";

            // 1. 构建请求URL
            String apiUrl = "https://dashscope.aliyuncs.com/api/v1/services/aigc/background-generation/generation/";

            // 2. 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("X-DashScope-Async", "enable");
            headers.set("Authorization", "Bearer " + System.getenv("DASHSCOPE_API_KEY"));
            headers.setContentType(MediaType.APPLICATION_JSON);

            // 3. 构建请求体（使用转换后的RGBA图像URL）
            Map<String, Object> requestBody = buildRequestBodyWithConvertedImage(convertedRefImageUrl);

            // 4. 创建HTTP实体
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

            // 5. 发送请求
            log.info("发送带RGBA转换的请求到阿里云API: {}", apiUrl);
            log.info("请求体: {}", objectMapper.writeValueAsString(requestBody));

            ResponseEntity<String> response = restTemplate.exchange(
                    apiUrl,
                    HttpMethod.POST,
                    requestEntity,
                    String.class
            );

            // 6. 处理响应
            log.info("响应状态码: {}", response.getStatusCode());
            log.info("响应体: {}", response.getBody());

        } catch (Exception e) {
            log.error("测试带RGBA转换的背景生成API失败", e);
        }
    }

    /**
     * 生成唯一文件名（测试用）
     *
     * @param extension 文件扩展名
     * @return 唯一文件名
     */
    private String generateUniqueFileNameForTest(String extension) {
        long timestamp = System.currentTimeMillis();
        String uuid = java.util.UUID.randomUUID().toString().replace("-", "");
        return timestamp + "_" + uuid + "." + extension;
    }

    /**
     * 完整的图片转换和阿里云API调用流程
     * #########################################################################################################################################################
     */
    @Test
    public void testImageAnalysisAndConversion() {
        try {
            log.info("开始完整的图片转换和阿里云API调用流程");

            // 1. 分析阿里云图片特征（参考）
            String aliyunImageUrl = "https://vision-poster.oss-cn-shanghai.aliyuncs.com/lllcho.lc/data/test_data/images/main_images/new_main_img/a.png";
            //analyzeImageCharacteristics(aliyunImageUrl, "阿里云参考图片");

            // 2. 分析您的原始图片特征
            String yourImageUrl = "http://101.35.52.237:19005/car/1760605862400_e3a319ba13184fdd9f4a08cdc3e3b30e.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20251016%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251016T091103Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=a2b4ae679552b6cfebcfeee228b84497a6eb458dc061dbf244f533fed41356b0";
            String yourImageUrl2 = "http://101.35.52.237:19005/car/1760663602296_153e5c5aed024210909d904a19c9410d.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20251017%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251017T011323Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=ab5908cfb26fde10b4445d67285cbebb061936687443fae59ed3edb7bf6cfaf4";           // analyzeImageCharacteristics(yourImageUrl, "您的原始图片");
            String yourImageUrl3 = "http://101.35.52.237:19005/car/1760664450807_c409152beb0344feb227438ff2c20e73.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20251017%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251017T012731Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=36ee81f8c51826b16af508dc3a90c5af8f951e76575b7a13ff4570c6a92078b5";
            // 3. 转换图片为符合阿里云要求的格式（使用工具类）
            byte[] convertedImageBytes = imageConversionUtil.convertImageToAliyunFormatAdvanced(yourImageUrl3);
            if (convertedImageBytes == null) {
                log.error("图片转换失败，无法继续");
                return;
            }
            log.info("图片转换完成，转换后大小: {} bytes", convertedImageBytes.length);

            // 4. 上传转换后的图片到MinIO
            String minioFileName = uploadImageToMinIO(convertedImageBytes);
            if (minioFileName == null) {
                log.error("上传到MinIO失败，无法继续");
                return;
            }
            log.info("图片上传到MinIO成功，文件名: {}", minioFileName);

            // 4.1 同时保存一份到本地电脑
            String localFilePath = saveImageToLocal(convertedImageBytes, minioFileName);
            if (localFilePath != null) {
                log.info("图片已保存到本地: {}", localFilePath);
            } else {
                log.warn("保存到本地失败，但MinIO上传成功，继续执行");
            }

            // 5. 生成临时访问链接
            String tempUrl = generateTempUrl(minioFileName);
            if (tempUrl == null) {
                log.error("生成临时访问链接失败，无法继续");
                return;
            }
            log.info("生成临时访问链接: {}", tempUrl);

            // 6. 验证转换后的图片特征
            analyzeImageCharacteristics(tempUrl, "转换后的图片");

            // 7. 使用转换后的图片调用阿里云API
            callAliyunAPIWithConvertedImage(tempUrl);

        } catch (Exception e) {
            log.error("完整的图片转换和API调用流程失败", e);
        }
    }

    /**
     * 分析图片特征
     *
     * @param imageUrl  图片URL
     * @param imageName 图片名称
     */
    private void analyzeImageCharacteristics(String imageUrl, String imageName) {
        try {
            log.info("=== 分析{}特征 ===", imageName);

            // 下载图片
            BufferedImage image = downloadImage(imageUrl);
            if (image == null) {
                log.error("无法下载图片: {}", imageUrl);
                return;
            }

            // 分析基本特征
            int width = image.getWidth();
            int height = image.getHeight();
            int type = image.getType();
            int maxDimension = Math.max(width, height);

            log.info("图片尺寸: {}x{}", width, height);
            log.info("图片类型: {} ({})", type, getImageTypeName(type));
            log.info("最大尺寸: {} (是否超过2048: {})", maxDimension, maxDimension > 2048);

            // 分析颜色模式
            analyzeColorMode(image);

            // 分析透明度
            analyzeTransparency(image);

            // 分析文件格式
            analyzeFileFormat(imageUrl);

        } catch (Exception e) {
            log.error("分析图片特征失败: {}", imageUrl, e);
        }
    }

    /**
     * 下载图片
     *
     * @param imageUrl 图片URL
     * @return BufferedImage对象
     */
    private BufferedImage downloadImage(String imageUrl) {
        try {
            URL url = new URL(imageUrl);
            return ImageIO.read(url);
        } catch (Exception e) {
            log.error("下载图片失败: {}", imageUrl, e);
            return null;
        }
    }

    /**
     * 获取图片类型名称
     *
     * @param type 图片类型
     * @return 类型名称
     */
    private String getImageTypeName(int type) {
        switch (type) {
            case BufferedImage.TYPE_INT_RGB:
                return "RGB";
            case BufferedImage.TYPE_INT_ARGB:
                return "ARGB";
            case BufferedImage.TYPE_INT_ARGB_PRE:
                return "ARGB_PRE";
            case BufferedImage.TYPE_4BYTE_ABGR:
                return "ABGR";
            case BufferedImage.TYPE_4BYTE_ABGR_PRE:
                return "ABGR_PRE";
            case BufferedImage.TYPE_3BYTE_BGR:
                return "BGR";
            case BufferedImage.TYPE_BYTE_GRAY:
                return "GRAY";
            case BufferedImage.TYPE_USHORT_555_RGB:
                return "RGB_555";
            case BufferedImage.TYPE_USHORT_565_RGB:
                return "RGB_565";
            default:
                return "UNKNOWN";
        }
    }

    /**
     * 分析颜色模式
     *
     * @param image 图片对象
     */
    private void analyzeColorMode(BufferedImage image) {
        try {
            int width = image.getWidth();
            int height = image.getHeight();

            // 采样分析颜色
            int sampleSize = Math.min(100, Math.min(width, height));
            int stepX = width / sampleSize;
            int stepY = height / sampleSize;

            int transparentPixels = 0;
            int opaquePixels = 0;
            int totalPixels = 0;

            for (int y = 0; y < height; y += stepY) {
                for (int x = 0; x < width; x += stepX) {
                    int rgb = image.getRGB(x, y);
                    int alpha = (rgb >> 24) & 0xFF;

                    if (alpha == 0) {
                        transparentPixels++;
                    } else if (alpha == 255) {
                        opaquePixels++;
                    }
                    totalPixels++;
                }
            }

            double transparentRatio = (double) transparentPixels / totalPixels;
            double opaqueRatio = (double) opaquePixels / totalPixels;

            log.info("透明度分析:");
            log.info("  透明像素比例: {:.2f}%", transparentRatio * 100);
            log.info("  不透明像素比例: {:.2f}%", opaqueRatio * 100);
            log.info("  半透明像素比例: {:.2f}%", (1 - transparentRatio - opaqueRatio) * 100);

        } catch (Exception e) {
            log.error("分析颜色模式失败", e);
        }
    }

    /**
     * 分析透明度
     *
     * @param image 图片对象
     */
    private void analyzeTransparency(BufferedImage image) {
        try {
            int width = image.getWidth();
            int height = image.getHeight();

            boolean hasTransparency = image.getColorModel().hasAlpha();
            log.info("是否支持透明度: {}", hasTransparency);

            // 检查是否有透明像素
            boolean hasTransparentPixels = false;
            for (int y = 0; y < height; y += 10) { // 采样检查
                for (int x = 0; x < width; x += 10) {
                    int rgb = image.getRGB(x, y);
                    int alpha = (rgb >> 24) & 0xFF;
                    if (alpha < 255) {
                        hasTransparentPixels = true;
                        break;
                    }
                }
                if (hasTransparentPixels) break;
            }

            log.info("是否包含透明像素: {}", hasTransparentPixels);

        } catch (Exception e) {
            log.error("分析透明度失败", e);
        }
    }

    /**
     * 分析文件格式
     *
     * @param imageUrl 图片URL
     */
    private void analyzeFileFormat(String imageUrl) {
        try {
            if (imageUrl.startsWith("file://")) {
                String filePath = imageUrl.substring(7);
                File file = new File(filePath);
                if (file.exists()) {
                    log.info("文件大小: {} bytes", file.length());
                    log.info("文件扩展名: {}", getFileExtension(file.getName()));
                }
            } else {
                URL url = new URL(imageUrl);
                try (InputStream inputStream = url.openStream()) {
                    byte[] header = new byte[8];
                    inputStream.read(header);

                    log.info("文件头: {}", bytesToHex(header));

                    // 检查PNG格式
                    if (header[0] == (byte) 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47) {
                        log.info("文件格式: PNG");
                    } else if (header[0] == (byte) 0xFF && header[1] == (byte) 0xD8) {
                        log.info("文件格式: JPEG");
                    } else {
                        log.info("文件格式: 未知");
                    }
                }
            }
        } catch (Exception e) {
            log.error("分析文件格式失败", e);
        }
    }

    /**
     * 字节数组转十六进制字符串
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02X ", b));
        }
        return result.toString();
    }

    /**
     * 获取文件扩展名
     *
     * @param filename 文件名
     * @return 扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || filename.lastIndexOf('.') == -1) {
            return "";
        }
        return filename.substring(filename.lastIndexOf('.') + 1);
    }

    /**
     * 转换图片为符合阿里云要求的格式（返回字节数组）
     * 阿里云要求：主体图像必须为带透明背景的RGBA四通道图像，PNG格式，长边不超过2048像素
     * 
     * 注意：此方法为基础版本，推荐使用 convertImageToAliyunFormatAdvanced 方法获得更好的效果
     *
     * @param imageUrl 原始图片URL
     * @return 转换后的图片字节数组
     */
    private byte[] convertImageToAliyunFormatBytes(String imageUrl) {
        try {
            log.info("开始转换图片为阿里云格式");

            // 1. 下载原始图片
            BufferedImage originalImage = downloadImage(imageUrl);
            if (originalImage == null) {
                log.error("无法下载原始图片");
                return null;
            }

            int width = originalImage.getWidth();
            int height = originalImage.getHeight();
            log.info("原始图片尺寸: {}x{}", width, height);

            // 2. 检查尺寸，如果超过2048则缩放
            if (Math.max(width, height) > 2048) {
                double scale = 2048.0 / Math.max(width, height);
                int newWidth = (int) (width * scale);
                int newHeight = (int) (height * scale);
                log.info("图片尺寸过大，缩放至: {}x{}", newWidth, newHeight);

                BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = scaledImage.createGraphics();
                
                // 设置高质量渲染
                g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                
                // 绘制原始图片到缩放图片上
                g2d.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
                g2d.dispose();

                originalImage = scaledImage;
                width = newWidth;
                height = newHeight;
            }

            // 3. 创建真正的RGBA四通道图像，确保支持透明度
            BufferedImage rgbaImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = rgbaImage.createGraphics();

            // 设置高质量渲染
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

            // 先清空背景为透明
            g2d.setComposite(AlphaComposite.Clear);
            g2d.fillRect(0, 0, width, height);
            
            // 设置正常合成模式
            g2d.setComposite(AlphaComposite.SrcOver);
            
            // 绘制原始图片到RGBA图片上，保持透明度
            g2d.drawImage(originalImage, 0, 0, null);
            g2d.dispose();

            // 4. 验证RGBA图像是否真正支持透明度
            boolean hasTransparency = rgbaImage.getColorModel().hasAlpha();
            log.info("RGBA图像是否支持透明度: {}", hasTransparency);
            
            // 检查是否有透明像素
            boolean hasTransparentPixels = false;
            for (int y = 0; y < height; y += Math.max(1, height / 20)) {
                for (int x = 0; x < width; x += Math.max(1, width / 20)) {
                    int rgb = rgbaImage.getRGB(x, y);
                    int alpha = (rgb >> 24) & 0xFF;
                    if (alpha < 255) {
                        hasTransparentPixels = true;
                        break;
                    }
                }
                if (hasTransparentPixels) break;
            }
            log.info("RGBA图像是否包含透明像素: {}", hasTransparentPixels);

            // 5. 转换为PNG格式字节数组
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            boolean success = ImageIO.write(rgbaImage, "PNG", baos);
            if (success) {
                byte[] imageBytes = baos.toByteArray();
                log.info("图片转换成功，大小: {} bytes", imageBytes.length);
                
                // 验证PNG文件头
                if (imageBytes.length >= 8) {
                    boolean isPng = (imageBytes[0] == (byte) 0x89 && imageBytes[1] == 0x50 && 
                                   imageBytes[2] == 0x4E && imageBytes[3] == 0x47);
                    log.info("输出文件是否为PNG格式: {}", isPng);
                }
                
                return imageBytes;
            } else {
                log.error("图片转换失败");
                return null;
            }

        } catch (Exception e) {
            log.error("转换图片失败", e);
            return null;
        }
    }

    /**
     * 高级图片转换方法，专门处理透明背景需求
     * 确保生成符合阿里云要求的RGBA四通道PNG图像
     *
     * @param imageUrl 原始图片URL
     * @return 转换后的图片字节数组
     */
    private byte[] convertImageToAliyunFormatAdvanced(String imageUrl) {
        try {
            log.info("开始高级图片转换为阿里云格式");

            // 1. 下载原始图片
            BufferedImage originalImage = downloadImage(imageUrl);
            if (originalImage == null) {
                log.error("无法下载原始图片");
                return null;
            }

            int width = originalImage.getWidth();
            int height = originalImage.getHeight();
            log.info("原始图片尺寸: {}x{}, 类型: {}", width, height, getImageTypeName(originalImage.getType()));

            // 2. 检查尺寸，如果超过2048则缩放
            if (Math.max(width, height) > 2048) {
                double scale = 2048.0 / Math.max(width, height);
                int newWidth = (int) (width * scale);
                int newHeight = (int) (height * scale);
                log.info("图片尺寸过大，缩放至: {}x{}", newWidth, newHeight);

                BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = scaledImage.createGraphics();
                
                // 设置最高质量渲染
                g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
                g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                
                // 绘制原始图片到缩放图片上
                g2d.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
                g2d.dispose();

                originalImage = scaledImage;
                width = newWidth;
                height = newHeight;
            }

            // 3. 创建真正的RGBA四通道图像，强制透明背景
            BufferedImage rgbaImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = rgbaImage.createGraphics();

            // 设置最高质量渲染
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);

            // 强制清空背景为完全透明
            g2d.setComposite(AlphaComposite.Clear);
            g2d.fillRect(0, 0, width, height);
            
            // 设置正常合成模式
            g2d.setComposite(AlphaComposite.SrcOver);
            
            // 如果原始图片没有透明背景，使用智能背景移除
            if (!originalImage.getColorModel().hasAlpha() || !hasTransparentPixels(originalImage)) {
                log.info("原始图片没有透明背景，使用智能背景移除");
                
                // 使用智能背景移除算法
                BufferedImage transparentImage = createTransparentBackgroundImage(originalImage);
                
                // 将处理后的图片绘制到RGBA图像上
                g2d.drawImage(transparentImage, 0, 0, null);
                
                // 验证透明像素数量
                int transparentCount = 0;
                for (int y = 0; y < height; y += Math.max(1, height / 50)) {
                    for (int x = 0; x < width; x += Math.max(1, width / 50)) {
                        int rgb = rgbaImage.getRGB(x, y);
                        int alpha = (rgb >> 24) & 0xFF;
                        if (alpha == 0) {
                            transparentCount++;
                        }
                    }
                }
                
                log.info("智能背景移除完成，采样透明像素比例: {:.2f}%", 
                        (double) transparentCount / ((width / Math.max(1, width / 50)) * (height / Math.max(1, height / 50))) * 100);
            } else {
                // 原始图片已有透明度，直接绘制
                g2d.drawImage(originalImage, 0, 0, null);
            }
            
            g2d.dispose();

            // 4. 深度验证RGBA图像
            boolean hasTransparency = rgbaImage.getColorModel().hasAlpha();
            log.info("RGBA图像是否支持透明度: {}", hasTransparency);
            
            // 详细分析透明度
            analyzeTransparency(rgbaImage);
            analyzeColorMode(rgbaImage);

            // 5. 转换为PNG格式字节数组
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            boolean success = ImageIO.write(rgbaImage, "PNG", baos);
            if (success) {
                byte[] imageBytes = baos.toByteArray();
                log.info("高级图片转换成功，大小: {} bytes", imageBytes.length);
                
                // 验证PNG文件头
                if (imageBytes.length >= 8) {
                    boolean isPng = (imageBytes[0] == (byte) 0x89 && imageBytes[1] == 0x50 && 
                                   imageBytes[2] == 0x4E && imageBytes[3] == 0x47);
                    log.info("输出文件是否为PNG格式: {}", isPng);
                    
                    // 检查PNG是否包含透明度信息
                    if (imageBytes.length > 25) {
                        // 检查IHDR chunk中的颜色类型
                        boolean hasAlphaChannel = false;
                        for (int i = 0; i < imageBytes.length - 25; i++) {
                            if (imageBytes[i] == 'I' && imageBytes[i+1] == 'H' && 
                                imageBytes[i+2] == 'D' && imageBytes[i+3] == 'R') {
                                // 颜色类型在第25个字节
                                int colorType = imageBytes[i + 25] & 0xFF;
                                hasAlphaChannel = (colorType == 4 || colorType == 6);
                                log.info("PNG颜色类型: {}, 是否包含Alpha通道: {}", colorType, hasAlphaChannel);
                                break;
                            }
                        }
                    }
                }
                
                return imageBytes;
            } else {
                log.error("高级图片转换失败");
                return null;
            }

        } catch (Exception e) {
            log.error("高级图片转换失败", e);
            return null;
        }
    }

    /**
     * 上传图片到MinIO
     *
     * @param imageBytes 图片字节数组
     * @return MinIO文件名
     */
    private String uploadImageToMinIO(byte[] imageBytes) {
        try {
            log.info("开始上传图片到MinIO");

            // 生成唯一文件名
            String fileName = generateUniqueFileNameForTest("png");

            // 上传到MinIO
            String materialUrl = minIOService.uploadFile(imageBytes, fileName, "image/png");
            if (materialUrl != null) {
                log.info("图片上传到MinIO成功: {}", materialUrl);
                return fileName;
            } else {
                log.error("图片上传到MinIO失败");
                return null;
            }

        } catch (Exception e) {
            log.error("上传图片到MinIO失败", e);
            return null;
        }
    }

    /**
     * 保存图片到本地电脑
     *
     * @param imageBytes    图片字节数组
     * @param minioFileName MinIO文件名（用作本地文件名）
     * @return 本地文件路径
     */
    private String saveImageToLocal(byte[] imageBytes, String minioFileName) {
        try {
            log.info("开始保存图片到本地电脑");

            // 创建本地保存目录
            String localDir = "converted_images";
            File dir = new File(localDir);
            if (!dir.exists()) {
                boolean created = dir.mkdirs();
                if (!created) {
                    log.error("创建本地目录失败: {}", localDir);
                    return null;
                }
                log.info("创建本地目录: {}", localDir);
            }

            // 构建本地文件路径
            String localFileName = "converted_" + minioFileName;
            String localFilePath = localDir + File.separator + localFileName;
            File localFile = new File(localFilePath);

            // 写入文件
            try (FileOutputStream fos = new FileOutputStream(localFile)) {
                fos.write(imageBytes);
                fos.flush();
            }

            log.info("图片保存到本地成功: {}", localFile.getAbsolutePath());
            log.info("本地文件大小: {} bytes", localFile.length());

            return localFile.getAbsolutePath();

        } catch (Exception e) {
            log.error("保存图片到本地失败", e);
            return null;
        }
    }

    /**
     * 生成临时访问链接
     *
     * @param fileName MinIO文件名
     * @return 临时访问链接
     */
    private String generateTempUrl(String fileName) {
        try {
            log.info("开始生成临时访问链接，文件名: {}", fileName);

            String tempUrl = minIOService.generateTempUrl(fileName);
            if (tempUrl != null) {
                log.info("临时访问链接生成成功: {}", tempUrl);
                return tempUrl;
            } else {
                log.error("临时访问链接生成失败");
                return null;
            }

        } catch (Exception e) {
            log.error("生成临时访问链接失败", e);
            return null;
        }
    }

    /**
     * 创建带透明背景的图片（专门处理无透明背景的图片）
     * 使用高级背景移除算法，确保彻底移除背景
     *
     * @param originalImage 原始图片
     * @return 带透明背景的图片
     */
    private BufferedImage createTransparentBackgroundImage(BufferedImage originalImage) {
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();
        
        log.info("开始高级背景移除处理，图片尺寸: {}x{}", width, height);
        
        // 创建RGBA图像
        BufferedImage transparentImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        
        // 第一步：分析图片，找到主体区域
        int[] edgePixels = findEdgePixels(originalImage);
        int leftEdge = edgePixels[0];
        int rightEdge = edgePixels[1];
        int topEdge = edgePixels[2];
        int bottomEdge = edgePixels[3];
        
        log.info("检测到主体区域: 左={}, 右={}, 上={}, 下={}", leftEdge, rightEdge, topEdge, bottomEdge);
        
        // 第二步：分析背景颜色特征
        Color[] backgroundColors = analyzeBackgroundColors(originalImage, edgePixels);
        log.info("分析到背景颜色数量: {}", backgroundColors.length);
        
        // 第三步：高级背景移除处理
        int transparentCount = 0;
        int subjectCount = 0;
        
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int rgb = originalImage.getRGB(x, y);
                int r = (rgb >> 16) & 0xFF;
                int g = (rgb >> 8) & 0xFF;
                int b = rgb & 0xFF;
                
                // 多重判断是否为主体像素
                boolean isSubject = isSubjectPixel(x, y, r, g, b, edgePixels, backgroundColors, originalImage);
                
                if (isSubject) {
                    // 主体区域：保持原色，但可能进行边缘羽化
                    int alpha = calculateEdgeAlpha(x, y, edgePixels, width, height);
                    transparentImage.setRGB(x, y, (alpha << 24) | (rgb & 0xFFFFFF));
                    subjectCount++;
                } else {
                    // 背景区域：设为透明
                    transparentImage.setRGB(x, y, 0x00000000);
                    transparentCount++;
                }
            }
        }
        
        log.info("背景移除完成 - 主体像素: {}, 透明像素: {}, 主体比例: {:.2f}%", 
                subjectCount, transparentCount, (double) subjectCount / (width * height) * 100);
        
        // 第四步：后处理优化
        BufferedImage optimizedImage = postProcessTransparentImage(transparentImage, originalImage);
        
        return optimizedImage;
    }
    
    /**
     * 分析背景颜色特征
     *
     * @param image 图片对象
     * @param edgePixels 主体边缘坐标
     * @return 背景颜色数组
     */
    private Color[] analyzeBackgroundColors(BufferedImage image, int[] edgePixels) {
        int width = image.getWidth();
        int height = image.getHeight();
        int leftEdge = edgePixels[0];
        int rightEdge = edgePixels[1];
        int topEdge = edgePixels[2];
        int bottomEdge = edgePixels[3];
        
        List<Color> backgroundColors = new ArrayList<>();
        
        // 采样边缘区域的背景颜色
        int sampleSize = 100;
        for (int i = 0; i < sampleSize; i++) {
            int x, y;
            
            // 随机选择边缘区域外的像素
            if (i % 4 == 0) {
                // 左侧边缘
                x = (int) (Math.random() * Math.max(1, leftEdge));
                y = (int) (Math.random() * height);
            } else if (i % 4 == 1) {
                // 右侧边缘
                x = rightEdge + (int) (Math.random() * Math.max(1, width - rightEdge));
                y = (int) (Math.random() * height);
            } else if (i % 4 == 2) {
                // 上侧边缘
                x = (int) (Math.random() * width);
                y = (int) (Math.random() * Math.max(1, topEdge));
            } else {
                // 下侧边缘
                x = (int) (Math.random() * width);
                y = bottomEdge + (int) (Math.random() * Math.max(1, height - bottomEdge));
            }
            
            if (x >= 0 && x < width && y >= 0 && y < height) {
                int rgb = image.getRGB(x, y);
                int r = (rgb >> 16) & 0xFF;
                int g = (rgb >> 8) & 0xFF;
                int b = rgb & 0xFF;
                backgroundColors.add(new Color(r, g, b));
            }
        }
        
        return backgroundColors.toArray(new Color[0]);
    }
    
    /**
     * 判断像素是否为主体像素（多重条件判断）
     *
     * @param x 像素X坐标
     * @param y 像素Y坐标
     * @param r 红色值
     * @param g 绿色值
     * @param b 蓝色值
     * @param edgePixels 主体边缘坐标
     * @param backgroundColors 背景颜色数组
     * @param image 原始图片
     * @return 是否为主体像素
     */
    private boolean isSubjectPixel(int x, int y, int r, int g, int b, int[] edgePixels, 
                                 Color[] backgroundColors, BufferedImage image) {
        int leftEdge = edgePixels[0];
        int rightEdge = edgePixels[1];
        int topEdge = edgePixels[2];
        int bottomEdge = edgePixels[3];
        
        // 条件1：位置判断 - 必须在主体区域内
        boolean inSubjectArea = (x >= leftEdge && x <= rightEdge && y >= topEdge && y <= bottomEdge);
        if (!inSubjectArea) {
            return false;
        }
        
        // 条件2：颜色判断 - 不能是明显的背景色
        boolean isBackgroundColor = false;
        for (Color bgColor : backgroundColors) {
            int colorDiff = Math.abs(r - bgColor.getRed()) + 
                           Math.abs(g - bgColor.getGreen()) + 
                           Math.abs(b - bgColor.getBlue());
            if (colorDiff < 30) { // 颜色相似度阈值
                isBackgroundColor = true;
                break;
            }
        }
        
        // 条件3：亮度判断 - 不能是过亮或过暗的背景色
        int brightness = (r + g + b) / 3;
        boolean isExtremeBrightness = brightness > 240 || brightness < 20;
        
        // 条件4：颜色均匀性判断 - 不能是过于均匀的颜色
        boolean isUniformColor = Math.abs(r - g) < 10 && Math.abs(g - b) < 10 && Math.abs(r - b) < 10;
        
        // 条件5：边缘检测 - 检查周围像素的变化
        boolean hasColorVariation = hasSignificantColorVariation(image, x, y);
        
        // 综合判断：必须满足主体区域条件，且不满足背景特征
        return inSubjectArea && !isBackgroundColor && !isExtremeBrightness && 
               (!isUniformColor || hasColorVariation);
    }
    
    /**
     * 检查像素周围是否有显著的颜色变化
     *
     * @param image 图片对象
     * @param x 像素X坐标
     * @param y 像素Y坐标
     * @return 是否有显著颜色变化
     */
    private boolean hasSignificantColorVariation(BufferedImage image, int x, int y) {
        int width = image.getWidth();
        int height = image.getHeight();
        int centerRgb = image.getRGB(x, y);
        int centerR = (centerRgb >> 16) & 0xFF;
        int centerG = (centerRgb >> 8) & 0xFF;
        int centerB = centerRgb & 0xFF;
        
        int variationCount = 0;
        int totalSamples = 0;
        
        // 检查周围8个像素
        for (int dy = -1; dy <= 1; dy++) {
            for (int dx = -1; dx <= 1; dx++) {
                if (dx == 0 && dy == 0) continue;
                
                int nx = x + dx;
                int ny = y + dy;
                
                if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                    int neighborRgb = image.getRGB(nx, ny);
                    int neighborR = (neighborRgb >> 16) & 0xFF;
                    int neighborG = (neighborRgb >> 8) & 0xFF;
                    int neighborB = neighborRgb & 0xFF;
                    
                    int colorDiff = Math.abs(centerR - neighborR) + 
                                   Math.abs(centerG - neighborG) + 
                                   Math.abs(centerB - neighborB);
                    
                    if (colorDiff > 30) { // 颜色差异阈值
                        variationCount++;
                    }
                    totalSamples++;
                }
            }
        }
        
        return totalSamples > 0 && (double) variationCount / totalSamples > 0.3;
    }
    
    /**
     * 计算边缘像素的Alpha值（羽化效果）
     *
     * @param x 像素X坐标
     * @param y 像素Y坐标
     * @param edgePixels 主体边缘坐标
     * @param width 图片宽度
     * @param height 图片高度
     * @return Alpha值
     */
    private int calculateEdgeAlpha(int x, int y, int[] edgePixels, int width, int height) {
        int leftEdge = edgePixels[0];
        int rightEdge = edgePixels[1];
        int topEdge = edgePixels[2];
        int bottomEdge = edgePixels[3];
        
        // 计算到边缘的距离
        int distToLeft = x - leftEdge;
        int distToRight = rightEdge - x;
        int distToTop = y - topEdge;
        int distToBottom = bottomEdge - y;
        
        int minDist = Math.min(Math.min(distToLeft, distToRight), Math.min(distToTop, distToBottom));
        
        // 如果距离边缘很近，进行羽化处理
        if (minDist <= 3) {
            return Math.max(128, 255 - (3 - minDist) * 40); // 边缘羽化
        }
        
        return 255; // 完全不透明
    }
    
    /**
     * 后处理透明图片，进一步优化背景移除效果
     *
     * @param transparentImage 初步处理的透明图片
     * @param originalImage 原始图片
     * @return 优化后的透明图片
     */
    private BufferedImage postProcessTransparentImage(BufferedImage transparentImage, BufferedImage originalImage) {
        int width = transparentImage.getWidth();
        int height = transparentImage.getHeight();
        
        log.info("开始后处理优化，进一步清理残留背景");
        
        BufferedImage optimizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        
        // 复制透明图片
        Graphics2D g2d = optimizedImage.createGraphics();
        g2d.drawImage(transparentImage, 0, 0, null);
        g2d.dispose();
        
        // 多轮清理残留背景
        for (int round = 1; round <= 3; round++) {
            log.info("执行第{}轮背景清理", round);
            
            int cleanedPixels = 0;
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int rgb = optimizedImage.getRGB(x, y);
                    int alpha = (rgb >> 24) & 0xFF;
                    
                    // 只处理非透明像素
                    if (alpha > 0) {
                        int r = (rgb >> 16) & 0xFF;
                        int g = (rgb >> 8) & 0xFF;
                        int b = rgb & 0xFF;
                        
                        // 检查是否应该被清理
                        if (shouldCleanPixel(x, y, r, g, b, optimizedImage, round)) {
                            optimizedImage.setRGB(x, y, 0x00000000); // 设为透明
                            cleanedPixels++;
                        }
                    }
                }
            }
            
            log.info("第{}轮清理完成，清理了{}个像素", round, cleanedPixels);
            
            // 如果清理的像素很少，说明已经比较干净了
            if (cleanedPixels < 100) {
                break;
            }
        }
        
        // 最终验证透明像素比例
        int finalTransparentCount = 0;
        for (int y = 0; y < height; y += Math.max(1, height / 50)) {
            for (int x = 0; x < width; x += Math.max(1, width / 50)) {
                int rgb = optimizedImage.getRGB(x, y);
                int alpha = (rgb >> 24) & 0xFF;
                if (alpha == 0) {
                    finalTransparentCount++;
                }
            }
        }
        
        log.info("后处理完成，最终透明像素比例: {:.2f}%", 
                (double) finalTransparentCount / ((width / Math.max(1, width / 50)) * (height / Math.max(1, height / 50))) * 100);
        
        return optimizedImage;
    }
    
    /**
     * 判断像素是否应该被清理
     *
     * @param x 像素X坐标
     * @param y 像素Y坐标
     * @param r 红色值
     * @param g 绿色值
     * @param b 蓝色值
     * @param image 当前图片
     * @param round 清理轮次
     * @return 是否应该清理
     */
    private boolean shouldCleanPixel(int x, int y, int r, int g, int b, BufferedImage image, int round) {
        int width = image.getWidth();
        int height = image.getHeight();
        
        // 检查周围透明像素的比例
        int transparentNeighbors = 0;
        int totalNeighbors = 0;
        
        for (int dy = -2; dy <= 2; dy++) {
            for (int dx = -2; dx <= 2; dx++) {
                if (dx == 0 && dy == 0) continue;
                
                int nx = x + dx;
                int ny = y + dy;
                
                if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
                    int neighborRgb = image.getRGB(nx, ny);
                    int neighborAlpha = (neighborRgb >> 24) & 0xFF;
                    
                    if (neighborAlpha == 0) {
                        transparentNeighbors++;
                    }
                    totalNeighbors++;
                }
            }
        }
        
        double transparentRatio = totalNeighbors > 0 ? (double) transparentNeighbors / totalNeighbors : 0;
        
        // 根据轮次调整清理策略
        double threshold = 0.6 - (round - 1) * 0.1; // 逐渐降低阈值
        
        // 如果周围透明像素比例很高，且当前像素颜色特征像背景，则清理
        if (transparentRatio > threshold) {
            // 检查颜色特征
            int brightness = (r + g + b) / 3;
            boolean isUniformColor = Math.abs(r - g) < 15 && Math.abs(g - b) < 15 && Math.abs(r - b) < 15;
            boolean isExtremeBrightness = brightness > 220 || brightness < 30;
            
            return isUniformColor || isExtremeBrightness;
        }
        
        return false;
    }

    /**
     * 找到图片的主体边缘
     *
     * @param image 图片对象
     * @return [left, right, top, bottom] 边缘坐标
     */
    private int[] findEdgePixels(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();
        
        int leftEdge = width;
        int rightEdge = 0;
        int topEdge = height;
        int bottomEdge = 0;
        
        // 扫描图片找到非背景像素的边界
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int rgb = image.getRGB(x, y);
                int r = (rgb >> 16) & 0xFF;
                int g = (rgb >> 8) & 0xFF;
                int b = rgb & 0xFF;
                
                // 判断是否为主体像素（非白色/浅色背景）
                boolean isSubject = !(r > 240 && g > 240 && b > 240);
                
                if (isSubject) {
                    if (x < leftEdge) leftEdge = x;
                    if (x > rightEdge) rightEdge = x;
                    if (y < topEdge) topEdge = y;
                    if (y > bottomEdge) bottomEdge = y;
                }
            }
        }
        
        // 确保边界有效
        leftEdge = Math.max(0, leftEdge - 5); // 留一些边距
        rightEdge = Math.min(width - 1, rightEdge + 5);
        topEdge = Math.max(0, topEdge - 5);
        bottomEdge = Math.min(height - 1, bottomEdge + 5);
        
        return new int[]{leftEdge, rightEdge, topEdge, bottomEdge};
    }

    /**
     * 检查图片是否包含透明像素
     *
     * @param image 图片对象
     * @return 是否包含透明像素
     */
    private boolean hasTransparentPixels(BufferedImage image) {
        if (!image.getColorModel().hasAlpha()) {
            return false;
        }
        
        int width = image.getWidth();
        int height = image.getHeight();
        int sampleSize = Math.min(1000, width * height);
        
        for (int i = 0; i < sampleSize; i++) {
            int x = (i * width) / sampleSize;
            int y = (i * height) / sampleSize;
            int rgb = image.getRGB(x, y);
            int alpha = (rgb >> 24) & 0xFF;
            
            if (alpha < 255) {
                return true;
            }
        }
        return false;
    }

    /**
     * 验证图片是否满足阿里云要求
     * 阿里云要求：主体图像必须为带透明背景的RGBA四通道图像，PNG格式，长边不超过2048像素
     *
     * @param imageUrl 图片URL
     * @return 是否满足要求
     */
    private boolean validateImageForAliyun(String imageUrl) {
        try {
            log.info("开始验证图片是否满足阿里云要求: {}", imageUrl);

            // 1. 下载图片
            BufferedImage image = downloadImage(imageUrl);
            if (image == null) {
                log.error("❌ 无法下载图片");
                return false;
            }

            int width = image.getWidth();
            int height = image.getHeight();
            log.info("图片尺寸: {}x{}", width, height);

            // 2. 检查尺寸要求（长边不超过2048像素）
            if (Math.max(width, height) > 2048) {
                log.error("❌ 图片长边超过2048像素: {}", Math.max(width, height));
                return false;
            }
            log.info("✅ 图片尺寸符合要求（长边: {}）", Math.max(width, height));

            // 3. 检查是否为RGBA四通道图像
            boolean hasAlpha = image.getColorModel().hasAlpha();
            if (!hasAlpha) {
                log.error("❌ 图片不支持透明度（非RGBA四通道）");
                return false;
            }
            log.info("✅ 图片支持透明度（RGBA四通道）");

            // 4. 检查图片类型是否为ARGB
            int imageType = image.getType();
            if (imageType != BufferedImage.TYPE_INT_ARGB) {
                log.warn("⚠️ 图片类型不是TYPE_INT_ARGB: {}", getImageTypeName(imageType));
                // 不强制要求，但记录警告
            } else {
                log.info("✅ 图片类型为TYPE_INT_ARGB");
            }

            // 5. 检查是否包含透明像素
            boolean hasTransparentPixels = false;
            int transparentPixelCount = 0;
            int totalPixels = width * height;
            int sampleSize = Math.min(1000, totalPixels); // 采样检查
            
            for (int i = 0; i < sampleSize; i++) {
                int x = (i * width) / sampleSize;
                int y = (i * height) / sampleSize;
                int rgb = image.getRGB(x, y);
                int alpha = (rgb >> 24) & 0xFF;
                
                if (alpha < 255) {
                    hasTransparentPixels = true;
                    transparentPixelCount++;
                }
            }

            if (!hasTransparentPixels) {
                log.error("❌ 图片不包含透明像素，不符合阿里云要求");
                return false;
            }
            log.info("✅ 图片包含透明像素，透明像素比例: {:.2f}%", 
                    (double) transparentPixelCount / sampleSize * 100);

            // 6. 验证文件格式（通过URL检查）
            if (!imageUrl.toLowerCase().contains(".png")) {
                log.error("❌ 图片URL不包含.png扩展名");
                return false;
            }
            log.info("✅ 图片格式为PNG");

            // 7. 检查图片是否可访问
            try {
                URL url = new URL(imageUrl);
                url.openConnection().connect();
                log.info("✅ 图片URL可访问");
            } catch (Exception e) {
                log.error("❌ 图片URL不可访问: {}", e.getMessage());
                return false;
            }

            log.info("🎉 图片完全满足阿里云要求！");
            return true;

        } catch (Exception e) {
            log.error("验证图片时发生错误", e);
            return false;
        }
    }

    /**
     * 使用转换后的图片调用阿里云API
     *
     * @param convertedImageUrl 转换后的图片URL
     */
    private void callAliyunAPIWithConvertedImage(String convertedImageUrl) {
        try {
            log.info("开始使用转换后的图片调用阿里云API: {}", convertedImageUrl);

            // 1. 构建请求URL
            String apiUrl = "https://dashscope.aliyuncs.com/api/v1/services/aigc/background-generation/generation/";

            // 2. 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.set("X-DashScope-Async", "enable");
            headers.set("Authorization", "Bearer " + System.getenv("DASHSCOPE_API_KEY"));
            headers.setContentType(MediaType.APPLICATION_JSON);

            // 2.5. 验证转换后的图片是否满足阿里云要求
            if (!validateImageForAliyun(convertedImageUrl)) {
                log.error("转换后的图片不满足阿里云要求，无法继续调用API");
                return;
            }
            log.info("✅ 图片验证通过，满足阿里云要求");

            // 3. 构建请求体（使用转换后的图片URL）
            Map<String, Object> requestBody = buildRequestBodyWithConvertedImage(convertedImageUrl);

            // 4. 创建HTTP实体
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

            // 5. 发送请求
            log.info("发送请求到阿里云API: {}", apiUrl);
            log.info("请求体: {}", objectMapper.writeValueAsString(requestBody));

            ResponseEntity<String> response = restTemplate.exchange(
                    apiUrl,
                    HttpMethod.POST,
                    requestEntity,
                    String.class
            );

            // 6. 处理响应
            log.info("响应状态码: {}", response.getStatusCode());
            log.info("响应体: {}", response.getBody());
            //7. 获取生成结果 ，根据task id
            if (response.getStatusCode() == HttpStatus.OK) {

                String responseBody = response.getBody();
                JSONObject responseJson = JSON.parseObject(responseBody);


                String taskId = responseJson.getJSONObject("output").getString("task_id");
                log.info("阿里云任务ID: {}", taskId);
                log.info("✅ 使用转换后的图片成功调用阿里云API！");


                for (int i = 0; i < 10; i++) {
                    Thread.sleep(1000 * 30); //30秒
                    // 调用阿里云API检查任务状态
                    String resultUrl = "https://dashscope.aliyuncs.com/api/v1/tasks/" + taskId;

                    HttpHeaders resultheaders = new HttpHeaders();
                    resultheaders.set("Authorization", "Bearer " + System.getenv("DASHSCOPE_API_KEY"));
                    resultheaders.set("Content-Type", "application/json");

                    HttpEntity<String> entity = new HttpEntity<>(resultheaders);

                    ResponseEntity<String> resultResponse = restTemplate.exchange(
                            resultUrl,
                            HttpMethod.GET,
                            entity,
                            String.class
                    );

                    if (resultResponse.getStatusCode().is2xxSuccessful()) {
                        String resultResponse22 = resultResponse.getBody();
                        log.info("阿里云API响应: {}", resultResponse22);

                    } else {
                        log.error("阿里云API调用失败，状态码: {}, resultResponse: {}", response.getStatusCode(), resultResponse);
                    }
                }
            }

        } catch (Exception e) {
            log.error("使用转换后的图片调用阿里云API失败", e);
        }
    }

    /**
     * 构建使用转换后图片的请求体
     *
     * @param convertedImageUrl 转换后的图片URL
     * @return 请求体Map
     */
    private Map<String, Object> buildRequestBodyWithConvertedImage(String convertedImageUrl) {
        Map<String, Object> requestBody = new HashMap<>();

        // 设置模型
        requestBody.put("model", "wanx-background-generation-v2");

        // 构建input参数
        Map<String, Object> input = new HashMap<>();
        input.put("base_image_url", convertedImageUrl); // 使用转换后的图片URL
        input.put("ref_image_url", "http://vision-poster.oss-cn-shanghai.aliyuncs.com/lllcho.lc/data/test_data/images/ref_images/c5e50d27be534709817b2ab080b0162f_0.jpg");
        input.put("ref_prompt", "山脉和晚霞");

        requestBody.put("input", input);

        // 构建parameters参数
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("n", 1);
        parameters.put("ref_prompt_weight", 0.5);
        parameters.put("model_version", "v3");
        requestBody.put("parameters", parameters);

        return requestBody;
    }

    /**
     * 转换图片为符合阿里云要求的格式（保存到本地文件）
     *
     * @param imageUrl 原始图片URL
     * @return 转换后的图片路径
     */
    private String convertImageToAliyunFormat(String imageUrl) {
        try {
            log.info("开始转换图片为阿里云格式");

            // 1. 下载原始图片
            BufferedImage originalImage = downloadImage(imageUrl);
            if (originalImage == null) {
                log.error("无法下载原始图片");
                return null;
            }

            int width = originalImage.getWidth();
            int height = originalImage.getHeight();

            // 2. 检查尺寸，如果超过2048则缩放
            if (Math.max(width, height) > 2048) {
                double scale = 2048.0 / Math.max(width, height);
                int newWidth = (int) (width * scale);
                int newHeight = (int) (height * scale);
                log.info("图片尺寸过大，缩放至: {}x{}", newWidth, newHeight);

                BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
                Graphics2D g2d = scaledImage.createGraphics();
                g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
                g2d.dispose();

                originalImage = scaledImage;
                width = newWidth;
                height = newHeight;
            }

            // 3. 转换为RGBA格式（确保有Alpha通道）
            BufferedImage rgbaImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = rgbaImage.createGraphics();

            // 设置高质量渲染
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            // 绘制原始图片到RGBA图片上
            g2d.drawImage(originalImage, 0, 0, null);
            g2d.dispose();

            // 4. 保存为PNG格式
            String outputPath = "converted_image_" + System.currentTimeMillis() + ".png";
            File outputFile = new File(outputPath);

            boolean success = ImageIO.write(rgbaImage, "PNG", outputFile);
            if (success) {
                log.info("图片转换成功，保存至: {}", outputFile.getAbsolutePath());
                return outputFile.getAbsolutePath();
            } else {
                log.error("图片保存失败");
                return null;
            }

        } catch (Exception e) {
            log.error("转换图片失败", e);
            return null;
        }
    }

    /**
     * 测试使用转换后的图片进行背景生成（包含本地保存）
     */
    @Test
    public void testBackgroundGenerationWithConvertedImage() {
        try {
            log.info("开始测试使用转换后的图片进行背景生成");

            // 1. 转换图片为字节数组（使用工具类）
            String originalImageUrl = "http://101.35.52.237:19005/car/1760605862400_e3a319ba13184fdd9f4a08cdc3e3b30e.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minioadmin%2F20251016%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20251016T091103Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=a2b4ae679552b6cfebcfeee228b84497a6eb458dc061dbf244f533fed41356b0";
            byte[] convertedImageBytes = imageConversionUtil.convertImageToAliyunFormatAdvanced(originalImageUrl);

            if (convertedImageBytes == null) {
                log.error("图片转换失败，无法继续测试");
                return;
            }
            log.info("图片转换完成，转换后大小: {} bytes", convertedImageBytes.length);

            // 2. 上传到MinIO
            String minioFileName = uploadImageToMinIO(convertedImageBytes);
            if (minioFileName == null) {
                log.error("上传到MinIO失败，无法继续测试");
                return;
            }
            log.info("图片上传到MinIO成功，文件名: {}", minioFileName);

            // 3. 同时保存到本地
            String localFilePath = saveImageToLocal(convertedImageBytes, minioFileName);
            if (localFilePath != null) {
                log.info("图片已保存到本地: {}", localFilePath);
            } else {
                log.warn("保存到本地失败，但MinIO上传成功，继续执行");
            }

            // 4. 生成临时访问链接
            String tempUrl = generateTempUrl(minioFileName);
            if (tempUrl == null) {
                log.error("生成临时访问链接失败，无法继续测试");
                return;
            }
            log.info("生成临时访问链接: {}", tempUrl);

            // 5. 使用转换后的图片URL进行测试
            callAliyunAPIWithConvertedImage(tempUrl);

        } catch (Exception e) {
            log.error("测试转换后的图片背景生成失败", e);
        }
    }
}
