package org.xyzh.ai.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.xyzh.ai.client.DifyApiClient;
import org.xyzh.ai.client.dto.DocumentStatusResponse;
import org.xyzh.api.ai.dto.DifyFileInfo;
import org.xyzh.ai.client.dto.DocumentUploadRequest;
import org.xyzh.ai.client.dto.DocumentUploadResponse;
import org.xyzh.ai.config.DifyConfig;
import org.xyzh.ai.exception.DifyException;
import org.xyzh.ai.mapper.AiAgentConfigMapper;
import org.xyzh.ai.mapper.AiKnowledgeMapper;
import org.xyzh.ai.mapper.AiUploadFileMapper;
import org.xyzh.api.ai.file.AiUploadFileService;
import org.xyzh.api.file.FileService;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageDomain;
import org.xyzh.common.core.page.PageParam;
import org.xyzh.common.dto.ai.TbAiAgentConfig;
import org.xyzh.common.dto.ai.TbAiKnowledge;
import org.xyzh.common.dto.ai.TbAiUploadFile;
import org.xyzh.common.dto.system.TbSysFile;
import org.xyzh.common.dto.user.TbSysUser;
import org.xyzh.system.utils.LoginUtil;

import java.io.File;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @description AI文件上传服务实现
 * @filename AiUploadFileServiceImpl.java
 * @author AI Assistant
 * @copyright xyzh
 * @since 2025-11-04
 */
@Slf4j
@Service
public class AiUploadFileServiceImpl implements AiUploadFileService {

    @Autowired
    private AiUploadFileMapper uploadFileMapper;

    @Autowired
    private AiKnowledgeMapper knowledgeMapper;

    @Autowired
    private DifyApiClient difyApiClient;

    @Autowired
    private DifyConfig difyConfig;

    @Autowired
    private AiAgentConfigMapper agentConfigMapper;

    @Autowired
    private FileService fileService;

    // 异步处理线程池
    private final ExecutorService executorService = Executors.newFixedThreadPool(5);

