package org.xyzh.ai.service.impl;

import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import org.xyzh.ai.client.DifyApiClient;
import org.xyzh.ai.client.dto.DatasetCreateRequest;
import org.xyzh.ai.client.dto.DatasetCreateResponse;
import org.xyzh.ai.client.dto.DatasetDetailResponse;
import org.xyzh.ai.client.dto.DocumentListResponse;
import org.xyzh.ai.mapper.TbKnowledgeFileMapper;
import org.xyzh.ai.mapper.TbKnowledgeMapper;
import org.xyzh.api.ai.dto.TbKnowledge;
import org.xyzh.api.ai.dto.TbKnowledgeFile;
import org.xyzh.api.ai.service.AIFileUploadService;
import org.xyzh.api.ai.service.KnowledgeService;
import org.xyzh.api.ai.vo.KnowledgeFileVO;
import org.xyzh.api.file.dto.TbSysFileDTO;
import org.xyzh.api.file.service.FileService;
import org.xyzh.common.core.domain.LoginDomain;
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.core.page.PageRequest;
import org.xyzh.common.utils.id.IdUtil;
import org.xyzh.common.auth.utils.LoginUtil;

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

/**
 * @description 知识库服务实现
 * @filename KnowledgeServiceImpl.java
 * @author yslg
 * @copyright xyzh
 * @since 2025-12-17
 */
@DubboService(version="1.0.0", group="ai", timeout=3000, retries=0)
public class KnowledgeServiceImpl implements KnowledgeService {
    private static final Logger logger = LoggerFactory.getLogger(KnowledgeServiceImpl.class);

    @Autowired
    private TbKnowledgeMapper knowledgeMapper;

    @Autowired
    private TbKnowledgeFileMapper knowledgeFileMapper;

    @Autowired
    private DifyApiClient difyApiClient;

    @DubboReference(version = "1.0.0", group = "file", timeout = 30000, retries = 0)
    private FileService fileService;

    @Autowired
    private AIFileUploadService aiFileUploadService;

    // ================================= 知识库管理 =================================

