package cn.com.poc.long_document.aggregate.impl;

import cn.com.poc.agent_application.entity.BizAgentApplicationDialoguesRecordEntity;
import cn.com.poc.agent_application.entity.BizAgentApplicationGcConfigEntity;
import cn.com.poc.agent_application.entity.CheckPluginUseEntity;
import cn.com.poc.agent_application.entity.KnowledgeContentResult;
import cn.com.poc.agent_application.service.BizAgentApplicationDialoguesRecordService;
import cn.com.poc.agent_application.service.BizAgentApplicationGcConfigService;
import cn.com.poc.agent_application.utils.AgentApplicationTools;
import cn.com.poc.ai_dialogues.entity.BizAiDialoguesEntity;
import cn.com.poc.ai_dialogues.service.BizAiDialoguesService;
import cn.com.poc.common.constant.CommonConstant;
import cn.com.poc.common.model.BizFileUploadRecordModel;
import cn.com.poc.common.service.BizFileUploadRecordService;
import cn.com.poc.common.utils.DocumentLoad;
import cn.com.poc.common.utils.JsonUtils;
import cn.com.poc.common.utils.ListUtils;
import cn.com.poc.common.utils.SSEUtil;
import cn.com.poc.knowledge.aggregate.KnowledgeService;
import cn.com.poc.knowledge.constant.KnowledgeConstant;
import cn.com.poc.knowledge.entity.BizKnowledgeDocumentEntity;
import cn.com.poc.knowledge.query.KnowledgeDocumentRelationQueryItem;
import cn.com.poc.knowledge.service.BizKnowledgeDocumentService;
import cn.com.poc.long_document.aggregate.LongTextDialoguesService;
import cn.com.poc.long_document.domain.LongtextDialoguesResult;
import cn.com.poc.long_document.domain.MindMap;
import cn.com.poc.long_document.domain.keyword.KeyWord;
import cn.com.poc.long_document.domain.keyword.MentionFrequency;
import cn.com.poc.long_document.dto.LongTextExampleDto;
import cn.com.poc.long_document.dto.LongTextSummaryDto;
import cn.com.poc.long_document.entity.BizLongTextSummaryCacheEntity;
import cn.com.poc.long_document.model.BizLongTextExampleModel;
import cn.com.poc.long_document.service.BizLongTextExampleService;
import cn.com.poc.long_document.service.BizLongTextSummaryCacheService;
import cn.com.poc.meeting.cache.KeyWordCounter;
import cn.com.poc.thirdparty.resource.demand.ai.aggregate.DemandKnowledgeService;
import cn.com.poc.thirdparty.resource.demand.ai.constants.KnowledgeSearchTypeEnum;
import cn.com.poc.thirdparty.resource.demand.ai.constants.LLMRoleEnum;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.FunctionCall;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Message;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Tool;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.ToolFunction;
import cn.com.poc.thirdparty.resource.demand.ai.entity.function.FunctionCallResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.knowledge.SearchKnowledgeResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelDemandResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelResponse;
import cn.com.poc.thirdparty.resource.demand.ai.function.AbstractFunctionResult;
import cn.com.poc.thirdparty.resource.demand.ai.function.web_seach.WebSearchFunction;
import cn.com.poc.thirdparty.resource.demand.ai.function.web_seach.WebSearchFunctionResult;
import cn.com.poc.thirdparty.service.LLMService;
import cn.com.yict.framemax.core.exception.BusinessException;
import cn.com.yict.framemax.frame.service.FmxParamConfigService;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.digest.MD5;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author alex.yao
 * @date 2025/6/17
 */
@Service
public class LongTextDialoguesServiceImpl implements LongTextDialoguesService {

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

    @Resource
    private LLMService llmService;

    @Resource
    private BizFileUploadRecordService bizFileUploadRecordService;

    @Resource
    private BizAiDialoguesService bizAiDialoguesService;

    @Resource
    private BizAgentApplicationDialoguesRecordService bizAgentApplicationDialoguesRecordService;

    @Resource
    private BizLongTextExampleService bizLongTextExampleService;

    @Resource
    private BizAgentApplicationGcConfigService bizAgentApplicationGcConfigService;

    @Resource
    private KnowledgeService knowledgeService;

    @Resource
    private BizKnowledgeDocumentService bizKnowledgeDocumentService;

    @Resource
    private DemandKnowledgeService demandKnowledgeService;

    @Resource
    private BizLongTextSummaryCacheService bizLongTextSummaryCacheService;

    @Resource
    private FmxParamConfigService fmxParamConfigService;

    @Resource
    private WebSearchFunction webSearchFunction;


