/**
 * @ProjectName: 智慧评标-主观分助手
 * @Package: com.zhpb.gdyd_zhpb_zgf.service.impl
 * @ClassName: FilePreviewServiceImpl
 * @Description: 文件预览服务实现类
 * @Author: 张志锋
 * @Date: 2025-11-01
 * @Version: 1.0
 * @Copyright: © 2025 智慧评标-主观分助手
 */
package com.zhpb.gdyd_zhpb_zgf.service.impl;

import com.zhpb.gdyd_zhpb_zgf.entity.mysql.File;
import com.zhpb.gdyd_zhpb_zgf.repository.mysql.FileRepository;
import com.zhpb.gdyd_zhpb_zgf.service.FilePreviewService;
import com.zhpb.gdyd_zhpb_zgf.service.FilePathResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;

/**
 * 文件预览服务实现类
 */
@Service
public class FilePreviewServiceImpl implements FilePreviewService {

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

    @Autowired
    private FileRepository fileRepository;

    @Autowired
    private FilePathResolver filePathResolver;

    @Value("${file.preview-path:./previews}")
    private String previewPath;

    @Override
    public InputStream previewPdf(String fileId) throws Exception {
        Optional<File> fileOpt = fileRepository.findByFileId(fileId);
        if (!fileOpt.isPresent()) {
            throw new IllegalArgumentException("文件不存在: " + fileId);
        }

        File file = fileOpt.get();
        
        Path previewCandidate = resolvePreviewFilePath(file.getPreviewPath());
        if (previewCandidate != null) {
            logger.debug("使用预览文件: {}", previewCandidate);
            return Files.newInputStream(previewCandidate);
        }
        
        Path originalPath = resolveOriginalFilePath(file);
        if (originalPath == null || !Files.exists(originalPath)) {
            throw new IOException("文件不存在: " + file.getFilePath());
        }
        
        String extension = file.getFileExtension();
        if (extension != null && extension.equalsIgnoreCase("pdf")) {
            return Files.newInputStream(originalPath);
        }
        
        throw new UnsupportedOperationException("不支持的文件类型: " + extension);
    }

    @Override
    public InputStream previewWord(String fileId) throws Exception {
        Optional<File> fileOpt = fileRepository.findByFileId(fileId);
        if (!fileOpt.isPresent()) {
            throw new IllegalArgumentException("文件不存在: " + fileId);
        }

        File file = fileOpt.get();
        Path originalPath = resolveOriginalFilePath(file);
        String filePath = originalPath != null ? originalPath.toString() : file.getFilePath();
        
        // 如果有预览路径（可能是URL或文件路径），如果是文件路径且存在则使用转换后的PDF
        if (file.getPreviewPath() != null && !file.getPreviewPath().isEmpty()) {
            String previewPathValue = file.getPreviewPath();
            Path previewCandidate = resolvePreviewFilePath(previewPathValue);
            if (previewCandidate != null) {
                logger.debug("使用Word转换后的PDF预览文件: {}", previewCandidate);
                return Files.newInputStream(previewCandidate);
            }
            // 如果是URL格式，说明预览接口已配置，需要查找转换后的PDF文件
        }
        
        // 查找Word转换后的PDF文件（存储在预览目录）
        String extension = file.getFileExtension();
        if (extension != null && (extension.toLowerCase().equals("doc") || 
                                  extension.toLowerCase().equals("docx"))) {
            Path previewDir = Paths.get(previewPath);
            String previewFileName = Paths.get(filePath).getFileName().toString()
                .replaceAll("\\.(doc|docx)$", ".pdf");
            Path convertedPdfPath = previewDir.resolve(fileId + "_" + previewFileName);
            
            if (Files.exists(convertedPdfPath)) {
                logger.debug("使用已转换的PDF文件: {}", convertedPdfPath);
                return Files.newInputStream(convertedPdfPath);
            }
            
            // 如果还没有转换，抛出异常提示需要转换
            throw new UnsupportedOperationException("Word转PDF功能暂未实现，文件类型: " + extension + "，需要先将Word转换为PDF");
        }
        
        throw new UnsupportedOperationException("不支持的文件类型: " + extension);
    }