    /**
     * @description    创建知识库基础信息，包含dify知识库各种参数的配置
     *                 注意：涉及外部API调用，不使用@Transactional，采用手动补偿机制
     * @param    knowledge 知识库信息
     * @return    ResultDomain<TbKnowledge> 创建结果
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<TbKnowledge> createKnowledge(TbKnowledge knowledge) {
        // 1. 参数校验
        if (!StringUtils.hasText(knowledge.getTitle())) {
            return ResultDomain.failure("知识库标题不能为空");
        }

        // 2. 获取当前用户
        LoginDomain loginDomain = LoginUtil.getCurrentLogin();
        if (loginDomain == null || !StringUtils.hasText(loginDomain.getUser().getUserId())) {
            return ResultDomain.failure("用户未登录");
        }
        String userId = loginDomain.getUser().getUserId();

        // 3. 生成ID
        knowledge.setDeptPath(loginDomain.getUserDepts().get(0).getDeptPath());
        knowledge.setOptsn(IdUtil.getOptsn());
        knowledge.setKnowledgeId(IdUtil.getSnowflakeId());
        knowledge.setCreator(userId);

        // 4. 创建Dify知识库
        String difyDatasetId = null;
        try {
            DatasetCreateRequest createRequest = new DatasetCreateRequest();
            createRequest.setName(knowledge.getTitle());
            createRequest.setDescription(knowledge.getDescription());
            if (StringUtils.hasText(knowledge.getDifyIndexingTechnique())) {
                createRequest.setIndexingTechnique(knowledge.getDifyIndexingTechnique());
            }

            DatasetCreateResponse difyResponse = difyApiClient.createDataset(createRequest);
            if (difyResponse != null && StringUtils.hasText(difyResponse.getId())) {
                difyDatasetId = difyResponse.getId();
                knowledge.setDifyDatasetId(difyDatasetId);
            } else {
                return ResultDomain.failure("创建Dify知识库失败");
            }
        } catch (Exception e) {
            logger.error("创建Dify知识库异常: {}", e.getMessage(), e);
            return ResultDomain.failure("创建Dify知识库异常: " + e.getMessage());
        }

        // 5. 插入数据库
        int rows = knowledgeMapper.insertKnowledge(knowledge);
        if (rows > 0) {
            logger.info("创建知识库成功: knowledgeId={}, title={}", knowledge.getKnowledgeId(), knowledge.getTitle());
            return ResultDomain.success("创建知识库成功", knowledge);
        }

        // 数据库保存失败，补偿删除Dify知识库
        if (StringUtils.hasText(difyDatasetId)) {
            try {
                difyApiClient.deleteDataset(difyDatasetId);
                logger.info("补偿删除Dify知识库成功: difyDatasetId={}", difyDatasetId);
            } catch (Exception e) {
                logger.warn("补偿删除Dify知识库失败: {}", e.getMessage());
            }
        }
        return ResultDomain.failure("创建知识库失败");
    }

    /**
     * @description    内部创建知识库（不检查登录状态，用于系统初始化）
     *                 注意：调用方需要自行设置knowledgeId和creator
     * @param    knowledge 知识库信息
     * @return    ResultDomain<TbKnowledge> 创建结果
     * @author    yslg
     * @since 2025-12-20
     */
    @Override
    public ResultDomain<TbKnowledge> createKnowledgeInternal(TbKnowledge knowledge) {
        // 1. 参数校验
        if (!StringUtils.hasText(knowledge.getTitle())) {
            return ResultDomain.failure("知识库标题不能为空");
        }
        if (!StringUtils.hasText(knowledge.getKnowledgeId())) {
            return ResultDomain.failure("知识库ID不能为空");
        }

        // 2. 设置默认值
        if (!StringUtils.hasText(knowledge.getOptsn())) {
            knowledge.setOptsn(IdUtil.getOptsn());
        }
        if (!StringUtils.hasText(knowledge.getCreator())) {
            knowledge.setCreator("system");
        }

        // 3. 创建Dify知识库
        String difyDatasetId = null;
        try {
            DatasetCreateRequest createRequest = new DatasetCreateRequest();
            createRequest.setName(knowledge.getTitle());
            createRequest.setDescription(knowledge.getDescription());
            if (StringUtils.hasText(knowledge.getDifyIndexingTechnique())) {
                createRequest.setIndexingTechnique(knowledge.getDifyIndexingTechnique());
            }

            DatasetCreateResponse difyResponse = difyApiClient.createDataset(createRequest);
            if (difyResponse != null && StringUtils.hasText(difyResponse.getId())) {
                difyDatasetId = difyResponse.getId();
                knowledge.setDifyDatasetId(difyDatasetId);
            } else {
                return ResultDomain.failure("创建Dify知识库失败");
            }
        } catch (Exception e) {
            logger.error("创建Dify知识库异常: {}", e.getMessage(), e);
            return ResultDomain.failure("创建Dify知识库异常: " + e.getMessage());
        }

        // 4. 插入数据库
        int rows = knowledgeMapper.insertKnowledge(knowledge);
        if (rows > 0) {
            logger.info("内部创建知识库成功: knowledgeId={}, title={}", knowledge.getKnowledgeId(), knowledge.getTitle());
            return ResultDomain.success("创建知识库成功", knowledge);
        }

        // 数据库保存失败，补偿删除Dify知识库
        if (StringUtils.hasText(difyDatasetId)) {
            try {
                difyApiClient.deleteDataset(difyDatasetId);
                logger.info("补偿删除Dify知识库成功: difyDatasetId={}", difyDatasetId);
            } catch (Exception e) {
                logger.warn("补偿删除Dify知识库失败: {}", e.getMessage());
            }
        }
        return ResultDomain.failure("创建知识库失败");
    }