    @Override
    public void call(String dialoguesId, String fileUrl, String input, Integer[] knowledgeIds, Long userId, Boolean enableSearchEngine, Boolean enableDeepThinking) throws Exception {
        BizAiDialoguesEntity bizAiDialoguesEntity = new BizAiDialoguesEntity();
        bizAiDialoguesEntity.setDialoguesId(dialoguesId);
        bizAiDialoguesEntity.setMemberId(userId);
        bizAiDialoguesEntity.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizAiDialoguesEntity> bizAiDialoguesEntities = bizAiDialoguesService.findByExample(bizAiDialoguesEntity, null);

        if (CollectionUtils.isEmpty(bizAiDialoguesEntities)) {
            throw new BusinessException("对话ID不存在");
        }

        BizAiDialoguesEntity aiDialoguesEntity = bizAiDialoguesEntities.get(0);

        //更新标题
        if (StringUtils.isBlank(aiDialoguesEntity.getTitle())) { // 标题
            aiDialoguesEntity.setTitle(input.substring(0, Math.min(input.length(), 150)));
            aiDialoguesEntity = bizAiDialoguesService.update(aiDialoguesEntity);
        }
        BizAgentApplicationDialoguesRecordEntity dialoguesRecordEntity = new BizAgentApplicationDialoguesRecordEntity();
        dialoguesRecordEntity.setDialogsId(dialoguesId);
        dialoguesRecordEntity.setMemberId(userId);
        dialoguesRecordEntity.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizAgentApplicationDialoguesRecordEntity> dialoguesRecordEntities = bizAgentApplicationDialoguesRecordService.findByExample(dialoguesRecordEntity, null);

        boolean isInit = false;
        if (CollectionUtils.isEmpty(dialoguesRecordEntities)) {
            if (StringUtils.isNoneBlank(aiDialoguesEntity.getFileUrl()) && StringUtils.isBlank(fileUrl)) {
                fileUrl = aiDialoguesEntity.getFileUrl();
            }
            isInit = true;
        }

        // 文件是否变更
        boolean isFileUrlChanged = (StringUtils.isNotBlank(fileUrl) && !fileUrl.equals(aiDialoguesEntity.getFileUrl()))
                || isInit;

        if (StringUtils.isBlank(fileUrl)) {
            fileUrl = aiDialoguesEntity.getFileUrl();
        }

        // 更新文件URL
        if (isFileUrlChanged) {
            if (!isInit && StringUtils.isNotBlank(fileUrl)) {
                aiDialoguesEntity.setFileUrl(fileUrl);
                bizAiDialoguesService.update(aiDialoguesEntity);
            }
        }

        //记录提问时间
        long inputTimestamp = System.currentTimeMillis();

        SSEUtil sseUtil = new SSEUtil();
        // 知识库
        //获取知识库配置
        List<Integer> kdIds = knowledgeService.getKdIdsByKnowledgeInfoIds(knowledgeIds);
        List<KnowledgeContentResult> knowledgeResult = knowledge(kdIds, input, 5, 0.5, KnowledgeSearchTypeEnum.MIX);

        if (CollectionUtils.isNotEmpty(knowledgeResult)) {
            LargeModelDemandResult result = new LargeModelDemandResult();
            result.setCode("0");
            result.setFunction(null);
            result.setDbChainResult(null);
            result.setKnowledgeContentResult(knowledgeResult);
            sseUtil.send(JsonUtils.serialize(result));
        }

        String longTextDialoguesModel = enableDeepThinking ? fmxParamConfigService.getParam("longtext.dialogues_model_think")
                : fmxParamConfigService.getParam("longtext.dialogues_model");


        // 插件调用
        ToolFunction toolFunction = getToolFunction(dialoguesId, input, enableSearchEngine, sseUtil);

        //组装请求参数
        List<Message> messages = buildMessages(dialoguesId, userId, input, fileUrl, knowledgeResult, toolFunction);
        LargeModelResponse largeModelResponse = new LargeModelResponse();
        largeModelResponse.setModel(longTextDialoguesModel);
        largeModelResponse.setMessages(messages.toArray(new Message[0]));
        largeModelResponse.setStream(true);
        BufferedReader bufferedReader = llmService.chatChunk(largeModelResponse);
        LongtextDialoguesResult longtextDialoguesResult = textOutputStream(sseUtil, bufferedReader);


        // 保存用户输入记录
        BizAgentApplicationDialoguesRecordEntity inputRecord = new BizAgentApplicationDialoguesRecordEntity();
        inputRecord.setMemberId(userId);
        inputRecord.setContent(input);
        if (isFileUrlChanged) {
            inputRecord.setFileUrl(fileUrl);
        }
        inputRecord.setDialogsId(dialoguesId);
        inputRecord.setRole("user");
        inputRecord.setTimestamp(inputTimestamp);

        // 保存AI回复记录
        BizAgentApplicationDialoguesRecordEntity assistantRecord = new BizAgentApplicationDialoguesRecordEntity();
        assistantRecord.setMemberId(userId);
        assistantRecord.setContent(longtextDialoguesResult.getMessage());
        assistantRecord.setReasoningContent(longtextDialoguesResult.getReasoningContent());
        assistantRecord.setDialogsId(dialoguesId);
        assistantRecord.setRole("assistant");
        assistantRecord.setTimestamp(System.currentTimeMillis());

        bizAgentApplicationDialoguesRecordService.save(inputRecord);
        bizAgentApplicationDialoguesRecordService.save(assistantRecord);
    }