    @Override
    @Async
    @Transactional
    public void generatePreview(String fileId) {
        try {
            // 先检查是否已经有预览URL（大部分文件在保存时已设置）
            Optional<File> fileOpt = fileRepository.findByFileId(fileId);
            if (!fileOpt.isPresent()) {
                logger.warn("文件不存在，无法生成预览: {}", fileId);
                return;
            }

            File file = fileOpt.get();
            
            // 如果已经有预览URL，直接跳过（大部分文件在保存时已设置）
            if (file.getPreviewPath() != null && !file.getPreviewPath().isEmpty()) {
                // 如果是URL格式，说明已配置，跳过
                if (file.getPreviewPath().startsWith("/api/v1/files/preview/")) {
                    logger.debug("预览URL已配置，跳过生成: {} -> {}", fileId, file.getPreviewPath());
                    return;
                }
                // 如果是旧的文件路径格式，检查文件是否存在
                String previewPathValue = file.getPreviewPath();
                if (previewPathValue.contains(":\\") || 
                    (previewPathValue.startsWith("/") && !previewPathValue.startsWith("/api/"))) {
                    Path previewFilePath = Paths.get(previewPathValue);
                    if (Files.exists(previewFilePath)) {
                        logger.debug("预览文件已存在，跳过生成: {}", fileId);
                        return;
                    }
                }
            }
            
            // 只有没有预览URL的文件才需要设置（主要是旧数据或特殊情况）
            String extension = file.getFileExtension();
            if (extension == null) {
                logger.debug("文件无扩展名，跳过预览生成: {}", fileId);
                return;
            }
            
            String ext = extension.toLowerCase();

            // PDF文件：设置预览接口URL
            if ("pdf".equals(ext)) {
                String previewUrl = "/api/v1/files/stream/pdf/" + fileId;
                file.setPreviewPath(previewUrl);
                fileRepository.save(file);
                logger.info("PDF文件预览URL已设置: {} -> {}", fileId, previewUrl);
                return;
            }

            // Word文件：设置预览接口URL（转换为PDF后预览）
            if ("doc".equals(ext) || "docx".equals(ext)) {
                String previewUrl = "/api/v1/files/preview/word/" + fileId;
                file.setPreviewPath(previewUrl);
                fileRepository.save(file);
                logger.info("Word文件预览URL已设置: {} -> {}", fileId, previewUrl);
                
                // TODO: 实际转换Word到PDF的功能可以在预览时异步处理
                logger.debug("Word转PDF功能将在预览时异步处理: {}", fileId);
            }

        } catch (Exception e) {
            logger.error("生成文件预览失败: {}, 错误: {}", fileId, e.getMessage(), e);
        }
    }

    private Path resolveOriginalFilePath(File file) throws IOException {
        try {
            Optional<Path> resolvedOpt = filePathResolver.resolveExistingPath(
                file.getFilePath(), file.getProjectId(), file.getFileName());
            if (resolvedOpt.isEmpty()) {
                return null;
            }
            Path resolvedPath = resolvedOpt.get();
            String normalized = filePathResolver.normalizeForStorage(resolvedPath);
            if (normalized != null && !normalized.equals(file.getFilePath())) {
                file.setFilePath(normalized);
                fileRepository.save(file);
                logger.info("自动纠正文件路径: {} -> {}", file.getFileId(), normalized);
            }
            return resolvedPath;
        } catch (Exception e) {
            logger.warn("解析文件路径失败: fileId={}, error={}", file.getFileId(), e.getMessage());
            return null;
        }
    }

    private Path resolvePreviewFilePath(String previewPathValue) {
        if (previewPathValue == null || previewPathValue.isBlank()) {
            return null;
        }
        if (previewPathValue.startsWith("/api/")) {
            return null;
        }
        try {
            Path candidate = filePathResolver.resolveStoredPath(previewPathValue);
            if (candidate != null && Files.exists(candidate)) {
                return candidate;
            }
        } catch (Exception ignore) {
            // ignore
        }
        try {
            Path direct = Paths.get(previewPathValue);
            if (Files.exists(direct)) {
                return direct;
            }
        } catch (Exception ignore) {
            // ignore
        }
        return null;
    }
}