    @Override
    public ResultDomain<Map<String, Object>> uploadFileForChat(MultipartFile file, String agentId) {
        ResultDomain<Map<String, Object>> resultDomain = new ResultDomain<>();

        try {
            // 1. 参数验证
            if (file == null || file.isEmpty()) {
                resultDomain.fail("文件不能为空");
                return resultDomain;
            }
            if (!StringUtils.hasText(agentId)) {
                resultDomain.fail("智能体ID不能为空");
                return resultDomain;
            }

            // 2. 获取当前用户
            TbSysUser currentUser = LoginUtil.getCurrentUser();
            if (currentUser == null) {
                resultDomain.fail("用户未登录");
                return resultDomain;
            }

            // 3. 验证文件类型和大小
            String originalFilename = file.getOriginalFilename();
            if (!isValidFileType(originalFilename)) {
                resultDomain.fail("不支持的文件类型");
                return resultDomain;
            }

            long maxSize = difyConfig.getUpload().getMaxSize() * 1024 * 1024; // MB转字节
            if (file.getSize() > maxSize) {
                resultDomain.fail("文件大小超过限制: " + (maxSize / 1024 / 1024) + "MB");
                return resultDomain;
            }

            // 4. 获取智能体配置
            TbAiAgentConfig agent = agentConfigMapper.selectAgentConfigById(agentId);
            if (agent == null || agent.getDeleted()) {
                resultDomain.fail("智能体不存在");
                return resultDomain;
            }

            // 5. 先保存到系统文件表（永久存储）
            ResultDomain<TbSysFile> uploadResult = fileService.uploadFile(
                    file,
                    "ai-agent", // 模块名
                    agentId, // 业务ID（智能体ID）
                    currentUser.getID() // 上传者
            );

            if (!uploadResult.isSuccess() || uploadResult.getData() == null) {
                resultDomain.fail("保存文件失败: " + uploadResult.getMessage());
                return resultDomain;
            }

            TbSysFile sysFile = (TbSysFile) uploadResult.getData();
            log.info("文件已保存到系统文件表: sysFileId={}, fileName={}", sysFile.getID(), sysFile.getOriginalName());

            // 6. 获取已保存文件的File对象，直接用于上传到Dify（不需要再保存临时文件）
            File fileToUpload = fileService.getFileByRelativePath(sysFile.getFilePath());

            try {
                // 7. 调用Dify API上传文件
                DifyFileInfo difyResponse = difyApiClient.uploadFileForChat(
                        fileToUpload,
                        originalFilename,
                        currentUser.getID(),
                        agent.getDifyApiKey());

                // 9. 转换为前端需要的格式，包含系统文件ID和文件路径
                Map<String, Object> fileInfo = new HashMap<>();
                fileInfo.put("id", difyResponse.getId()); // Dify文件ID
                fileInfo.put("sys_file_id", sysFile.getID()); // 系统文件ID（重要：用于关联消息）
                fileInfo.put("file_path", sysFile.getFilePath()); // 文件路径（重要：用于保存记录）
                fileInfo.put("name", difyResponse.getName());
                fileInfo.put("size", difyResponse.getSize());
                fileInfo.put("extension", difyResponse.getExtension());
                fileInfo.put("mime_type", difyResponse.getMimeType());
                fileInfo.put("type", getFileType(originalFilename));
                fileInfo.put("transfer_method", "local_file");
                fileInfo.put("upload_file_id", difyResponse.getId()); // Dify上传文件ID
                fileInfo.put("file_url", sysFile.getFileUrl()); // 文件访问URL

                log.info("对话文件上传成功: sysFileId={}, difyFileId={}", sysFile.getID(), difyResponse.getId());
                resultDomain.success("文件上传成功", fileInfo);
                return resultDomain;

            } catch (DifyException e) {
                log.error("上传文件到Dify失败", e);
                resultDomain.fail("上传文件失败: " + e.getMessage());
                return resultDomain;
            } catch (Exception e) {
                log.error("上传文件异常", e);
                resultDomain.fail("上传文件异常: " + e.getMessage());
                return resultDomain;
            }

        } catch (Exception e) {
            log.error("文件上传处理异常", e);
            resultDomain.fail("文件上传处理异常: " + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbAiUploadFile> uploadToKnowledge(
            String knowledgeId,
            MultipartFile file,
            String indexingTechnique) {

        ResultDomain<TbAiUploadFile> resultDomain = new ResultDomain<>();

        try {
            // 1. 参数验证
            if (!StringUtils.hasText(knowledgeId)) {
                resultDomain.fail("知识库ID不能为空");
                return resultDomain;
            }
            if (file == null || file.isEmpty()) {
                resultDomain.fail("文件不能为空");
                return resultDomain;
            }

            // 2. 验证文件类型和大小
            String originalFilename = file.getOriginalFilename();
            if (!isValidFileType(originalFilename)) {
                resultDomain.fail("不支持的文件类型");
                return resultDomain;
            }

            long maxSize = difyConfig.getUpload().getMaxSize() * 1024 * 1024; // MB转字节
            if (file.getSize() > maxSize) {
                resultDomain.fail("文件大小超过限制: " + (maxSize / 1024 / 1024) + "MB");
                return resultDomain;
            }

            // 3. 查询知识库信息
            TbAiKnowledge knowledge = knowledgeMapper.selectKnowledgeById(knowledgeId);
            if (knowledge == null || knowledge.getDeleted()) {
                resultDomain.fail("知识库不存在");
                return resultDomain;
            }

            if (!StringUtils.hasText(knowledge.getDifyDatasetId())) {
                resultDomain.fail("知识库未关联Dify Dataset");
                return resultDomain;
            }

            // 4. 获取当前用户
            TbSysUser currentUser = LoginUtil.getCurrentUser();
            if (currentUser == null) {
                resultDomain.fail("用户未登录");
                return resultDomain;
            }

            // 5. 先保存到系统文件表（永久存储）
            ResultDomain<TbSysFile> uploadResult = fileService.uploadFile(
                    file,
                    "ai-knowledge", // 模块名
                    knowledgeId, // 业务ID（知识库ID）
                    currentUser.getID() // 上传者
            );

            if (!uploadResult.isSuccess() || uploadResult.getData() == null) {
                resultDomain.fail("保存文件失败: " + uploadResult.getMessage());
                return resultDomain;
            }

            TbSysFile sysFile = (TbSysFile) uploadResult.getData();
            log.info("文件已保存到系统文件表: sysFileId={}, fileName={}", sysFile.getID(), sysFile.getOriginalName());

            // 6. 获取已保存文件的File对象，直接用于上传到Dify
            File fileToUpload = fileService.getFileByRelativePath(sysFile.getFilePath());

            // 7. 上传到Dify
            DocumentUploadRequest uploadRequest = new DocumentUploadRequest();
            uploadRequest.setName(originalFilename);

            if (!StringUtils.hasText(indexingTechnique)) {
                indexingTechnique = knowledge.getDifyIndexingTechnique();
            }
            uploadRequest.setIndexingTechnique(indexingTechnique);

            DocumentUploadResponse difyResponse = difyApiClient.uploadDocumentByFile(
                    knowledge.getDifyDatasetId(),
                    fileToUpload,
                    originalFilename,
                    uploadRequest);

            // 8. 保存到本地数据库
            TbAiUploadFile uploadFile = new TbAiUploadFile();
            uploadFile.setID(UUID.randomUUID().toString());
            uploadFile.setUserID(currentUser.getID());
            uploadFile.setKnowledgeId(knowledgeId);
            uploadFile.setSysFileId(sysFile.getID()); // 关联系统文件ID
            uploadFile.setFileName(originalFilename);
            uploadFile.setFilePath(sysFile.getFilePath()); // 保存系统文件的相对路径
            uploadFile.setFileSize(file.getSize());
            uploadFile.setFileType(getFileExtension(originalFilename));
            uploadFile.setDifyDocumentId(difyResponse.getDocument().getId());
            uploadFile.setDifyBatchId(difyResponse.getBatch());
            uploadFile.setStatus(difyResponse.getDocument().getIndexingStatus() == "completed" ? 2 : 1); // 1=处理中
            uploadFile.setChunkCount(difyResponse.getDocument().getWordCount() != null ? difyResponse.getDocument().getWordCount() : 0);
            uploadFile.setEnabled(difyResponse.getDocument().getEnabled() != null ? difyResponse.getDocument().getEnabled() : true);
            uploadFile.setDisplayStatus(difyResponse.getDocument().getDisplayStatus());
            uploadFile.setCreateTime(new Date());
            uploadFile.setUpdateTime(new Date());
            uploadFile.setDeleted(false);

            int rows = uploadFileMapper.insertUploadFile(uploadFile);
            knowledge.setDocumentCount(knowledge.getDocumentCount() + 1);
            int knowledgeRows = knowledgeMapper.updateKnowledge(knowledge);
            if (rows > 0) {
                log.info("知识库文件上传成功: uploadFileId={}, sysFileId={}, fileName={}",
                        uploadFile.getID(), sysFile.getID(), originalFilename);

                // 9. 异步更新向量化状态
                asyncUpdateVectorStatus(uploadFile.getID());
                
                resultDomain.success("文件上传成功", uploadFile);
                if (knowledgeRows <=0) {
                    resultDomain.setMessage("知识库文件数量更新失败");
                }
                return resultDomain;
            } else {
                resultDomain.fail("保存文件记录失败");
                return resultDomain;
            }

        } catch (DifyException e) {
            log.error("上传文件到Dify失败", e);
            resultDomain.fail("上传文件失败: " + e.getMessage());
            return resultDomain;
        } catch (Exception e) {
            log.error("上传文件异常", e);
            resultDomain.fail("上传文件异常: " + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbAiUploadFile> batchUploadToKnowledge(
            String knowledgeId,
            List<MultipartFile> files,
            String indexingTechnique) {

        ResultDomain<TbAiUploadFile> resultDomain = new ResultDomain<>();

        try {
            if (files == null || files.isEmpty()) {
                resultDomain.fail("文件列表不能为空");
                return resultDomain;
            }

            List<TbAiUploadFile> uploadedFiles = new ArrayList<>();
            List<String> failedFiles = new ArrayList<>();

            for (MultipartFile file : files) {
                ResultDomain<TbAiUploadFile> uploadResult = uploadToKnowledge(knowledgeId, file, indexingTechnique);

                if (uploadResult.isSuccess()) {
                    uploadedFiles.add(uploadResult.getData());
                } else {
                    failedFiles.add(file.getOriginalFilename() + ": " + uploadResult.getMessage());
                }
            }
            TbAiKnowledge knowledge = knowledgeMapper.selectKnowledgeById(knowledgeId);
            knowledge.setDocumentCount(knowledge.getDocumentCount() + uploadedFiles.size());
            int knowledgeRows = knowledgeMapper.updateKnowledge(knowledge);
            if (!failedFiles.isEmpty()) {
                String message = "部分文件上传失败: " + String.join(", ", failedFiles);
                log.warn(message);
                resultDomain.success(message, uploadedFiles);
            } else {
                resultDomain.success("批量上传成功", uploadedFiles);
            }
            if (knowledgeRows <=0) {
                resultDomain.setMessage("知识库文件数量更新失败");
            }
            return resultDomain;

        } catch (Exception e) {
            log.error("批量上传文件异常", e);
            resultDomain.fail("批量上传异常: " + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<Boolean> deleteFile(String fileId) {
        ResultDomain<Boolean> resultDomain = new ResultDomain<>();

        try {
            // 1. 查询文件信息
            TbAiUploadFile file = uploadFileMapper.selectUploadFileById(fileId);
            if (file == null || file.getDeleted()) {
                resultDomain.fail("文件不存在");
                return resultDomain;
            }

            // 2. 获取知识库信息
            TbAiKnowledge knowledge = knowledgeMapper.selectKnowledgeById(file.getKnowledgeId());
            if (knowledge == null) {
                resultDomain.fail("关联的知识库不存在");
                return resultDomain;
            }

            // 3. 删除Dify中的文档
            if (StringUtils.hasText(file.getDifyDocumentId()) &&
                    StringUtils.hasText(knowledge.getDifyDatasetId())) {
                try {
                    difyApiClient.deleteDocument(
                            knowledge.getDifyDatasetId(),
                            file.getDifyDocumentId());
                    log.info("Dify文档删除成功: {}", file.getDifyDocumentId());
                } catch (DifyException e) {
                    log.error("删除Dify文档失败，继续删除本地记录", e);
                }
            }

            // 4. 逻辑删除本地记录
            TbAiUploadFile deleteEntity = new TbAiUploadFile();
            deleteEntity.setID(fileId);

            int rows = uploadFileMapper.deleteUploadFile(deleteEntity);
            knowledge.setDocumentCount(knowledge.getDocumentCount() - 1);
            int knowledgeRows = knowledgeMapper.updateKnowledge(knowledge);
            if (rows > 0) {
                log.info("文件删除成功: {} - {}", fileId, file.getFileName());
                resultDomain.success("文件删除成功", true);
                if (knowledgeRows <=0) {
                    resultDomain.setMessage("知识库文件数量更新失败");
                }
                return resultDomain;
            } else {
                resultDomain.fail("文件删除失败");
                return resultDomain;
            }

        } catch (Exception e) {
            log.error("删除文件异常", e);
            resultDomain.fail("删除文件异常: " + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbAiUploadFile> getFileStatus(String fileId) {
        return syncFileStatus(fileId);
    }

    @Override
    public ResultDomain<TbAiUploadFile> getFileById(String fileId) {
        ResultDomain<TbAiUploadFile> resultDomain = new ResultDomain<>();

        try {
            if (!StringUtils.hasText(fileId)) {
                resultDomain.fail("文件ID不能为空");
                return resultDomain;
            }

            TbAiUploadFile file = uploadFileMapper.selectUploadFileById(fileId);
            if (file == null || file.getDeleted()) {
                resultDomain.fail("文件不存在");
                return resultDomain;
            }

            resultDomain.success("查询成功", file);
            return resultDomain;

        } catch (Exception e) {
            log.error("查询文件异常", e);
            resultDomain.fail("查询文件异常: " + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbAiUploadFile> listFilesByKnowledge(String knowledgeId) {
        ResultDomain<TbAiUploadFile> resultDomain = new ResultDomain<>();

        try {
            if (!StringUtils.hasText(knowledgeId)) {
                resultDomain.fail("知识库ID不能为空");
                return resultDomain;
            }

            List<TbAiUploadFile> files = uploadFileMapper.selectFilesByKnowledgeId(knowledgeId);
            resultDomain.success("查询成功", files);
            return resultDomain;

        } catch (Exception e) {
            log.error("查询文件列表异常", e);
            resultDomain.fail("查询失败: " + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public PageDomain<TbAiUploadFile> pageFiles(TbAiUploadFile filter, PageParam pageParam) {
        try {
            // 查询列表
            List<TbAiUploadFile> files = uploadFileMapper.selectUploadFilesPage(filter, pageParam);

            // 查询总数
            long total = uploadFileMapper.countUploadFiles(filter);

            // 构建分页结果
            PageParam resultPageParam = new PageParam(pageParam.getPageNumber(), pageParam.getPageSize());
            resultPageParam.setTotalElements(total);
            resultPageParam.setTotalPages((int) Math.ceil((double) total / pageParam.getPageSize()));

            return new PageDomain<>(resultPageParam, files);

        } catch (Exception e) {
            log.error("分页查询文件列表异常", e);
            return new PageDomain<>();
        }
    }

    @Override
    public ResultDomain<TbAiUploadFile> syncFileStatus(String fileId) {
        ResultDomain<TbAiUploadFile> resultDomain = new ResultDomain<>();

        try {
            // 1. 查询本地文件记录
            TbAiUploadFile file = uploadFileMapper.selectUploadFileById(fileId);
            if (file == null || file.getDeleted()) {
                resultDomain.fail("文件不存在");
                return resultDomain;
            }

            // 2. 查询知识库信息
            TbAiKnowledge knowledge = knowledgeMapper.selectKnowledgeById(file.getKnowledgeId());
            if (knowledge == null || !StringUtils.hasText(knowledge.getDifyDatasetId())) {
                resultDomain.fail("关联的知识库不存在或未关联Dify");
                return resultDomain;
            }

            // 3. 从Dify获取文档状态
            if (!StringUtils.hasText(file.getDifyBatchId())) {
                resultDomain.fail("文件未关联Dify批次ID");
                return resultDomain;
            }

            try {
                DocumentStatusResponse statusResponse = difyApiClient.getDocumentStatus(
                        knowledge.getDifyDatasetId(),
                        file.getDifyBatchId());

                // 4. 更新本地状态
                TbAiUploadFile update = new TbAiUploadFile();
                update.setID(fileId);

                // 映射Dify状态到本地状态：completed=2, processing=1, error=3
                // DocumentStatusResponse返回的是文档列表，取第一个
                if (statusResponse.getData() != null && !statusResponse.getData().isEmpty()) {
                    DocumentStatusResponse.DocumentStatus docStatus = statusResponse.getData().get(0);
                    String indexingStatus = docStatus.getIndexingStatus();

                    if ("completed".equals(indexingStatus)) {
                        update.setStatus(2); // 已完成
                    } else if ("error".equals(indexingStatus)) {
                        update.setStatus(3); // 失败
                    } else {
                        update.setStatus(1); // 处理中
                    }

                    if (docStatus.getTotalSegments() != null) {
                        update.setChunkCount(docStatus.getTotalSegments());
                    }
                }

                update.setUpdateTime(new Date());

                uploadFileMapper.updateUploadFile(update);

                // 5. 重新查询返回
                TbAiUploadFile updated = uploadFileMapper.selectUploadFileById(fileId);
                log.info("文件状态同步成功: {} - 状态: {}", fileId, updated.getStatus());
                resultDomain.success("状态同步成功", updated);
                return resultDomain;

            } catch (DifyException e) {
                log.error("从Dify同步文件状态失败", e);
                resultDomain.fail("同步失败: " + e.getMessage());
                return resultDomain;
            }

        } catch (Exception e) {
            log.error("同步文件状态异常", e);
            resultDomain.fail("同步异常: " + e.getMessage());
            return resultDomain;
        }
    }

    @Override
    public ResultDomain<TbAiUploadFile> syncKnowledgeFiles(String knowledgeId) {
        ResultDomain<TbAiUploadFile> resultDomain = new ResultDomain<>();

        try {
            // 查询知识库的所有文件
            List<TbAiUploadFile> files = uploadFileMapper.selectFilesByKnowledgeId(knowledgeId);

            if (files.isEmpty()) {
                resultDomain.success("没有需要同步的文件", files);
                return resultDomain;
            }

            // 并行同步所有文件状态
            List<CompletableFuture<Void>> futures = files.stream()
                    .map(file -> CompletableFuture.runAsync(() -> {
                        try {
                            syncFileStatus(file.getID());
                        } catch (Exception e) {
                            log.error("同步文件状态失败: {}", file.getID(), e);
                        }
                    }, executorService))
                    .collect(Collectors.toList());

            // 等待所有同步完成
            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

            // 重新查询返回最新状态
            List<TbAiUploadFile> updatedFiles = uploadFileMapper.selectFilesByKnowledgeId(knowledgeId);
            resultDomain.success("批量同步成功", updatedFiles);
            return resultDomain;

        } catch (Exception e) {
            log.error("批量同步文件状态异常", e);
            resultDomain.fail("批量同步异常: " + e.getMessage());
            return resultDomain;
        }
    }

    /**
     * 验证文件类型
     */
    private boolean isValidFileType(String filename) {
        if (!StringUtils.hasText(filename)) {
            return false;
        }

        String extension = getFileExtension(filename).toLowerCase();
        String[] allowedTypes = difyConfig.getUpload().getAllowedTypes();

        for (String type : allowedTypes) {
            if (type.equalsIgnoreCase(extension)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        if (!StringUtils.hasText(filename)) {
            return "";
        }

        int lastDot = filename.lastIndexOf('.');
        if (lastDot > 0 && lastDot < filename.length() - 1) {
            return filename.substring(lastDot + 1);
        }
        return "";
    }

    /**
     * 获取文件类型（使用具体的文件扩展名）
     * 图片类型返回 "image"，其他类型返回具体扩展名（pdf, docx, txt等）
     */
    private String getFileType(String filename) {
        if (!StringUtils.hasText(filename)) {
            return "file";
        }

        // 转换为大写以匹配数组中的类型
        String extension = getFileExtension(filename).toUpperCase();

        // 图片类型统一返回 "image"
        String[] imageTypes = { "JPG", "JPEG", "PNG", "GIF", "WEBP", "SVG" };
        String[] documentTypes = { "TXT", "MD", "MARKDOWN", "MDX", "PDF", "HTML", "XLSX", "XLS", "VTT", "PROPERTIES",
                "DOC", "DOCX", "CSV", "EML", "MSG", "PPTX", "PPT", "XML", "EPUB" };
        String[] audioTypes = { "MP3", "M4A", "WAV", "WEBM", "MPGA" };
        String[] videoTypes = { "MP4", "MOV", "MPEG", "WEBM" };

        for (String type : imageTypes) {
            if (type.equals(extension)) {
                return "image";
            }
        }
        for (String type : documentTypes) {
            if (type.equals(extension)) {
                return "document";
            }
        }
        for (String type : audioTypes) {
            if (type.equals(extension)) {
                return "audio";
            }
        }
        for (String type : videoTypes) {
            if (type.equals(extension)) {
                return "video";
            }
        }
        return "custom";
    }

    /**
     * 异步更新向量化状态
     */
    private void asyncUpdateVectorStatus(String fileId) {
        CompletableFuture.runAsync(() -> {
            try {
                // 等待3秒后开始检查状态
                Thread.sleep(3000);

                // 最多检查10次，每次间隔3秒
                for (int i = 0; i < 10; i++) {
                    ResultDomain<TbAiUploadFile> result = syncFileStatus(fileId);
                    if (result.isSuccess() && result.getData() != null) {
                        Integer status = result.getData().getStatus();
                        if (status != null && status != 1) {
                            // 处理完成(2)或失败(3)，停止检查
                            log.info("文件向量化完成: {} - 状态: {}", fileId, status);
                            break;
                        }
                    }
                    Thread.sleep(3000);
                }
            } catch (Exception e) {
                log.error("异步更新向量化状态失败: {}", fileId, e);
            }
        }, executorService);
    }

    @Override
    public ResultDomain<TbAiUploadFile> listFilesByMessageId(String messageId) {
        ResultDomain<TbAiUploadFile> resultDomain = new ResultDomain<>();

        try {
            if (!StringUtils.hasText(messageId)) {
                resultDomain.fail("消息ID不能为空");
                return resultDomain;
            }

            List<TbAiUploadFile> files = uploadFileMapper.selectFilesByMessageId(messageId);
            log.info("查询消息文件列表成功: messageId={}, fileCount={}", messageId, files.size());
            resultDomain.success("查询成功", files);
            return resultDomain;

        } catch (Exception e) {
            log.error("查询消息文件列表异常: messageId={}", messageId, e);
            resultDomain.fail("查询失败: " + e.getMessage());
            return resultDomain;
        }
    }
}