    @Override
    public LongTextSummaryDto summary(String dialoguesId, Long userId) throws Exception {

        BizAiDialoguesEntity bizAiDialoguesEntity = new BizAiDialoguesEntity();
        bizAiDialoguesEntity.setDialoguesId(dialoguesId);
        bizAiDialoguesEntity.setMemberId(userId);
        bizAiDialoguesEntity.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizAiDialoguesEntity> entities = bizAiDialoguesService.findByExample(bizAiDialoguesEntity, null);
        if (CollectionUtils.isEmpty(entities)) {
            throw new BusinessException("对话不存在");
        }

        BizAiDialoguesEntity aiDialoguesEntity = entities.get(0);
        String fileUrl = aiDialoguesEntity.getFileUrl();
        if (StringUtils.isBlank(fileUrl)) {
            throw new BusinessException("对话文件不存在，重新创建对话");
        }

        String summary = StringUtils.EMPTY;
        String corePoint = StringUtils.EMPTY;
        String mindMap = StringUtils.EMPTY;
        KeyWord keyWord = null;

        boolean summaryNeedGenerate = false;
        boolean corePointNeedGenerate = false;
        boolean mindMapNeedGenerate = false;
        boolean keyWordNeedGenerate = false;

        File file = DocumentLoad.downloadURLDocument(fileUrl);
        String fileMD5 = MD5.create().digestHex(file);

        // 缓存中查询摘要和核心观点
        BizLongTextSummaryCacheEntity bizLongTextSummaryCacheEntity = new BizLongTextSummaryCacheEntity();
        bizLongTextSummaryCacheEntity.setFileMd5(fileMD5);
        bizLongTextSummaryCacheEntity.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizLongTextSummaryCacheEntity> bizLongTextSummaryCacheEntities = bizLongTextSummaryCacheService.findByExample(bizLongTextSummaryCacheEntity, null);
        if (CollectionUtils.isNotEmpty(bizLongTextSummaryCacheEntities)) {
            BizLongTextSummaryCacheEntity longTextSummaryCacheEntity = bizLongTextSummaryCacheEntities.get(0);
            summary = longTextSummaryCacheEntity.getSummary();
            corePoint = longTextSummaryCacheEntity.getCorePoint();
            keyWord = StringUtils.isNotBlank(longTextSummaryCacheEntity.getKeyword()) ?
                    JsonUtils.deSerialize(longTextSummaryCacheEntity.getKeyword(), KeyWord.class) : null;
            mindMap = longTextSummaryCacheEntity.getMindmap();

        }

        summaryNeedGenerate = StringUtils.isBlank(summary);
        corePointNeedGenerate = StringUtils.isBlank(corePoint);
        mindMapNeedGenerate = StringUtils.isBlank(mindMap);
        keyWordNeedGenerate = ObjectUtil.isEmpty(keyWord);

        String document = DocumentLoad.documentToText(file);

        String finalSummary = summary;
        boolean finalSummaryNeedGenerate = summaryNeedGenerate;

        CompletableFuture<String> summaryFuture = CompletableFuture.supplyAsync(() -> {
            if (finalSummaryNeedGenerate) {
                return createSummary(document);
            } else {
                return finalSummary;
            }
        }).exceptionally(throwable -> {
            logger.error("生成摘要失败", throwable);
            throw new BusinessException(throwable);
        });


        String finalCorePoint = corePoint;
        boolean finalCorePointNeedGenerate = corePointNeedGenerate;
        CompletableFuture<String> corePointFuture = CompletableFuture.supplyAsync(() ->
                finalCorePointNeedGenerate ? createCorePoint(document) : finalCorePoint
        ).exceptionally(throwable -> {
            logger.error("生成核心观点失败", throwable);
            throw new BusinessException(throwable);
        });


        boolean finalMindMapNeedGenerate = mindMapNeedGenerate;
        String finalMindMap = mindMap;

        CompletableFuture<String> mindMapFuture = CompletableFuture.supplyAsync(
                () -> finalMindMapNeedGenerate ? createMindMap(document) : finalMindMap).exceptionally(throwable -> {
            logger.error("生成思维导图失败", throwable);
            throw new BusinessException(throwable);
        });

        boolean finalKeyWordNeedGenerate = keyWordNeedGenerate;
        KeyWord finalKeyWord = keyWord;
        CompletableFuture<KeyWord> keyWordFuture = CompletableFuture.supplyAsync(() ->
                finalKeyWordNeedGenerate ? createKeyWord(document) : finalKeyWord).exceptionally(throwable -> {
            logger.error("生成关键词失败", throwable);
            throw new BusinessException(throwable);
        });


        CompletableFuture<Void> allOf = CompletableFuture.allOf(summaryFuture, corePointFuture, mindMapFuture, keyWordFuture);

        allOf.join();
        summary = summaryFuture.get();
        corePoint = corePointFuture.get();
        mindMap = mindMapFuture.get();
        keyWord = keyWordFuture.get();
        // 保存缓存
        if (corePointNeedGenerate || summaryNeedGenerate || keyWordNeedGenerate || mindMapNeedGenerate) {
            // 删除就缓存
            if (CollectionUtils.isNotEmpty(bizLongTextSummaryCacheEntities)) {
                BizLongTextSummaryCacheEntity updateCacheEntity = bizLongTextSummaryCacheEntities.get(0);
                updateCacheEntity.setCorePoint(corePoint);
                updateCacheEntity.setSummary(summary);
                updateCacheEntity.setMindmap(mindMap);
                updateCacheEntity.setKeyword(ObjectUtil.isNotEmpty(keyWord) ?
                        JsonUtils.serialize(keyWord) : StringUtils.EMPTY);
                bizLongTextSummaryCacheService.update(updateCacheEntity);
            } else {
                BizLongTextSummaryCacheEntity saveCache = new BizLongTextSummaryCacheEntity();
                saveCache.setCorePoint(corePoint);
                saveCache.setSummary(summary);
                saveCache.setFileUrl(fileUrl);
                saveCache.setMindmap(mindMap);
                saveCache.setKeyword(ObjectUtil.isNotEmpty(keyWord) ?
                        JsonUtils.serialize(keyWord) : StringUtils.EMPTY);
                saveCache.setFileMd5(fileMD5);
                saveCache.setIsDeleted(CommonConstant.IsDeleted.N);
                bizLongTextSummaryCacheService.save(saveCache);
            }
        }
        if (StringUtils.isBlank(summary)) {
            throw new BusinessException("获取/生成摘要失败");
        }
        if (ObjectUtil.isEmpty(keyWord)) {
            throw new BusinessException("获取/生成关键词失败");
        }
        if (StringUtils.isBlank(corePoint)) {
            throw new BusinessException("获取/生成核心观点失败");
        }
        if (StringUtils.isBlank(mindMap)) {
            throw new BusinessException("获取/生成思维导图失败");
        }

        // 返回摘要和核心观点
        // 转换格式 json to list

        int startMindMap = mindMap.indexOf("{");
        int endMindMap = mindMap.lastIndexOf("}");

        LongTextSummaryDto longTextSummaryDto = new LongTextSummaryDto();
        longTextSummaryDto.setSummary(summary);
        longTextSummaryDto.setCorePoint(corePoint);
        longTextSummaryDto.setKeyword(keyWord);
        longTextSummaryDto.setMindMap(JsonUtils.deSerialize(mindMap.substring(startMindMap, endMindMap + 1), MindMap.class));
        return longTextSummaryDto;
    }