    /**
     * @description    更新知识库，包含dify知识库各种参数的配置
     * @param    knowledge 知识库信息
     * @return    ResultDomain<TbKnowledge> 更新结果
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<TbKnowledge> updateKnowledge(TbKnowledge knowledge) {
        // 1. 参数校验
        if (!StringUtils.hasText(knowledge.getKnowledgeId())) {
            return ResultDomain.failure("知识库ID不能为空");
        }

        // 2. 检查是否存在
        TbKnowledge existing = knowledgeMapper.selectKnowledgeById(knowledge.getKnowledgeId());
        if (existing == null) {
            return ResultDomain.failure("知识库不存在");
        }

        // 3. 设置更新者
        String userId = LoginUtil.getCurrentUserId();
        if (StringUtils.hasText(userId)) {
            knowledge.setUpdater(userId);
        }

        // 4. 更新数据库
        int rows = knowledgeMapper.updateKnowledge(knowledge);
        if (rows > 0) {
            logger.info("更新知识库成功: knowledgeId={}", knowledge.getKnowledgeId());
            TbKnowledge updated = knowledgeMapper.selectKnowledgeById(knowledge.getKnowledgeId());
            return ResultDomain.success("更新知识库成功", updated);
        }

        return ResultDomain.failure("更新知识库失败");
    }

    /**
     * @description    删除知识库，同时删除dify知识库
     *                 注意：Dify删除失败不影响本地删除
     * @param    knowledgeId 知识库ID
     * @return    ResultDomain<Boolean> 删除结果
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<Boolean> deleteKnowledge(String knowledgeId) {
        // 1. 参数校验
        if (!StringUtils.hasText(knowledgeId)) {
            return ResultDomain.failure("知识库ID不能为空");
        }

        // 2. 检查是否存在
        TbKnowledge existing = knowledgeMapper.selectKnowledgeById(knowledgeId);
        if (existing == null) {
            return ResultDomain.failure("知识库不存在");
        }

        // 3. 删除Dify知识库
        if (StringUtils.hasText(existing.getDifyDatasetId())) {
            try {
                difyApiClient.deleteDataset(existing.getDifyDatasetId());
            } catch (Exception e) {
                logger.warn("删除Dify知识库失败: {}", e.getMessage());
            }
        }

        // 4. 设置更新者并软删除
        TbKnowledge delete = new TbKnowledge();
        delete.setKnowledgeId(knowledgeId);
        String userId = LoginUtil.getCurrentUserId();
        if (StringUtils.hasText(userId)) {
            delete.setUpdater(userId);
        }

        int rows = knowledgeMapper.deleteKnowledge(delete);
        if (rows > 0) {
            logger.info("删除知识库成功: knowledgeId={}", knowledgeId);
            return ResultDomain.success("删除知识库成功", true);
        }

        return ResultDomain.failure("删除知识库失败");
    }

    /**
     * @description    获取知识库详情，包含dify知识库各种参数的配置
     * @param    knowledgeId 知识库ID
     * @return    ResultDomain<TbKnowledge> 知识库信息
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<TbKnowledge> getKnowledgeById(String knowledgeId) {
        if (!StringUtils.hasText(knowledgeId)) {
            return ResultDomain.failure("知识库ID不能为空");
        }

        TbKnowledge knowledge = knowledgeMapper.selectKnowledgeById(knowledgeId);
        if (knowledge == null) {
            return ResultDomain.failure("知识库不存在");
        }

        return ResultDomain.success("查询成功", knowledge);
    }

    /**
     * @description    查询知识库列表
     * @param    filter 过滤条件
     * @return    ResultDomain<TbKnowledge> 知识库列表
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<TbKnowledge> listKnowledges(TbKnowledge filter) {
        List<TbKnowledge> list = knowledgeMapper.selectKnowledgeList(filter);
        return ResultDomain.success("查询成功", list);
    }

    /**
     * @description    分页查询知识库
     * @param    filter 过滤条件
     * @param    pageParam 分页参数
     * @return    ResultDomain<TbKnowledge> 分页结果
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<TbKnowledge> pageKnowledges(TbKnowledge filter, PageParam pageParam) {
        List<TbKnowledge> list = knowledgeMapper.selectKnowledgePage(filter, pageParam);
        long total = knowledgeMapper.countKnowledges(filter);
        pageParam.setTotal((int) total);
        return ResultDomain.success("查询成功", list);
    }

    /**
     * @description    获取知识库统计信息（从Dify同步文档数量和分段数量）
     * @param    knowledgeId 知识库ID
     * @return    ResultDomain<TbKnowledge> 统计信息
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<TbKnowledge> getKnowledgeStats(String knowledgeId) {
        TbKnowledge knowledge = knowledgeMapper.selectKnowledgeById(knowledgeId);
        if (knowledge == null) {
            return ResultDomain.failure("知识库不存在");
        }

        // 从Dify同步统计信息
        if (StringUtils.hasText(knowledge.getDifyDatasetId())) {
            try {
                DatasetDetailResponse detail = difyApiClient.getDatasetDetail(knowledge.getDifyDatasetId());
                if (detail != null) {
                    TbKnowledge update = new TbKnowledge();
                    update.setKnowledgeId(knowledgeId);
                    update.setDocumentCount(detail.getDocumentCount());
                    update.setTotalChunks(detail.getWordCount());
                    knowledgeMapper.updateKnowledge(update);

                    knowledge.setDocumentCount(detail.getDocumentCount());
                    knowledge.setTotalChunks(detail.getWordCount());
                }
            } catch (Exception e) {
                logger.warn("同步Dify统计信息失败: {}", e.getMessage());
            }
        }

        return ResultDomain.success("查询成功", knowledge);
    }

    /**
     * @description    获取可用的嵌入模型列表
     * @return    ResultDomain<Map<String, Object>> 嵌入模型列表
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<Map<String, Object>> getAvailableEmbeddingModels() {
        try {
            var response = difyApiClient.getAvailableEmbeddingModels();
            Map<String, Object> result = new HashMap<>();
            result.put("data", response.getData());
            return ResultDomain.success("查询成功", result);
        } catch (Exception e) {
            logger.error("获取嵌入模型列表失败: {}", e.getMessage(), e);
            return ResultDomain.failure("获取嵌入模型列表失败: " + e.getMessage());
        }
    }

    /**
     * @description    获取可用的Rerank模型列表
     * @return    ResultDomain<Map<String, Object>> Rerank模型列表
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<Map<String, Object>> getAvailableRerankModels() {
        try {
            var response = difyApiClient.getAvailableRerankModels();
            Map<String, Object> result = new HashMap<>();
            result.put("data", response.getData());
            return ResultDomain.success("查询成功", result);
        } catch (Exception e) {
            logger.error("获取Rerank模型列表失败: {}", e.getMessage(), e);
            return ResultDomain.failure("获取Rerank模型列表失败: " + e.getMessage());
        }
    }

    /**
     * @description    获取知识库文档列表（查询本地数据库文件）
     * @param    pageRequest 分页请求，filter 中包含 knowledgeId
     * @return    ResultDomain<KnowledgeFileVO> 文档列表
     * @author    yslg
     * @since 2025-12-20
     */
    @Override
    public ResultDomain<KnowledgeFileVO> getDocumentList(PageRequest<TbKnowledgeFile> pageRequest) {
        TbKnowledgeFile filter = pageRequest.getFilter();
        if (filter == null || !StringUtils.hasText(filter.getKnowledgeId())) {
            return ResultDomain.failure("知识库ID不能为空");
        }
        
        String knowledgeId = filter.getKnowledgeId();
        
        // 验证知识库是否存在
        TbKnowledge knowledge = knowledgeMapper.selectKnowledgeById(knowledgeId);
        if (knowledge == null) {
            return ResultDomain.failure("知识库不存在");
        }
        
        try {
            // 分页查询知识库文件（已通过 SQL JOIN 关联文件详细信息）
            PageParam pageParam = pageRequest.getPageParam();
            List<KnowledgeFileVO> files = knowledgeFileMapper.selectFilePage(knowledgeId, pageParam);
            long total = knowledgeFileMapper.countFiles(knowledgeId);
            
            // 设置总数
            pageParam.setTotal((int) total);
            
            // 创建分页结果
            PageDomain<KnowledgeFileVO> pageDomain = new PageDomain<>(pageParam, files);
            
            return ResultDomain.success("查询成功", pageDomain);
        } catch (Exception e) {
            logger.error("获取知识库文件列表失败: knowledgeId={}, error={}", knowledgeId, e.getMessage(), e);
            return ResultDomain.failure("获取文件列表失败: " + e.getMessage());
        }
    }

