package top.tqx.demo_1.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import top.tqx.demo_1.config.AiApiConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import top.tqx.demo_1.dto.ImageItem;
import top.tqx.demo_1.dto.ImageListResponse;
import top.tqx.demo_1.dto.ImageStatsResponse;
import top.tqx.demo_1.mapper.ImageMapper;
import top.tqx.demo_1.dto.ImageCreateRequest;
import top.tqx.demo_1.dto.ImageUpdateRequest;
import top.tqx.demo_1.entity.Image;

import java.time.LocalDateTime;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import top.tqx.demo_1.service.ImageService;
import top.tqx.demo_1.service.RagService;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class ImageServiceImpl implements ImageService {

    @Autowired
    private AiApiConfig aiApiConfig;

    @Autowired
    private RagService ragService;

    @Autowired
    private ImageMapper imageMapper;

    @Value("${file.upload.path:./uploads/}")
    private String uploadPath;

    @Value("${file.upload.url-prefix:/files/}")
    private String urlPrefix;

    @Override
    public ImageListResponse getImageList(Integer limit, Integer offset) {
        String url = aiApiConfig.getFullUrl(aiApiConfig.getImages().getList());
        url += "?limit=" + limit + "&offset=" + offset;
        log.info("调用RAG服务获取图片列表: url={}", url);

        try {
            String jsonResponse = ragService.getJsonRequest(url, 30000);
            JsonNode rootNode = ragService.parseJson(jsonResponse);

            ImageListResponse response = new ImageListResponse();
            response.setSuccess(rootNode.has("success") ? rootNode.get("success").asBoolean() : false);

            if (rootNode.has("images") && rootNode.get("images").isArray()) {
                List<ImageItem> images = new ArrayList<>();
                for (JsonNode imageNode : rootNode.get("images")) {
                    ImageItem item = new ImageItem();
                    if (imageNode.has("image_id")) {
                        item.setImageId(imageNode.get("image_id").asText());
                    }
                    if (imageNode.has("filename")) {
                        item.setFilename(imageNode.get("filename").asText());
                    }
                    if (imageNode.has("collection")) {
                        item.setCollection(imageNode.get("collection").asText());
                    }
                    if (imageNode.has("page")) {
                        item.setPage(imageNode.get("page").asInt());
                    }
                    if (imageNode.has("size")) {
                        item.setSize(imageNode.get("size").asLong());
                    }
                    if (imageNode.has("created_at")) {
                        item.setCreatedAt(imageNode.get("created_at").asText());
                    }
                    images.add(item);
                }
                response.setImages(images);
            }
            if (rootNode.has("total")) {
                response.setTotal(rootNode.get("total").asInt());
            }
            if (rootNode.has("limit")) {
                response.setLimit(rootNode.get("limit").asInt());
            }
            if (rootNode.has("offset")) {
                response.setOffset(rootNode.get("offset").asInt());
            }

            log.info("获取图片列表成功: count={}", response.getImages() != null ? response.getImages().size() : 0);
            return response;

        } catch (Exception e) {
            log.error("调用RAG服务获取图片列表失败: {}", e.getMessage(), e);
            ImageListResponse response = new ImageListResponse();
            response.setSuccess(false);
            response.setImages(new ArrayList<>());
            return response;
        }
    }

    /**
     * 尝试从本地获取图片
     * @param imageId 图片ID
     * @return 图片字节数组，如果未找到返回null
     */
    private byte[] tryGetLocalImage(String imageId) {
        try {
            Image imageRecord = getImageByImageId(imageId);
            if (imageRecord != null && imageRecord.getPath() != null && !imageRecord.getPath().isEmpty()) {
                String dbPath = imageRecord.getPath();
                log.info("尝试从本地路径读取图片: imageId={}, path={}", imageId, dbPath);
                
                // 方案1：如果数据库路径是完整路径且文件存在，直接使用
                Path fullPath = Paths.get(dbPath);
                if (fullPath.isAbsolute() && Files.exists(fullPath)) {
                    byte[] imageBytes = Files.readAllBytes(fullPath);
                    log.info("从本地读取图片成功(完整路径): imageId={}, path={}, size={} bytes", 
                            imageId, dbPath, imageBytes.length);
                    return imageBytes;
                }
                
                // 方案2：如果数据库路径是相对路径，相对于 uploadPath
                Path tryPath = Paths.get(uploadPath, dbPath);
                if (Files.exists(tryPath)) {
                    byte[] imageBytes = Files.readAllBytes(tryPath);
                    log.info("从本地读取图片成功(相对路径): imageId={}, path={}, size={} bytes", 
                            imageId, tryPath, imageBytes.length);
                    return imageBytes;
                }
                
                // 方案3：兼容旧版代码，尝试其他可能的路径
                String filename = dbPath.startsWith("/img/") ? dbPath.substring(5) : dbPath;
                String[] possibleDirs = {
                    "./img",
                    System.getProperty("user.home") + "/img",
                    System.getProperty("java.io.tmpdir") + "/img",
                    "/tmp/img"
                };
                
                for (String dir : possibleDirs) {
                    Path backupPath = Paths.get(dir, filename);
                    if (Files.exists(backupPath)) {
                        byte[] imageBytes = Files.readAllBytes(backupPath);
                        log.info("从本地读取图片成功(遍历目录): imageId={}, path={}, size={} bytes", 
                                imageId, backupPath, imageBytes.length);
                        return imageBytes;
                    }
                }
                
                log.warn("本地路径不存在，尝试过的路径: dbPath={}", dbPath);
            }
        } catch (Exception e) {
            log.warn("从本地读取图片失败: imageId={}, error={}", imageId, e.getMessage(), e);
        }
        return null;
    }

    @Override
    public byte[] getImage(String imageId) {
        log.info("获取图片: imageId={}", imageId);
        
        // 1. 首先尝试从数据库查找本地路径（先尝试原始ID）
        byte[] localImage = tryGetLocalImage(imageId);
        if (localImage != null) {
            log.info("从本地获取图片成功: imageId={}", imageId);
            return localImage;
        }
        
        // 2. 如果原始ID没找到，尝试添加.jpg后缀（数据库中存储的格式）
        if (!imageId.toLowerCase().endsWith(".jpg")) {
            localImage = tryGetLocalImage(imageId + ".jpg");
            if (localImage != null) {
                log.info("从本地获取图片成功(带.jpg后缀): imageId={}", imageId);
                return localImage;
            }
        }
        
        // 3. 如果带后缀也没找到，尝试去掉后缀（如果有）
        if (imageId.toLowerCase().endsWith(".jpg") || imageId.toLowerCase().endsWith(".jpeg") ||
            imageId.toLowerCase().endsWith(".png") || imageId.toLowerCase().endsWith(".gif")) {
            int lastDotIndex = imageId.lastIndexOf('.');
            if (lastDotIndex > 0) {
                String imageIdWithoutExt = imageId.substring(0, lastDotIndex);
                localImage = tryGetLocalImage(imageIdWithoutExt);
                if (localImage != null) {
                    log.info("从本地获取图片成功(去掉后缀): imageId={}", imageId);
                    return localImage;
                }
            }
        }
        
        log.warn("本地未找到图片，尝试从AI服务获取: imageId={}", imageId);
        
        // 4. 如果本地没有，从AI服务获取
        String url = aiApiConfig.getFullUrl(aiApiConfig.getImages().getImage());
        
        // 去掉可能的文件后缀
        String cleanImageId = imageId;
        if (cleanImageId.toLowerCase().endsWith(".jpg") || cleanImageId.toLowerCase().endsWith(".jpeg") || 
            cleanImageId.toLowerCase().endsWith(".png") || cleanImageId.toLowerCase().endsWith(".gif")) {
            int lastDotIndex = cleanImageId.lastIndexOf('.');
            if (lastDotIndex > 0) {
                cleanImageId = cleanImageId.substring(0, lastDotIndex);
            }
        }
        
        url = url.replace("{image_id}", cleanImageId);
        log.info("调用RAG服务获取图片: url={}", url);

        try {
            byte[] imageBytes = ragService.getBinaryRequest(url, 30000);
            log.info("从RAG服务获取图片成功: imageId={}, size={}", imageId, imageBytes.length);
            return imageBytes;

        } catch (Exception e) {
            log.error("调用RAG服务获取图片失败: imageId={}, error={}", imageId, e.getMessage());
            // 返回一个占位符或者空数组，而不是抛出异常，避免影响整个页面加载
            log.warn("返回空图片数据作为回退: imageId={}", imageId);
            return new byte[0];
        }
    }

    @Override
    public ImageStatsResponse getImageStats() {
        String url = aiApiConfig.getFullUrl(aiApiConfig.getImages().getStats());
        log.info("调用RAG服务获取图片统计: url={}", url);

        try {
            String jsonResponse = ragService.getJsonRequest(url, 30000);
            JsonNode rootNode = ragService.parseJson(jsonResponse);

            ImageStatsResponse response = new ImageStatsResponse();
            response.setSuccess(rootNode.has("success") ? rootNode.get("success").asBoolean() : false);

            if (rootNode.has("total")) {
                response.setTotal(rootNode.get("total").asInt());
            }
            if (rootNode.has("total_size")) {
                response.setTotalSize(rootNode.get("total_size").asLong());
            }

            log.info("获取图片统计成功: total={}", response.getTotal());
            return response;

        } catch (Exception e) {
            log.error("调用RAG服务获取图片统计失败: {}", e.getMessage(), e);
            ImageStatsResponse response = new ImageStatsResponse();
            response.setSuccess(false);
            return response;
        }
    }

    @Override
    public Image createImage(ImageCreateRequest request) {
        Image image = new Image();
        image.setImageId(request.getImageId());
        image.setFilename(request.getFilename());
        image.setPath(request.getPath());
        image.setSizeBytes(request.getSizeBytes());
        image.setFormat(request.getFormat());
        image.setSource(request.getSource());
        image.setPage(request.getPage());
        image.setPageEnd(request.getPageEnd());
        image.setPageRange(request.getPageRange());
        image.setSection(request.getSection());
        image.setChunkType(request.getChunkType());
        image.setType(request.getType());
        image.setDescription(request.getDescription());
        image.setFullDescription(request.getFullDescription());
        image.setScore(request.getScore());
        image.setCollection(request.getCollection());
        image.setCreateTime(LocalDateTime.now());

        imageMapper.insert(image);
        log.info("创建图片记录成功: id={}, imageId={}", image.getId(), image.getImageId());
        return image;
    }

    @Override
    public Image getImageById(Long id) {
        return imageMapper.selectById(id);
    }

    @Override
    public Image updateImage(Long id, ImageUpdateRequest request) {
        Image image = imageMapper.selectById(id);
        if (image == null) {
            throw new IllegalArgumentException("图片不存在");
        }

        if (request.getFilename() != null) {
            image.setFilename(request.getFilename());
        }
        if (request.getPath() != null) {
            image.setPath(request.getPath());
        }
        if (request.getSizeBytes() != null) {
            image.setSizeBytes(request.getSizeBytes());
        }
        if (request.getFormat() != null) {
            image.setFormat(request.getFormat());
        }
        if (request.getSource() != null) {
            image.setSource(request.getSource());
        }
        if (request.getPage() != null) {
            image.setPage(request.getPage());
        }
        if (request.getCollection() != null) {
            image.setCollection(request.getCollection());
        }

        imageMapper.updateById(image);
        return image;
    }

    @Override
    public boolean deleteImage(Long id) {
        return imageMapper.deleteById(id) > 0;
    }

    @Override
    public int batchDeleteImages(List<Long> ids) {
        return imageMapper.deleteBatchIds(ids);
    }

    @Override
    public Image getImageByImageId(String imageId) {
        LambdaQueryWrapper<Image> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Image::getImageId, imageId);
        return imageMapper.selectOne(queryWrapper);
    }

    @Override
    public boolean existsByImageId(String imageId) {
        LambdaQueryWrapper<Image> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Image::getImageId, imageId);
        return imageMapper.exists(queryWrapper);
    }

    @Override
    public Map<String, Object> getImageInfo(String imageId) {
        String url = aiApiConfig.getFullUrl(aiApiConfig.getImages().getInfo());
        url = url.replace("{image_id}", imageId);
        log.info("调用RAG服务获取图片信息: url={}", url);

        try {
            String jsonResponse = ragService.getJsonRequest(url, 30000);
            JsonNode rootNode = ragService.parseJson(jsonResponse);

            Map<String, Object> info = new HashMap<>();
            if (rootNode.has("image_id")) {
                info.put("image_id", rootNode.get("image_id").asText());
            }
            if (rootNode.has("format")) {
                info.put("format", rootNode.get("format").asText());
            }
            if (rootNode.has("width")) {
                info.put("width", rootNode.get("width").asInt());
            }
            if (rootNode.has("height")) {
                info.put("height", rootNode.get("height").asInt());
            }
            if (rootNode.has("size_bytes")) {
                info.put("size_bytes", rootNode.get("size_bytes").asLong());
            }
            if (rootNode.has("mode")) {
                info.put("mode", rootNode.get("mode").asText());
            }
            if (rootNode.has("url")) {
                info.put("url", rootNode.get("url").asText());
            }

            log.info("获取图片信息成功: imageId={}, info={}", imageId, info);
            return info;

        } catch (Exception e) {
            log.error("调用RAG服务获取图片信息失败: {}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    public Image downloadAndSaveImage(String imageId) {
        log.info("开始下载并保存图片: imageId={}", imageId);

        try {
            if (existsByImageId(imageId)) {
                Image existing = getImageByImageId(imageId);
                log.info("图片已存在于数据库: imageId={}, id={}", imageId, existing.getId());
                return existing;
            }

            Map<String, Object> imageInfo = getImageInfo(imageId);
            if (imageInfo == null) {
                log.warn("无法获取图片信息: imageId={}", imageId);
                return null;
            }

            byte[] imageData = getImage(imageId);
            if (imageData == null || imageData.length == 0) {
                log.warn("无法获取图片数据: imageId={}", imageId);
                return null;
            }

            ImageCreateRequest request = new ImageCreateRequest();
            request.setImageId(imageId);
            request.setFormat((String) imageInfo.get("format"));
            request.setSizeBytes((Long) imageInfo.get("size_bytes"));
            request.setPath((String) imageInfo.get("url"));

            Image image = createImage(request);
            log.info("图片下载并保存成功: imageId={}, dbId={}", imageId, image.getId());
            return image;

        } catch (Exception e) {
            log.error("下载并保存图片失败: imageId={}, error={}", imageId, e.getMessage(), e);
            return null;
        }
    }

    @Override
    public Image downloadAndSaveImageWithMetadata(Map<String, Object> imageMetadata) {
        long startTime = System.currentTimeMillis();
        String operationId = java.util.UUID.randomUUID().toString().substring(0, 8);
        
        log.error("[{}] [{}] ========== 图片保存流程开始 ==========", java.time.LocalDateTime.now(), operationId);

        if (imageMetadata == null || !imageMetadata.containsKey("id")) {
            log.error("[{}] [{}] [文件接收阶段] 失败 - 图片元数据为空或不包含id字段, metadata={}", 
                    java.time.LocalDateTime.now(), operationId, imageMetadata);
            return null;
        }

        String imageId = String.valueOf(imageMetadata.get("id"));
        log.error("[{}] [{}] [文件接收阶段] 成功 - 接收到图片元数据, imageId={}, metadataKeys={}", 
                java.time.LocalDateTime.now(), operationId, imageId, imageMetadata.keySet());
        
        // 处理图片 ID：去掉可能的文件后缀（如 .jpg, .png）
        String cleanImageId = imageId;
        if (cleanImageId.toLowerCase().endsWith(".jpg") || cleanImageId.toLowerCase().endsWith(".jpeg") || 
            cleanImageId.toLowerCase().endsWith(".png") || cleanImageId.toLowerCase().endsWith(".gif") ||
            cleanImageId.toLowerCase().endsWith(".webp")) {
            int lastDotIndex = cleanImageId.lastIndexOf('.');
            if (lastDotIndex > 0) {
                cleanImageId = cleanImageId.substring(0, lastDotIndex);
                log.error("[{}] [{}] [文件接收阶段] 处理 - 去掉图片ID后缀, original={}, clean={}", 
                        java.time.LocalDateTime.now(), operationId, imageId, cleanImageId);
            }
        }
        final String finalImageId = cleanImageId;

        try {
            log.error("[{}] [{}] [数据验证阶段] 开始 - 检查图片是否已存在, imageId={}", java.time.LocalDateTime.now(), operationId, imageId);
            if (existsByImageId(imageId)) {
                Image existing = getImageByImageId(imageId);
                log.error("[{}] [{}] [数据验证阶段] 成功 - 图片已存在于数据库, imageId={}, dbId={}", 
                        java.time.LocalDateTime.now(), operationId, imageId, existing.getId());
                long duration = System.currentTimeMillis() - startTime;
                log.error("[{}] [{}] ========== 图片保存流程结束 - 图片已存在, 耗时={}ms ==========", 
                        java.time.LocalDateTime.now(), operationId, duration);
                return existing;
            }
            log.error("[{}] [{}] [数据验证阶段] 成功 - 图片不存在于数据库, 需要新建, imageId={}", 
                    java.time.LocalDateTime.now(), operationId, imageId);

            log.error("[{}] [{}] [数据转换阶段] 开始 - 构建ImageCreateRequest", java.time.LocalDateTime.now(), operationId);
            ImageCreateRequest request = new ImageCreateRequest();
            request.setImageId(imageId); // 数据库保存原始ID

            if (imageMetadata.containsKey("type")) {
                request.setType(String.valueOf(imageMetadata.get("type")));
                log.debug("[{}] [{}] [数据转换阶段] 设置type={}", java.time.LocalDateTime.now(), operationId, request.getType());
            }
            if (imageMetadata.containsKey("source")) {
                request.setSource(String.valueOf(imageMetadata.get("source")));
                log.debug("[{}] [{}] [数据转换阶段] 设置source={}", java.time.LocalDateTime.now(), operationId, request.getSource());
            }
            if (imageMetadata.containsKey("page")) {
                Object page = imageMetadata.get("page");
                if (page instanceof Number) {
                    request.setPage(((Number) page).intValue());
                } else if (page != null) {
                    request.setPage(Integer.parseInt(page.toString()));
                }
                log.debug("[{}] [{}] [数据转换阶段] 设置page={}", java.time.LocalDateTime.now(), operationId, request.getPage());
            }
            if (imageMetadata.containsKey("page_end")) {
                request.setPageEnd(String.valueOf(imageMetadata.get("page_end")));
                log.debug("[{}] [{}] [数据转换阶段] 设置page_end={}", java.time.LocalDateTime.now(), operationId, request.getPageEnd());
            }
            if (imageMetadata.containsKey("page_range")) {
                request.setPageRange(String.valueOf(imageMetadata.get("page_range")));
                log.debug("[{}] [{}] [数据转换阶段] 设置page_range={}", java.time.LocalDateTime.now(), operationId, request.getPageRange());
            }
            if (imageMetadata.containsKey("section")) {
                request.setSection(String.valueOf(imageMetadata.get("section")));
                log.debug("[{}] [{}] [数据转换阶段] 设置section={}", java.time.LocalDateTime.now(), operationId, request.getSection());
            }
            if (imageMetadata.containsKey("description")) {
                request.setDescription(String.valueOf(imageMetadata.get("description")));
                log.debug("[{}] [{}] [数据转换阶段] 设置description={}", java.time.LocalDateTime.now(), operationId, 
                        request.getDescription() != null ? request.getDescription().substring(0, Math.min(50, request.getDescription().length())) + "..." : "null");
            }
            if (imageMetadata.containsKey("full_description")) {
                request.setFullDescription(String.valueOf(imageMetadata.get("full_description")));
                log.debug("[{}] [{}] [数据转换阶段] 设置full_description长度={}", java.time.LocalDateTime.now(), operationId, 
                        request.getFullDescription() != null ? request.getFullDescription().length() : 0);
            }
            if (imageMetadata.containsKey("score")) {
                Object score = imageMetadata.get("score");
                if (score instanceof Number) {
                    request.setScore(java.math.BigDecimal.valueOf(((Number) score).doubleValue()));
                }
                log.debug("[{}] [{}] [数据转换阶段] 设置score={}", java.time.LocalDateTime.now(), operationId, request.getScore());
            }
            if (imageMetadata.containsKey("chunk_type")) {
                request.setChunkType(String.valueOf(imageMetadata.get("chunk_type")));
                log.debug("[{}] [{}] [数据转换阶段] 设置chunk_type={}", java.time.LocalDateTime.now(), operationId, request.getChunkType());
            }
            log.info("[{}] [{}] [数据转换阶段] 成功 - ImageCreateRequest构建完成", java.time.LocalDateTime.now(), operationId);

            log.error("[{}] [{}] [图片信息获取阶段] 开始 - 调用AI服务获取图片元信息, finalImageId={}", java.time.LocalDateTime.now(), operationId, finalImageId);
            Map<String, Object> aiImageInfo = getImageInfo(finalImageId);
            if (aiImageInfo != null) {
                log.error("[{}] [{}] [图片信息获取阶段] 成功 - 获取到图片信息, format={}, size_bytes={}, width={}, height={}", 
                        java.time.LocalDateTime.now(), operationId, 
                        aiImageInfo.get("format"), aiImageInfo.get("size_bytes"), aiImageInfo.get("width"), aiImageInfo.get("height"));
                
                if (aiImageInfo.containsKey("format") && request.getFormat() == null) {
                    request.setFormat((String) aiImageInfo.get("format"));
                    log.debug("[{}] [{}] [图片信息获取阶段] 补充format={}", java.time.LocalDateTime.now(), operationId, request.getFormat());
                }
                if (aiImageInfo.containsKey("size_bytes") && request.getSizeBytes() == null) {
                    Object sizeBytes = aiImageInfo.get("size_bytes");
                    if (sizeBytes instanceof Number) {
                        request.setSizeBytes(((Number) sizeBytes).longValue());
                    }
                    log.debug("[{}] [{}] [图片信息获取阶段] 补充size_bytes={}", java.time.LocalDateTime.now(), operationId, request.getSizeBytes());
                }
            } else {
                log.warn("[{}] [{}] [图片信息获取阶段] 警告 - 未能获取图片元信息, imageId={}", 
                        java.time.LocalDateTime.now(), operationId, imageId);
            }

            log.error("[{}] [{}] [图片下载阶段] 开始 - 调用AI服务下载图片数据, finalImageId={}", java.time.LocalDateTime.now(), operationId, finalImageId);
            byte[] imageData = getImage(finalImageId);
            if (imageData != null && imageData.length > 0) {
                log.error("[{}] [{}] [图片下载阶段] 成功 - 图片数据下载完成, finalImageId={}, size={} bytes", 
                        java.time.LocalDateTime.now(), operationId, finalImageId, imageData.length);
                
                log.error("[{}] [{}] [本地保存阶段] 开始 - 保存图片到本地目录, imageId={}", java.time.LocalDateTime.now(), operationId, imageId);
                String localPath = saveImageToLocal(imageId, imageData);
                if (localPath != null) {
                    request.setPath(localPath);
                    log.error("[{}] [{}] [本地保存阶段] 成功 - 图片保存到本地, path={}", java.time.LocalDateTime.now(), operationId, localPath);
                    
                    if (request.getSizeBytes() == null) {
                        request.setSizeBytes((long) imageData.length);
                        log.debug("[{}] [{}] [本地保存阶段] 补充size_bytes={}", java.time.LocalDateTime.now(), operationId, request.getSizeBytes());
                    }
                } else {
                    log.error("[{}] [{}] [本地保存阶段] 警告 - 未能保存图片到本地, 将继续保存数据库记录", java.time.LocalDateTime.now(), operationId);
                }
            } else {
                log.error("[{}] [{}] [图片下载阶段] 警告 - 图片数据为空或下载失败, imageId={}", 
                        java.time.LocalDateTime.now(), operationId, imageId);
            }

            log.error("[{}] [{}] [数据库写入前] 开始 - 准备写入数据库, imageId={}, request={}", 
                    java.time.LocalDateTime.now(), operationId, imageId, 
                    request.getImageId() + "," + request.getPath() + "," + request.getFormat());
            
            Image image = createImage(request);
            
            log.error("[{}] [{}] [数据库写入后] 成功 - 图片记录已保存到数据库, imageId={}, dbId={}, path={}, format={}, sizeBytes={}", 
                    java.time.LocalDateTime.now(), operationId, imageId, image.getId(), image.getPath(), image.getFormat(), image.getSizeBytes());

            long duration = System.currentTimeMillis() - startTime;
            log.error("[{}] [{}] ========== 图片保存流程成功完成, 耗时={}ms ==========", 
                    java.time.LocalDateTime.now(), operationId, duration);
            
            return image;

        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            log.error("[{}] [{}] [异常捕获阶段] 失败 - 图片保存流程异常, imageId={}, error={}, stackTrace={}, 耗时={}ms", 
                    java.time.LocalDateTime.now(), operationId, imageId, e.getMessage(), 
                    org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace(e), duration);
            return null;
        }
    }

    private String saveImageToLocal(String imageId, byte[] imageData) {
        try {
            log.debug("[本地保存] 开始 - 准备保存图片到本地, imageId={}, dataSize={} bytes",
                    imageId, imageData.length);
            
            Path imgDir = getImageStorageDir();
            
            if (!Files.exists(imgDir)) {
                Files.createDirectories(imgDir);
            }

            String filename = imageId;
            if (!filename.contains(".")) {
                filename = imageId + ".jpg";
            }
            Path filePath = imgDir.resolve(filename);

            log.debug("[本地保存] 开始写入文件...");
            Files.write(filePath, imageData);
            
            long fileSize = Files.size(filePath);
            log.info("[本地保存] 成功 - 图片已保存到本地, path={}, size={} bytes",
                    filePath.toAbsolutePath(), fileSize);

            // 构建相对路径（相对于 uploadPath），这样数据库里是 img/xxx.jpg
            Path basePath = Paths.get(uploadPath);
            String relativePath = basePath.relativize(filePath).toString().replace("\\", "/");
            log.debug("[本地保存] 返回相对路径: {}", relativePath);
            return relativePath;
            
        } catch (java.io.IOException e) {
            log.error("[本地保存] 失败 - IO异常, imageId={}, error={}", imageId, e.getMessage(), e);
            return null;
        } catch (Exception e) {
            log.error("[本地保存] 失败 - 未知异常, imageId={}, error={}", imageId, e.getMessage(), e);
            return null;
        }
    }

    private Path getImageStorageDir() {
        // 使用配置的 uploadPath + /img 作为图片存储目录
        Path imgDir = Paths.get(uploadPath, "img");
        try {
            if (!Files.exists(imgDir)) {
                Files.createDirectories(imgDir);
                log.info("[存储目录] 创建图片目录: {}", imgDir.toAbsolutePath());
            }
            return imgDir;
        } catch (Exception e) {
            log.error("[存储目录] 无法创建图片目录, 使用临时目录, error={}", e.getMessage());
            // 回退到临时目录
            Path fallbackPath = Paths.get(System.getProperty("java.io.tmpdir")).resolve("img");
            try {
                if (!Files.exists(fallbackPath)) {
                    Files.createDirectories(fallbackPath);
                }
                return fallbackPath;
            } catch (Exception ex) {
                log.error("[存储目录] 无法创建任何目录, error={}", ex.getMessage());
                return Paths.get("/tmp");
            }
        }
    }

    /**
     * 根据图片ID获取Nginx格式的URL
     * @param imageId 图片ID
     * @return Nginx格式的URL，如果找不到则返回null
     */
    public String getNginxUrlByImageId(String imageId) {
        try {
            Image image = getImageByImageId(imageId);
            if (image == null && !imageId.toLowerCase().endsWith(".jpg")) {
                image = getImageByImageId(imageId + ".jpg");
            }
            
            if (image != null && image.getPath() != null) {
                // 从 path 中提取文件名，格式是 img/xxx.jpg
                String dbPath = image.getPath();
                String filename = extractFilenameFromPath(dbPath);
                if (filename != null) {
                    return urlPrefix + "img/" + filename;
                }
            }
        } catch (Exception e) {
            log.warn("获取图片Nginx URL失败: imageId={}, error={}", imageId, e.getMessage());
        }
        return null;
    }

    /**
     * 从文件路径中提取文件名
     */
    private String extractFilenameFromPath(String path) {
        if (path == null || path.isEmpty()) {
            return null;
        }
        try {
            Path filePath = Paths.get(path);
            return filePath.getFileName().toString();
        } catch (Exception e) {
            try {
                int lastSlash = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
                if (lastSlash >= 0 && lastSlash < path.length() - 1) {
                    return path.substring(lastSlash + 1);
                }
            } catch (Exception ex) {
                log.warn("提取文件名失败: path={}", path);
            }
        }
        return null;
    }

    @Override
    public List<Image> findImagesByReference(String docName, Integer page, String chunkId) {
        log.info("查找与引用关联的图片: docName={}, page={}, chunkId={}", docName, page, chunkId);
        
        LambdaQueryWrapper<Image> queryWrapper = new LambdaQueryWrapper<>();
        
        // 尝试通过 docName 和 page 查找
        if (docName != null && !docName.isEmpty()) {
            queryWrapper.eq(Image::getSource, docName);
        }
        if (page != null) {
            queryWrapper.eq(Image::getPage, page);
        }
        
        List<Image> results = imageMapper.selectList(queryWrapper);
        log.info("通过 docName 和 page 找到 {} 张图片", results != null ? results.size() : 0);
        
        return results != null ? results : new ArrayList<>();
    }
}