    @Override
    public List<LongTextExampleDto> example() throws Exception {
        List<LongTextExampleDto> result = new ArrayList<>();
        BizLongTextExampleModel bizLongTextExampleModel = new BizLongTextExampleModel();
        bizLongTextExampleModel.setIsDeleted(CommonConstant.IsDeleted.N);
        Collection<BizLongTextExampleModel> models = bizLongTextExampleService.findByExample(bizLongTextExampleModel, null);
        if (CollectionUtils.isNotEmpty(models)) {
            for (BizLongTextExampleModel model : models) {
                LongTextExampleDto dto = new LongTextExampleDto();
                dto.setTitle(model.getTitle());
                dto.setFileUrl(model.getFileUrl());
                dto.setPreviewImage(model.getPreviewImage());
                if (StringUtils.isNotBlank(model.getFileUrl())) {
                    BizFileUploadRecordModel bizFileUploadRecordModel = new BizFileUploadRecordModel();
                    bizFileUploadRecordModel.setFileUrl(model.getFileUrl());
                    List<BizFileUploadRecordModel> fileUploadRecordModels = bizFileUploadRecordService.findByExample(bizFileUploadRecordModel, null);
                    if (CollectionUtils.isNotEmpty(fileUploadRecordModels)) {
                        dto.setFileName(fileUploadRecordModels.get(0).getFileName());
                    }
                }
                dto.setDescription(model.getDescription());
                dto.setQuestion(model.getQuestion());
                result.add(dto);
            }
        }
        return result;
    }


    private List<Message> buildMessages(String dialogsId, Long userId, String input, String fileUrl, List<KnowledgeContentResult> knowledgeContentResults, ToolFunction toolFunction) throws Exception {
        // 获取对话提示词
        String promptCode = "DocumentDialoguePrompt";
        BizAgentApplicationGcConfigEntity documentDialoguePrompt = bizAgentApplicationGcConfigService.getByConfigCode(promptCode);
        if (documentDialoguePrompt == null || StringUtils.isBlank(documentDialoguePrompt.getConfigSystem())) {
            logger.error("获取对话提示词失败 , configCode:{}", promptCode);
            throw new BusinessException("获取对话提示词失败");
        }

        // 加载文件
        File file = DocumentLoad.downloadURLDocument(fileUrl);
        String fileContent = DocumentLoad.documentToText(file);


        // 加载对话提示词
        String prompt = documentDialoguePrompt.getConfigSystem();
        if (CollectionUtils.isNotEmpty(knowledgeContentResults)) {
            String knowledgeContent = JsonUtils.serialize(knowledgeContentResults);
            prompt = prompt.replace("${knowledgeContent}", knowledgeContent);
        } else {
            prompt = prompt.replace("${knowledgeContent}", StringUtils.EMPTY);
        }

        if (toolFunction != null) {
            prompt = prompt.replace("${toolFunction}", JsonUtils.serialize(toolFunction));
        }

        // 配置message
        List<Message> messages = new ArrayList<>();
        Message systemMessage = new Message();
        systemMessage.setContent(prompt);
        systemMessage.setRole(LLMRoleEnum.SYSTEM.getRole());
        messages.add(systemMessage);

        // 文件内容
        Message fileSystemMessage = new Message();
        fileSystemMessage.setContent(fileContent);
        fileSystemMessage.setRole(LLMRoleEnum.SYSTEM.getRole());
        messages.add(fileSystemMessage);

        // 对话记录
        BizAgentApplicationDialoguesRecordEntity recordEntity = new BizAgentApplicationDialoguesRecordEntity();
        recordEntity.setDialogsId(dialogsId);
        recordEntity.setIsDeleted(CommonConstant.IsDeleted.N);
        recordEntity.setMemberId(userId);
        List<BizAgentApplicationDialoguesRecordEntity> recordEntities = bizAgentApplicationDialoguesRecordService.findByExample(recordEntity, null);
        if (CollectionUtils.isNotEmpty(recordEntities)) {
            for (BizAgentApplicationDialoguesRecordEntity entity : recordEntities) {
                Message message = new Message();
                message.setContent(entity.getContent());
                message.setRole(entity.getRole());
                messages.add(message);
            }
        }
        //判断最后是否为User，若是则删除。
        if (CollectionUtils.isNotEmpty(messages)) {
            if (LLMRoleEnum.USER.getRole().equals(messages.get(messages.size() - 1).getRole())) {
                Long recordId = recordEntities.get(recordEntities.size() - 1).getId();
                bizAgentApplicationDialoguesRecordService.deletedById(recordId);
                messages.remove(messages.size() - 1);
            }
        }

        // 用户输入
        Message message = new Message();
        message.setContent(input);
        message.setRole(LLMRoleEnum.USER.getRole());
        messages.add(message);
        logger.info("--------- Build Messages dialogsId:{},messages:{}--------------", dialogsId, messages);
        return messages;
    }