    // ================================= 文件管理 =================================

    /**
     * @description    上传文件到知识库（完整流程：minio + Dify + 数据库）
     * @param    knowledgeId 知识库ID
     * @param    file 上传的文件
     * @param    indexingTechnique 索引方式
     * @return    ResultDomain<TbKnowledgeFile> 上传结果
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<TbKnowledgeFile> uploadKnowledgeFile(String knowledgeId, MultipartFile file, String indexingTechnique) {
        // 1. 参数校验
        if (!StringUtils.hasText(knowledgeId)) {
            return ResultDomain.failure("知识库ID不能为空");
        }
        if (file == null || file.isEmpty()) {
            return ResultDomain.failure("文件不能为空");
        }

        // 2. 获取知识库
        TbKnowledge knowledge = knowledgeMapper.selectKnowledgeById(knowledgeId);
        if (knowledge == null) {
            return ResultDomain.failure("知识库不存在");
        }
        if (!StringUtils.hasText(knowledge.getDifyDatasetId())) {
            return ResultDomain.failure("知识库未关联Dify");
        }

        // 3. 调用FileService上传到minio（使用字节数组方式，支持跨模块Dubbo调用）
        byte[] fileBytes;
        try {
            fileBytes = file.getBytes();
        } catch (Exception e) {
            logger.error("读取文件字节失败", e);
            return ResultDomain.failure("读取文件失败: " + e.getMessage());
        }
        ResultDomain<TbSysFileDTO> fileResult = fileService.uploadFileBytes(
            fileBytes, file.getOriginalFilename(), file.getContentType(), "knowledge", knowledgeId);
        if (!fileResult.getSuccess() || fileResult.getData() == null) {
            return ResultDomain.failure("上传文件到存储服务失败: " + fileResult.getMessage());
        }
        TbSysFileDTO sysFile = fileResult.getData();
        String fileId = sysFile.getFileId();
        logger.info("上传文件到minio成功: fileId={}, path={}", fileId, sysFile.getPath());

        // 4. 上传到Dify知识库
        String difyFileId = null;
        File tempFile = null;
        try {
            tempFile = File.createTempFile("knowledge_", "_" + file.getOriginalFilename());
            file.transferTo(tempFile);

            String technique = StringUtils.hasText(indexingTechnique) ? indexingTechnique : knowledge.getDifyIndexingTechnique();
            ResultDomain<String> difyResult = aiFileUploadService.uploadFileToDify(
                    knowledge.getDifyDatasetId(), tempFile, file.getOriginalFilename(), technique);

            if (difyResult.getSuccess() && StringUtils.hasText(difyResult.getData())) {
                difyFileId = difyResult.getData();
                logger.info("上传文件到Dify成功: difyFileId={}", difyFileId);
            } else {
                logger.error("上传文件到Dify失败: {}", difyResult.getMessage());
                fileService.deleteFile(fileId);
                return ResultDomain.failure("上传文件到Dify失败: " + difyResult.getMessage());
            }
        } catch (Exception e) {
            logger.error("上传文件到Dify异常: {}", e.getMessage(), e);
            fileService.deleteFile(fileId);
            return ResultDomain.failure("上传文件到Dify异常: " + e.getMessage());
        } finally {
            if (tempFile != null && tempFile.exists()) {
                tempFile.delete();
            }
        }

        // 5. 保存tb_knowledge_file
        TbKnowledgeFile knowledgeFile = new TbKnowledgeFile();
        knowledgeFile.setOptsn(IdUtil.getOptsn());
        knowledgeFile.setKnowledgeId(knowledgeId);
        knowledgeFile.setFileRootId(fileId);
        knowledgeFile.setFileId(fileId);
        knowledgeFile.setDifyFileId(difyFileId);
        knowledgeFile.setVersion(1);

        knowledgeMapper.updateKnowledgeFileCount(knowledgeId, 1);
        int rows = knowledgeFileMapper.insertKnowledgeFile(knowledgeFile);
        if (rows > 0) {
            logger.info("保存知识库文件记录成功: knowledgeId={}, fileId={}, difyFileId={}", knowledgeId, fileId, difyFileId);
            return ResultDomain.success("上传成功", knowledgeFile);
        }

        // 补偿删除
        fileService.deleteFile(fileId);
        aiFileUploadService.deleteFileFromDify(knowledge.getDifyDatasetId(), difyFileId);
        return ResultDomain.failure("保存知识库文件记录失败");
    }

    /**
     * @description    批量上传文件到知识库
     * @param    knowledgeId 知识库ID
     * @param    files 文件列表
     * @param    indexingTechnique 索引方式
     * @return    ResultDomain<TbKnowledgeFile> 上传结果
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<TbKnowledgeFile> batchUploadKnowledgeFile(String knowledgeId, List<MultipartFile> files, String indexingTechnique) {
        if (!StringUtils.hasText(knowledgeId)) {
            return ResultDomain.failure("知识库ID不能为空");
        }
        if (files == null || files.isEmpty()) {
            return ResultDomain.failure("文件列表不能为空");
        }

        List<TbKnowledgeFile> successList = new ArrayList<>();
        List<String> failedFiles = new ArrayList<>();

        for (MultipartFile file : files) {
            ResultDomain<TbKnowledgeFile> result = uploadKnowledgeFile(knowledgeId, file, indexingTechnique);
            if (result.getSuccess() && result.getData() != null) {
                successList.add(result.getData());
            } else {
                failedFiles.add(file.getOriginalFilename() + "(" + result.getMessage() + ")");
            }
        }

        if (failedFiles.isEmpty()) {
            return ResultDomain.success("批量上传成功", successList);
        } else if (successList.isEmpty()) {
            return ResultDomain.failure("批量上传全部失败: " + String.join(", ", failedFiles));
        } else {
            return ResultDomain.success("部分上传成功，失败: " + String.join(", ", failedFiles), successList);
        }
    }

    /**
     * @description    上传新版本文件（fileRootId一致，version递增）
     * @param    knowledgeId 知识库ID
     * @param    file 新文件
     * @param    fileRootId 文件根ID
     * @return    ResultDomain<TbKnowledgeFile> 新版本文件信息
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<TbKnowledgeFile> updateKnowledgeFileVersion(String knowledgeId, MultipartFile file, String fileRootId) {
        // 1. 参数校验
        if (!StringUtils.hasText(knowledgeId)) {
            return ResultDomain.failure("知识库ID不能为空");
        }
        if (file == null || file.isEmpty()) {
            return ResultDomain.failure("文件不能为空");
        }
        if (!StringUtils.hasText(fileRootId)) {
            return ResultDomain.failure("文件根ID不能为空");
        }

        // 2. 获取知识库
        TbKnowledge knowledge = knowledgeMapper.selectKnowledgeById(knowledgeId);
        if (knowledge == null) {
            return ResultDomain.failure("知识库不存在");
        }
        if (!StringUtils.hasText(knowledge.getDifyDatasetId())) {
            return ResultDomain.failure("知识库未关联Dify");
        }

        // 3. 获取最大版本的旧文件
        TbKnowledgeFile latestOldFile = knowledgeFileMapper.selectLatestVersionFile(fileRootId);
        if (latestOldFile == null) {
            return ResultDomain.failure("原文件不存在");
        }

        // 4. 上传新版本到minio（使用字节数组避免 Dubbo 序列化问题）
        byte[] fileBytes;
        try {
            fileBytes = file.getBytes();
        } catch (java.io.IOException e) {
            logger.error("读取文件字节失败", e);
            return ResultDomain.failure("读取文件字节失败: " + e.getMessage());
        }
        ResultDomain<TbSysFileDTO> fileResult = fileService.uploadFileBytesVersion(
                fileBytes, file.getOriginalFilename(), file.getContentType(), "knowledge", knowledgeId, fileRootId);
        if (!fileResult.getSuccess() || fileResult.getData() == null) {
            return ResultDomain.failure("上传新版本文件失败: " + fileResult.getMessage());
        }
        TbSysFileDTO sysFile = fileResult.getData();
        String newFileId = sysFile.getFileId();
        int newVersion = sysFile.getVersion();
        logger.info("上传新版本到minio成功: fileId={}, version={}", newFileId, newVersion);

        // 5. 删除Dify最大版本的旧文档
        if (StringUtils.hasText(latestOldFile.getDifyFileId())) {
            aiFileUploadService.deleteFileFromDify(knowledge.getDifyDatasetId(), latestOldFile.getDifyFileId());
        }

        // 6. 上传新文件到Dify
        String newDifyFileId = null;
        File tempFile = null;
        try {
            tempFile = File.createTempFile("knowledge_update_", "_" + file.getOriginalFilename());
            file.transferTo(tempFile);

            ResultDomain<String> difyResult = aiFileUploadService.uploadFileToDify(
                    knowledge.getDifyDatasetId(), tempFile, file.getOriginalFilename(), knowledge.getDifyIndexingTechnique());

            if (difyResult.getSuccess() && StringUtils.hasText(difyResult.getData())) {
                newDifyFileId = difyResult.getData();
            } else {
                fileService.deleteFile(newFileId);
                return ResultDomain.failure("上传新文件到Dify失败: " + difyResult.getMessage());
            }
        } catch (Exception e) {
            logger.error("上传新文件到Dify异常: {}", e.getMessage(), e);
            fileService.deleteFile(newFileId);
            return ResultDomain.failure("上传新文件到Dify异常: " + e.getMessage());
        } finally {
            if (tempFile != null && tempFile.exists()) {
                tempFile.delete();
            }
        }

        // 7. 保存tb_knowledge_file
        TbKnowledgeFile newKnowledgeFile = new TbKnowledgeFile();
        newKnowledgeFile.setOptsn(IdUtil.getOptsn());
        newKnowledgeFile.setKnowledgeId(knowledgeId);
        newKnowledgeFile.setFileRootId(fileRootId);
        newKnowledgeFile.setFileId(newFileId);
        newKnowledgeFile.setDifyFileId(newDifyFileId);
        newKnowledgeFile.setVersion(newVersion);

        int rows = knowledgeFileMapper.insertKnowledgeFile(newKnowledgeFile);
        if (rows > 0) {
            logger.info("保存新版本记录成功: knowledgeId={}, fileRootId={}, newVersion={}", knowledgeId, fileRootId, newVersion);
            return ResultDomain.success("更新成功", newKnowledgeFile);
        }

        // 补偿
        fileService.deleteFile(newFileId);
        aiFileUploadService.deleteFileFromDify(knowledge.getDifyDatasetId(), newDifyFileId);
        return ResultDomain.failure("保存新版本记录失败");
    }

    /**
     * @description    删除知识库文件（根据fileRootId删除所有版本）
     * @param    fileRootId 文件根ID
     * @return    ResultDomain<Boolean> 删除结果
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<Boolean> deleteKnowledgeFileById(String fileRootId) {
        if (!StringUtils.hasText(fileRootId)) {
            return ResultDomain.failure("文件根ID不能为空");
        }

        // 1. 获取所有版本
        List<TbKnowledgeFile> versions = knowledgeFileMapper.selectFileVersions(fileRootId);
        if (versions == null || versions.isEmpty()) {
            return ResultDomain.failure("文件不存在");
        }

        // 2. 删除Dify中的文档
        TbKnowledge knowledge = knowledgeMapper.selectKnowledgeById(versions.get(0).getKnowledgeId());
        if (knowledge != null && StringUtils.hasText(knowledge.getDifyDatasetId())) {
            List<String> difyDocIds = new ArrayList<>();
            for (TbKnowledgeFile file : versions) {
                if (StringUtils.hasText(file.getDifyFileId())) {
                    difyDocIds.add(file.getDifyFileId());
                }
            }
            if (!difyDocIds.isEmpty()) {
                aiFileUploadService.batchDeleteFilesFromDify(knowledge.getDifyDatasetId(), difyDocIds);
            }
        }else{
            return ResultDomain.failure("知识库未关联Dify");
        }

        // 3. 软删除本地记录和minio文件
        int rows = knowledgeFileMapper.deleteFilesByRootId(fileRootId);
        knowledgeMapper.updateKnowledgeFileCount(knowledge.getKnowledgeId(), -1);
        if (rows > 0) {
            logger.info("删除知识库文件成功: fileRootId={}", fileRootId);
            for (TbKnowledgeFile file : versions) {
                fileService.deleteFile(file.getFileId());
            }
            return ResultDomain.success("删除成功", true);
        }

        return ResultDomain.failure("删除文件失败");
    }

    /**
     * @description    获取文件历史版本
     * @param    fileRootId 文件根ID
     * @return    ResultDomain<KnowledgeFileVO> 文件历史版本列表（dataList）
     * @author    yslg
     * @since 2025-12-18
     */
    @Override
    public ResultDomain<KnowledgeFileVO> getKnowledgeFileHistory(String fileRootId) {
        if (!StringUtils.hasText(fileRootId)) {
            return ResultDomain.failure("文件根ID不能为空");
        }

        List<KnowledgeFileVO> versions = knowledgeFileMapper.selectFileVersionsWithDetail(fileRootId);
        ResultDomain<KnowledgeFileVO> result = ResultDomain.success("查询成功");
        result.setDataList(versions);
        return result;
    }
}