    /**
     * 文本输出结果
     *
     * @param sseUtil
     * @param bufferedReader
     * @throws IOException
     */
    private LongtextDialoguesResult textOutputStream(SSEUtil sseUtil, BufferedReader bufferedReader) throws IOException {
        String res = "";
        StringBuilder output = new StringBuilder();
        StringBuilder reasoningContent = new StringBuilder();
        try {
            while ((res = bufferedReader.readLine()) != null) {
                if (StringUtils.isEmpty(res)) {
                    continue;
                }
                res = StringUtils.replace(res, "data: ", StringUtils.EMPTY);
                LargeModelDemandResult result = JsonUtils.deSerialize(res, LargeModelDemandResult.class);
                if (!"0".equals(result.getCode())) {
                    logger.error("LLM Error,code:{}", result.getCode());
                    BusinessException ex = new BusinessException("exception/call.failure");
                    result.setMessage(ex.getMessage());
                    sseUtil.send(JsonUtils.serialize(result));
                    sseUtil.send("[DONE]");
                    sseUtil.complete();
                    throw ex;
                }
                result.setFunction(null);
                result.setDbChainResult(null);
                result.setKnowledgeContentResult(null);
                result.setMessage(result.getMessage()) ;
                sseUtil.send(JsonUtils.serialize(result));
                if (StringUtils.isNotEmpty(result.getMessage())) {
                    output.append(result.getMessage());
                }
                if (StringUtils.isNotEmpty(result.getReasoningContent())) {
                    reasoningContent.append(result.getReasoningContent());
                }
            }
            // 关闭资源
            sseUtil.send("[DONE]");
            sseUtil.complete();
            LongtextDialoguesResult longtextDialoguesResult = new LongtextDialoguesResult();
            longtextDialoguesResult.setMessage(output.toString());
            longtextDialoguesResult.setReasoningContent(reasoningContent.toString());
            return longtextDialoguesResult;
        } catch (IOException e) {
            logger.error("连接断开,code:{}", e.getMessage());
            sseUtil.completeByError("连接断开");
            throw new BusinessException("连接断开");
        } finally {
            bufferedReader.close();
            sseUtil.complete();
        }
    }


    private List<KnowledgeContentResult> knowledge(List<Integer> kdIds, String input, Integer topK, Double score, KnowledgeSearchTypeEnum searchTypeEnum) {
        List<KnowledgeContentResult> knowledgeContentResults = new ArrayList<>();
        if (CollectionUtils.isEmpty(kdIds)) {
            return knowledgeContentResults;
        }
        List<String> knowledgeIds = new ArrayList<>();
        for (Integer kdId : kdIds) {
            BizKnowledgeDocumentEntity knowledgeDocumentEntity = bizKnowledgeDocumentService.get(kdId);
            // 筛选训练完成的文档，否则跳过该文档
            if (null == knowledgeDocumentEntity && KnowledgeConstant.TrainStatus.COMPLETE.equals(knowledgeDocumentEntity.getTrainStatus())) {
                continue;
            }
            knowledgeIds.add(knowledgeDocumentEntity.getKnowledgeId());
        }

        SearchKnowledgeResult searchKnowledgeResult = demandKnowledgeService.searchKnowledge(input, knowledgeIds, topK, score, searchTypeEnum);

        if (CollectionUtils.isNotEmpty(searchKnowledgeResult.getDocuments())) {
            for (int i = 1; i <= searchKnowledgeResult.getDocuments().size(); i++) {
                KnowledgeContentResult knowledgeContentResult = new KnowledgeContentResult();
                knowledgeContentResult.setContent(searchKnowledgeResult.getDocuments().get(i - 1));
                knowledgeContentResult.setKnowledgeId(searchKnowledgeResult.getKnowledgeIds().get(i - 1));
                knowledgeContentResult.setScore(searchKnowledgeResult.getScore().get(i - 1));
                knowledgeContentResults.add(knowledgeContentResult);
            }
            // 根据knowledgeId获取知识库名和文档名
            knowledgeIds = knowledgeContentResults.stream().map(KnowledgeContentResult::getKnowledgeId).distinct().collect(Collectors.toList());
            List<KnowledgeDocumentRelationQueryItem> knowledgeDocumentRelationQueryItems = bizKnowledgeDocumentService.knowledgeDocumentRelationQuery(knowledgeIds, null);
            for (KnowledgeContentResult result : knowledgeContentResults) {
                String knowledgeId = result.getKnowledgeId();
                KnowledgeDocumentRelationQueryItem item = knowledgeDocumentRelationQueryItems.stream().filter(v -> v.getKnowledgeId().equals(knowledgeId)).findFirst().get();
                result.setKnowledgeName(item.getKnowledgeName());
                result.setKdId(item.getKdId());
                result.setDocumentName(item.getDocumentName());
            }
        }

        return knowledgeContentResults;
    }

    private String createSummary(String document) {
        // 获取对话提示词
        String promptCode = "CreateSummaryPrompt";
        BizAgentApplicationGcConfigEntity documentDialoguePrompt = bizAgentApplicationGcConfigService.getByConfigCode(promptCode);
        if (documentDialoguePrompt == null || StringUtils.isBlank(documentDialoguePrompt.getConfigSystem())) {
            logger.error("获取对话提示词失败 , configCode:{}", promptCode);
            throw new BusinessException("获取对话提示词失败");
        }

        String prompt = documentDialoguePrompt.getConfigSystem();
        String largeModel = documentDialoguePrompt.getLargeModel();

        // 配置message
        List<Message> messages = new ArrayList<>();
        Message systemMessage = new Message();
        systemMessage.setContent(prompt);
        systemMessage.setRole(LLMRoleEnum.SYSTEM.getRole());
        messages.add(systemMessage);

        // 文件内容
        Message fileSystemMessage = new Message();
        fileSystemMessage.setContent(document);
        fileSystemMessage.setRole(LLMRoleEnum.SYSTEM.getRole());
        messages.add(fileSystemMessage);

        Message questionMessage = new Message();
        questionMessage.setContent("获取总结摘要");
        questionMessage.setRole(LLMRoleEnum.USER.getRole());
        messages.add(questionMessage);

        // 调用LLM
        LargeModelResponse response = new LargeModelResponse();
        response.setModel(largeModel);
        response.setMessages(messages.toArray(new Message[0]));
        response.setStream(true);
        response.setUser("CreateSummary");
        try {
            StringBuilder summary = new StringBuilder();
            BufferedReader bufferedReader = llmService.chatChunk(response);
            String res;
            while ((res = bufferedReader.readLine()) != null) {
                if (StringUtils.isEmpty(res)) {
                    continue;
                }
                res = res.replace("data: ", StringUtils.EMPTY);
                LargeModelDemandResult result = JsonUtils.deSerialize(res, LargeModelDemandResult.class);
                if (ObjectUtil.isEmpty(result) || !result.getCode().equals("0")) {
                    logger.error("LLM Error,code:{}", result.getCode());
                    throw new BusinessException("获取总结摘要失败");
                }
                if (StringUtils.isNotBlank(result.getMessage())) {
                    String message = result.getMessage();
                    summary.append(message);
                }
            }
            bufferedReader.close();
            return summary.toString();
        } catch (Exception e) {
            logger.error("获取总结摘要失败", e);
            throw new BusinessException("获取总结摘要失败");
        }
    }

    private String createCorePoint(String document) {
        // 获取对话提示词
        String promptCode = "CreateCorePointPrompt";
        BizAgentApplicationGcConfigEntity documentDialoguePrompt = bizAgentApplicationGcConfigService.getByConfigCode(promptCode);
        if (documentDialoguePrompt == null || StringUtils.isBlank(documentDialoguePrompt.getConfigSystem())) {
            logger.error("获取对话提示词失败 , configCode:{}", promptCode);
            throw new BusinessException("获取对话提示词失败");
        }

        String prompt = documentDialoguePrompt.getConfigSystem();
        String largeModel = documentDialoguePrompt.getLargeModel();

        // 配置message
        List<Message> messages = new ArrayList<>();
        Message systemMessage = new Message();
        systemMessage.setContent(prompt);
        systemMessage.setRole(LLMRoleEnum.SYSTEM.getRole());
        messages.add(systemMessage);

        // 文件内容
        Message fileSystemMessage = new Message();
        fileSystemMessage.setContent(document);
        fileSystemMessage.setRole(LLMRoleEnum.SYSTEM.getRole());
        messages.add(fileSystemMessage);

        Message questionMessage = new Message();
        questionMessage.setContent("提取核心观点");
        questionMessage.setRole(LLMRoleEnum.USER.getRole());
        messages.add(questionMessage);

        // 调用LLM
        LargeModelResponse response = new LargeModelResponse();
        response.setModel(largeModel);
        response.setMessages(messages.toArray(new Message[0]));
        response.setStream(false);
        response.setUser("CreateCorePoint");
        try {
            StringBuilder corePoint = new StringBuilder();
            BufferedReader bufferedReader = llmService.chatChunk(response);
            String res;
            while ((res = bufferedReader.readLine()) != null) {
                if (StringUtils.isEmpty(res)) {
                    continue;
                }
                res = res.replace("data: ", StringUtils.EMPTY);
                LargeModelDemandResult result = JsonUtils.deSerialize(res, LargeModelDemandResult.class);
                if (ObjectUtil.isEmpty(result) || !result.getCode().equals("0")) {
                    logger.error("LLM Error,code:{}", result.getCode());
                    throw new BusinessException("获取核心观点失败");
                }
                if (StringUtils.isNotBlank(result.getMessage())) {
                    String message = result.getMessage();
                    corePoint.append(message);
                }
            }
            bufferedReader.close();
            return corePoint.toString();
        } catch (Exception e) {
            logger.error("获取核心观点失败", e);
            throw new BusinessException("获取核心观点失败");
        }
    }

    private KeyWord createKeyWord(String document) {
        // 获取对话提示词
        String promptCode = "CreateKeyWordPrompt";
        BizAgentApplicationGcConfigEntity documentDialoguePrompt = bizAgentApplicationGcConfigService.getByConfigCode(promptCode);
        if (documentDialoguePrompt == null || StringUtils.isBlank(documentDialoguePrompt.getConfigSystem())) {
            logger.error("获取对话提示词失败 , configCode:{}", promptCode);
            throw new BusinessException("获取对话提示词失败");
        }

        String prompt = documentDialoguePrompt.getConfigSystem();
        String largeModel = documentDialoguePrompt.getLargeModel();
        prompt = prompt.replace("{document}", document);

        // 配置message
        List<Message> messages = new ArrayList<>();
        Message systemMessage = new Message();
        systemMessage.setContent(prompt);
        systemMessage.setRole(LLMRoleEnum.SYSTEM.getRole());
        messages.add(systemMessage);

        Message questionMessage = new Message();
        questionMessage.setContent("获取关键词");
        questionMessage.setRole(LLMRoleEnum.USER.getRole());
        messages.add(questionMessage);

        // 调用LLM
        LargeModelResponse response = new LargeModelResponse();
        response.setModel(largeModel);
        response.setMessages(messages.toArray(new Message[0]));
        response.setStream(true);
        response.setUser("CreateKeyWord");
        try {
            StringBuilder summary = new StringBuilder();
            BufferedReader bufferedReader = llmService.chatChunk(response);
            String res;
            while ((res = bufferedReader.readLine()) != null) {
                if (StringUtils.isEmpty(res)) {
                    continue;
                }
                res = res.replace("data: ", StringUtils.EMPTY);
                LargeModelDemandResult result = JsonUtils.deSerialize(res, LargeModelDemandResult.class);
                if (ObjectUtil.isEmpty(result) || !result.getCode().equals("0")) {
                    logger.error("LLM Error,code:{}", result.getCode());
                    throw new BusinessException("获取关键词失败");
                }
                if (StringUtils.isNotBlank(result.getMessage())) {
                    String message = result.getMessage();
                    summary.append(message);
                }
            }
            bufferedReader.close();
            if (StringUtils.isBlank(summary.toString())) {
                logger.error("------------ summary is blank , check llm config -------------");
                throw new BusinessException("关键词提取失败");
            }
            String keywordStr = summary.toString();
            int start = keywordStr.lastIndexOf("[");
            int end = keywordStr.lastIndexOf("]");
            List<String> keywords = JsonUtils.deSerialize(keywordStr.substring(start, end + 1), new TypeReference<List<String>>() {
            }.getType());
            if (CollectionUtils.isEmpty(keywords)) {
                logger.error("------------ keywords is blank , check llm config -------------");
                throw new BusinessException("关键词提取失败");
            }

            //匹配关键词在文章中句子[按标点符号切分]/计算关键词频率
            Map<String, Integer> keywordCountMap = KeyWordCounter.keywordCount(document, keywords);
            Map<String, List<String>> matchSentenceMap = KeyWordCounter.keywordMatchSentence(document, keywords);
            List<MentionFrequency> mentionFrequencies = new ArrayList<>();
            for (String keyword : keywordCountMap.keySet()) {
                MentionFrequency mentionFrequency = new MentionFrequency();
                mentionFrequency.setKeyword(keyword);
                mentionFrequency.setSentences(matchSentenceMap.get(keyword).stream().distinct().collect(Collectors.toList()));
                mentionFrequency.setFrequency(keywordCountMap.get(keyword));
                mentionFrequencies.add(mentionFrequency);
            }
            // 相关概念
            List<String> concepts = createConcepts(document);
            KeyWord keyWord = new KeyWord();
            keyWord.setKeyWord(new ArrayList<>(keywordCountMap.keySet()));
            keyWord.setMentionFrequency(mentionFrequencies);
            keyWord.setConcepts(concepts);

            return keyWord;
        } catch (Exception e) {
            logger.error("获取关键词失败", e);
            throw new BusinessException("获取关键词失败");
        }
    }

    private List<String> createConcepts(String document) {
        // 获取对话提示词
        String promptCode = "CreateConceptsPrompt";
        BizAgentApplicationGcConfigEntity documentDialoguePrompt = bizAgentApplicationGcConfigService.getByConfigCode(promptCode);
        if (documentDialoguePrompt == null || StringUtils.isBlank(documentDialoguePrompt.getConfigSystem())) {
            logger.error("获取对话提示词失败 , configCode:{}", promptCode);
            throw new BusinessException("获取对话提示词失败");
        }

        String prompt = documentDialoguePrompt.getConfigSystem();
        String largeModel = documentDialoguePrompt.getLargeModel();

        prompt = prompt.replace("{document}", document);
        // 配置message
        List<Message> messages = new ArrayList<>();
        Message systemMessage = new Message();
        systemMessage.setContent(prompt);
        systemMessage.setRole(LLMRoleEnum.SYSTEM.getRole());
        messages.add(systemMessage);


        Message questionMessage = new Message();
        questionMessage.setContent("生成相关概念");
        questionMessage.setRole(LLMRoleEnum.USER.getRole());
        messages.add(questionMessage);

        // 调用LLM
        LargeModelResponse response = new LargeModelResponse();
        response.setModel(largeModel);
        response.setMessages(messages.toArray(new Message[0]));
        response.setStream(true);
        response.setUser("CreateMindMap");
        try {
            StringBuilder summary = new StringBuilder();
            BufferedReader bufferedReader = llmService.chatChunk(response);
            String res;
            while ((res = bufferedReader.readLine()) != null) {
                if (StringUtils.isEmpty(res)) {
                    continue;
                }
                res = res.replace("data: ", StringUtils.EMPTY);
                LargeModelDemandResult result = JsonUtils.deSerialize(res, LargeModelDemandResult.class);
                if (ObjectUtil.isEmpty(result) || !result.getCode().equals("0")) {
                    logger.error("LLM Error,code:{}", result.getCode());
                    throw new BusinessException("生成相关概念失败");
                }
                if (StringUtils.isNotBlank(result.getMessage())) {
                    String message = result.getMessage();
                    summary.append(message);
                }
            }
            bufferedReader.close();
            String result = summary.toString();
            if (StringUtils.isBlank(result)) {
                return ListUtils.EMPTY_LIST;
            }

            int startMindMap = result.indexOf("[");
            int endMindMap = result.lastIndexOf("]");
            return JsonUtils.deSerialize(result.substring(startMindMap, endMindMap + 1), new TypeReference<List<String>>() {
            }.getType());
        } catch (Exception e) {
            logger.error("-----------生成相关概念失败------------", e);
            return ListUtils.EMPTY_LIST;
        }

    }

    private String createMindMap(String document) {
        // 获取对话提示词
        String promptCode = "CreateMindMapPrompt";
        BizAgentApplicationGcConfigEntity documentDialoguePrompt = bizAgentApplicationGcConfigService.getByConfigCode(promptCode);
        if (documentDialoguePrompt == null || StringUtils.isBlank(documentDialoguePrompt.getConfigSystem())) {
            logger.error("获取对话提示词失败 , configCode:{}", promptCode);
            throw new BusinessException("获取对话提示词失败");
        }

        String prompt = documentDialoguePrompt.getConfigSystem();
        String largeModel = documentDialoguePrompt.getLargeModel();

        prompt = prompt.replace("{document}", document);
        // 配置message
        List<Message> messages = new ArrayList<>();
        Message systemMessage = new Message();
        systemMessage.setContent(prompt);
        systemMessage.setRole(LLMRoleEnum.SYSTEM.getRole());
        messages.add(systemMessage);


        Message questionMessage = new Message();
        questionMessage.setContent("生成思维导图");
        questionMessage.setRole(LLMRoleEnum.USER.getRole());
        messages.add(questionMessage);

        // 调用LLM
        LargeModelResponse response = new LargeModelResponse();
        response.setModel(largeModel);
        response.setMessages(messages.toArray(new Message[0]));
        response.setStream(true);
        response.setUser("CreateMindMap");
        try {
            StringBuilder summary = new StringBuilder();
            BufferedReader bufferedReader = llmService.chatChunk(response);
            String res;
            while ((res = bufferedReader.readLine()) != null) {
                if (StringUtils.isEmpty(res)) {
                    continue;
                }
                res = res.replace("data: ", StringUtils.EMPTY);
                LargeModelDemandResult result = JsonUtils.deSerialize(res, LargeModelDemandResult.class);
                if (ObjectUtil.isEmpty(result) || !result.getCode().equals("0")) {
                    logger.error("LLM Error,code:{}", result.getCode());
                    throw new BusinessException("生成思维导图失败");
                }
                if (StringUtils.isNotBlank(result.getMessage())) {
                    String message = result.getMessage();
                    summary.append(message);
                }
            }
            bufferedReader.close();
            return summary.toString();
        } catch (Exception e) {
            logger.error("生成思维导图失败", e);
            throw new BusinessException("生成思维导图失败");
        }
    }

    private ToolFunction getToolFunction(String dialoguesId, String input, Boolean enableSearchEngine, SSEUtil sseUtil) throws IOException {
        ToolFunction toolFunction = null;
        if (enableSearchEngine) {
            List<Message> messages = new ArrayList<>();
            Message message = new Message();
            message.setRole("user");
            message.setContent(input);
            messages.add(message);

            String[] unitIds = new String[1];
            unitIds[0] = "web_search";
            List<Tool> tools = AgentApplicationTools.buildFunctionConfig(null, "N", dialoguesId, dialoguesId, unitIds, "N");
            CheckPluginUseEntity checkPluginUseEntity = AgentApplicationTools.checkPluginUse(messages, tools, null);
            FunctionCallResult functionCallResult = checkPluginUseEntity.getFunctionCallResult();
            if (functionCallResult != null && functionCallResult.isNeed()) {
                FunctionCall functionCall = functionCallResult.getFunctionCall();
                if (functionCallResult.isNeed() && functionCall != null && "web_search".equals(functionCall.getName())) {
                    AbstractFunctionResult<List<WebSearchFunctionResult>> functionResult = webSearchFunction.doFunction(functionCall.getArguments(), dialoguesId, null, null);
                    if (functionResult != null && CollectionUtils.isNotEmpty(functionResult.getFunctionResult())) {
                        List<WebSearchFunctionResult> webSearchFunctionResults = functionResult.getFunctionResult();
                        if (CollectionUtils.isNotEmpty(webSearchFunctionResults)) {
                            toolFunction = new ToolFunction();
                            toolFunction.setResult(JsonUtils.serialize(webSearchFunctionResults));
                            toolFunction.setName("web_search");
                            toolFunction.setArguments(functionCall.getArguments());
                            toolFunction.setDisplayFormat("json");
                            LargeModelDemandResult result = new LargeModelDemandResult();
                            result.setCode("0");
                            result.setFunction(toolFunction);
                            result.setDbChainResult(null);
                            result.setKnowledgeContentResult(null);
                            sseUtil.send(JsonUtils.serialize(result));
                        }
                    }
                }
            }
        }
        return toolFunction;
    }
}
