package com.ruoyi.web.llm.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.llm.domain.CmcChat;
import com.ruoyi.llm.domain.CmcDocument;
import com.ruoyi.llm.service.ICmcChatService;
import com.ruoyi.llm.service.ICmcDocumentService;
import com.ruoyi.web.llm.service.ILangChainMilvusService;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.parser.TextDocumentParser;
import dev.langchain4j.data.document.parser.apache.pdfbox.ApachePdfBoxDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentByParagraphSplitter;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.embedding.onnx.bgesmallzhv15.BgeSmallZhV15EmbeddingModel;
import dev.langchain4j.store.embedding.EmbeddingMatch;
import dev.langchain4j.store.embedding.EmbeddingSearchRequest;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.collection.request.LoadCollectionReq;
import io.milvus.v2.service.collection.request.ReleaseCollectionReq;
import io.milvus.v2.service.vector.request.DeleteReq;
import io.milvus.v2.service.vector.request.InsertReq;
import io.milvus.v2.service.vector.request.SearchReq;
import io.milvus.v2.service.vector.request.data.BaseVector;
import io.milvus.v2.service.vector.request.data.FloatVec;
import io.milvus.v2.service.vector.response.InsertResp;
import io.milvus.v2.service.vector.response.SearchResp;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Paragraph;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.noear.solon.ai.chat.ChatModel;
import org.noear.solon.ai.chat.ChatResponse;
import org.noear.solon.ai.chat.ChatSession;
import org.noear.solon.ai.chat.message.ChatMessage;
import org.noear.solon.ai.chat.prompt.Prompt;
import org.noear.solon.ai.chat.session.InMemoryChatSession;
import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.*;
import java.util.*;

@Service
public class LangChainMilvusServiceImpl implements ILangChainMilvusService
{
    @Autowired
    private ICmcChatService cmcChatService;

    @Autowired
    private ICmcDocumentService cmcDocumentService;

    private static final EmbeddingModel embeddingModel = new BgeSmallZhV15EmbeddingModel();

    private String processValue = "";

    @Value("${cmc.llmService.url}")
    private String llmServiceUrl;

    @Value("${cmc.milvusService.url}")
    private String milvusServiceUrl;

    private MilvusClientV2 milvusClient;

    // 复用 ChatModel 实例
    private ChatModel chatModel;

    @PostConstruct
    public void initMilvusClient() {
        if (milvusServiceUrl == null || milvusServiceUrl.isEmpty()) {
            throw new IllegalArgumentException("milvusServiceUrl 配置不能为空");
        }
        milvusClient = new MilvusClientV2(
                ConnectConfig.builder()
                        .uri(milvusServiceUrl)
                        .build());
    }

    @PostConstruct
    public void initChatModel() {
        // 初始化 ChatModel
        chatModel = ChatModel.of(llmServiceUrl)
                .model("Qwen")
                .build();
    }

    @PreDestroy
    public void destroyMilvusClient() {
        if (milvusClient != null) {
            try {
                // 关闭 Milvus 客户端，释放 gRPC 通道
                milvusClient.close();
                System.out.println("Milvus client closed successfully");
            } catch (Exception e) {
                System.err.println("Error closing Milvus client: " + e.getMessage());
                e.printStackTrace();
            }
        }
    }

    /**
     * 上传多文件
     *
     * @return 结果
     */
    public String getProcess() {
        return processValue;
    }

    /**
     * 导入知识库文件
     * @return
     */
    @Override
    public int insertLangchainEmbeddingDocument(MultipartFile[] fileList, String collectionName)
    {
        processValue = "";
        int successfullyInsertedFiles = 0;

        for (int i = 0; i < fileList.length; i++) {
            MultipartFile file = fileList[i];
            try {
                // 构建上传目录路径
                String uploadDir = RuoYiConfig.getProfile() + "/upload/rag/knowledge/" + collectionName;
                File profilePath = new File(uploadDir);

                // 确保目录存在，创建目录并设置权限
                if (!profilePath.exists())
                    profilePath.mkdirs();
                File transferFile = new File(profilePath, file.getOriginalFilename());
                if (!transferFile.exists())
                    file.transferTo(transferFile);
                List<TextSegment> segments = splitDocument(transferFile);

                // 准备导入数据
                List<JsonObject> data = new ArrayList<>();
                // 提取文本和生成嵌入
                for (TextSegment segment : segments) {
                    String text = segment.text();
                    if (text.trim().isEmpty())
                        continue;

                    JSONObject fastjsonObj = new JSONObject();
                    fastjsonObj.put("file_name", file.getOriginalFilename());
                    String[] fileName = file.getOriginalFilename().split("\\.");
                    fastjsonObj.put("file_type", fileName[fileName.length - 1]);
                    fastjsonObj.put("title", text.split("\n")[0].split(" ")[1]);
                    fastjsonObj.put("content", text);
                    fastjsonObj.put("embedding", embeddingModel.embed(text).content().vectorAsList());
                    String jsonString = fastjsonObj.toJSONString();
                    JsonObject jsonObject = JsonParser.parseString(jsonString).getAsJsonObject();
                    data.add(jsonObject);
                }

                // 添加一条包含所有二、三级标题的记录
                String titlesContent = extractAllTitles(transferFile);
                if (!titlesContent.trim().isEmpty()) {
                    JSONObject titlesJsonObj = new JSONObject();
                    titlesJsonObj.put("file_name", file.getOriginalFilename());
                    titlesJsonObj.put("file_type", "标题");
                    titlesJsonObj.put("title", "");
                    titlesJsonObj.put("content", titlesContent);
                    titlesJsonObj.put("embedding", embeddingModel.embed(titlesContent).content().vectorAsList());
                    String titlesJsonString = titlesJsonObj.toJSONString();
                    JsonObject titlesJsonObject = JsonParser.parseString(titlesJsonString).getAsJsonObject();
                    data.add(titlesJsonObject);
                }

                // 加载集合
                LoadCollectionReq loadCollectionReq = LoadCollectionReq.builder()
                        .collectionName(collectionName)
                        .build();
                milvusClient.loadCollection(loadCollectionReq);

                try {
                    // 先删除相同文件名的记录
                    DeleteReq deleteReq = DeleteReq.builder()
                            .collectionName(collectionName)
                            .filter(String.format("file_name == \"%s\"", file.getOriginalFilename()))
                            .build();
                    if (milvusClient.delete(deleteReq).getDeleteCnt() > 0)
                        System.out.println("已删除同名文件记录: " + file.getOriginalFilename());

                    // 构建导入请求
                    InsertReq insertReq = InsertReq.builder()
                            .collectionName(collectionName)
                            .data(data)
                            .build();

                    // 执行导入并检查结果
                    InsertResp insertResp = milvusClient.insert(insertReq);
                    if (insertResp != null && insertResp.getInsertCnt() > 0) {
                        successfullyInsertedFiles++;
                        processValue = "上传中: " + String.format("%.2f", (double) (i + 1) / fileList.length * 100) + "%";
                        System.out.println("成功导入" + (i + 1) + "/" + fileList.length + "文件: " + file.getOriginalFilename() + ", 导入记录数: " + insertResp.getInsertCnt());
                    } else {
                        System.err.println("文件导入失败: " + file.getOriginalFilename() + ", 没有记录被导入");
                    }
                } finally {
                    // 释放集合
                    ReleaseCollectionReq releaseCollectionReq = ReleaseCollectionReq.builder()
                            .collectionName(collectionName)
                            .build();
                    milvusClient.releaseCollection(releaseCollectionReq);
                }
            } catch (Exception e) {
                System.err.println("处理文件时出错: " + file.getOriginalFilename() + ", 错误: " + e.getMessage());
                e.printStackTrace();
                // 继续处理下一个文件
            }
        }

        processValue = "上传完成";
        return successfullyInsertedFiles;
    }

    /**
     * 从Milvus检索相关文档
     * @return
     */
    @Override
    public List<JSONObject> retrieveFromMilvus(String collectionName, String query, int topK) {
        List<JSONObject> resultList = new ArrayList<>();
        List<List<SearchResp.SearchResult>> searchResultList = retrieve(collectionName, query, topK);
        searchResultList.forEach(searchResult -> {
            JSONObject result = new JSONObject();
            result.put("file_name", searchResult.get(0).getEntity().get("file_name"));
            result.put("content", searchResult.get(0).getEntity().get("content"));
            resultList.add(result);
        });
        return resultList;
    }

    /**
     * 从Milvus检索相关文档及相关度
     * @return
     */
    @Override
    public List<JSONObject> similarityFromMilvus(String collectionName, String query, int topK) {
        List<JSONObject> resultList = new ArrayList<>();
        List<List<SearchResp.SearchResult>> searchResultList = retrieve(collectionName, query, topK);
        searchResultList.forEach(searchResult -> {
            JSONObject result = new JSONObject();
            result.put("score", searchResult.get(0).getScore());
            result.put("file_name", searchResult.get(0).getEntity().get("file_name"));
            result.put("content", searchResult.get(0).getEntity().get("content"));
            resultList.add(result);
        });
        resultList.removeIf(jsonObject -> jsonObject.getDouble("score") < 0.7);
        return resultList;
    }

    /**
     * 调用LLM生成回答
     * @return
     */
    @Override
    public Flux<String> generateAnswer(String topicId, String prompt) {
        List<ChatMessage> messages = new ArrayList<>();
        if (topicId != null) {
            CmcChat cmcChat = new CmcChat();
            cmcChat.setTopicId(topicId);
            List<CmcChat> cmcChatList = cmcChatService.selectCmcChatList(cmcChat);
            for (CmcChat chat : cmcChatList) {
                messages.add(ChatMessage.ofUser(chat.getInput()));
                messages.add(ChatMessage.ofAssistant(chat.getOutput()));
            }
        }
        messages.add(ChatMessage.ofUser(prompt));
        ChatSession chatSession =  InMemoryChatSession.builder().messages(messages).build();
        Prompt prompt1 = Prompt.of(prompt).attrPut("session", chatSession);
        Publisher<ChatResponse> publisher = chatModel.prompt(prompt1).stream();
        return Flux.from(publisher)
                .map(response -> response.lastChoice().getMessage().getContent())
                .map(this::toSseDataFrame)
                .concatWith(Flux.just("data: [DONE]\n\n"));
    }

    private String toSseDataFrame(String data) {
        if (data == null) {
            return "data: \n\n";
        }
        // SSE 要求每一行都以 data: 开头
        String normalized = data.replace("\r\n", "\n");
        StringBuilder sb = new StringBuilder(normalized.length() + 16);
        sb.append("data: ");
        int start = 0;
        while (true) {
            int idx = normalized.indexOf('\n', start);
            if (idx < 0) {
                sb.append(normalized.substring(start));
                break;
            }
            sb.append(normalized, start, idx);
            sb.append("\n");
            sb.append("data: ");
            start = idx + 1;
        }
        sb.append("\n\n");
        return sb.toString();
    }

    /**
     * 调用LLM+RAG生成回答
     * @return
     */
    @Override
    public Flux<String> generateAnswerWithCollection(String topicId, String question, List<JSONObject> contexts) {
        StringBuilder sb = new StringBuilder();
        sb.append("问题: ").append(question).append("\n\n");
        sb.append("根据以下上下文回答问题：\n\n");
        for (JSONObject context : contexts) {
            sb.append("文件").append(": ")
                    .append(context.getString("file_name")).append("\n\n")
                    .append("上下文").append(": ")
                    .append(context.getString("content")).append("\n\n");
        }
        return generateAnswer(topicId, sb.toString());
    }

    /**
     * 调用LLM生成回答
     */
    @Override
    public Flux<String> generateAnswerWithDocument(String topicId, String chatId, String question) throws Exception {
        CmcDocument cmcDocument = new CmcDocument();
        cmcDocument.setChatId(chatId);
        List<CmcDocument> documentList = cmcDocumentService.selectCmcDocumentList(cmcDocument);
        StringBuilder sb = new StringBuilder("问题: " + question + "\n\n").append("根据以下上下文回答问题：\n\n");
        for (CmcDocument document : documentList) {
            File profilePath = new File(RuoYiConfig.getProfile() + document.getPath());
            InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
            List<TextSegment> segments = splitDocument(profilePath);
            List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
            embeddingStore.addAll(embeddings, segments);
            Embedding queryEmbedding = embeddingModel.embed(question).content();
            EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest.builder()
                    .queryEmbedding(queryEmbedding)
                    .minScore(0.7)
                    .build();
            List<EmbeddingMatch<TextSegment>> results = embeddingStore.search(embeddingSearchRequest).matches();
            results.sort(Comparator.comparingDouble(EmbeddingMatch<TextSegment>::score).reversed());
            for (EmbeddingMatch<TextSegment> embeddingMatch : results) {
                String contexts = embeddingMatch.embedded().toString();
                sb.append("文件").append(": ")
                        .append(document.getPath()).append("\n\n")
                        .append("上下文").append(": ")
                        .append(contexts).append("\n\n");
            }
        }
        return generateAnswer(topicId, sb.toString());
    }

    /**
     * 调用LLM生成回答
     */
    @Override
    public Flux<String> generateAnswerWithDocumentAndCollection(String topicId, String question, List<JSONObject> contexts) throws Exception {
        StringBuilder sb = new StringBuilder("招标文件内容：\n\n");
        CmcChat cmcChat = new CmcChat();
        cmcChat.setTopicId(topicId);
        for (CmcChat chat : cmcChatService.selectCmcChatList(cmcChat)) {
            CmcDocument cmcDocument = new CmcDocument();
            cmcDocument.setChatId(chat.getChatId());
            List<CmcDocument> documentList = cmcDocumentService.selectCmcDocumentList(cmcDocument);
            //技术标书撰写智能体一个话题只会上传一个招标文件
            if (documentList.size() == 1) {
                for (CmcDocument document : documentList) {
                    File profilePath = new File(RuoYiConfig.getProfile() + document.getPath());
                    InMemoryEmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
                    List<TextSegment> segments = splitDocument(profilePath);
                    List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
                    embeddingStore.addAll(embeddings, segments);
                    Embedding queryEmbedding = embeddingModel.embed(question).content();
                    EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest.builder()
                            .queryEmbedding(queryEmbedding)
                            .minScore(0.7)
                            .build();
                    List<EmbeddingMatch<TextSegment>> results = embeddingStore.search(embeddingSearchRequest).matches();
                    results.sort(Comparator.comparingDouble(EmbeddingMatch<TextSegment>::score).reversed());
                    for (EmbeddingMatch<TextSegment> embeddingMatch : results) {
                        String requests = embeddingMatch.embedded().toString();
                        sb.append(requests).append("\n\n");
                    }
                }
            }
        }
        sb.append("针对本项目招标文件内容，补全以下章节部分：\n\n").append(question);
//        for (JSONObject context : contexts) {
//            sb.append("文件").append(": ")
//                    .append(context.getString("file_name")).append("\n\n")
//                    .append("段落格式").append(": ")
//                    .append(context.getString("content")).append("\n\n");
//        }
        return generateAnswer(topicId, sb.toString());
    }

    /**
     * 获取二级标题下三级标题列表
     */
    @Override
    public List<String> extractSubTitles(String filename, String question) throws IOException {
        List<String> subTitles = new ArrayList<>();
        boolean inTargetSection = false;

        InputStream fileInputStream = new FileInputStream(filename);
        try (XWPFDocument document = new XWPFDocument(fileInputStream)) {
            for (XWPFParagraph paragraph : document.getParagraphs()) {
                String text = paragraph.getText().trim();
                if (paragraph.getStyle() != null) {
                    // 判断主标题
                    if (paragraph.getStyle().equals("3") &&
                            text.contains(question)) {
                        inTargetSection = true;
                        continue;
                    }

                    // 如果已经在目标节中，收集标题3级别的子标题
                    if (inTargetSection) {
                        if (paragraph.getStyle().equals("4")) {
                            subTitles.add(text);
                        }
                        // 遇到下一个Heading1则退出
                        else if (paragraph.getStyle().equals("3")) {
                            break;
                        }
                    }
                }
            }
        }
        if (subTitles.size() == 0)
            subTitles.add(question);
        return subTitles;
    }

    /**
     * 检索知识库
     * @return
     */
    private List<List<SearchResp.SearchResult>> retrieve(String collectionName, String query, int topK) {
        List<BaseVector> queryVector = Collections.singletonList(new FloatVec(embeddingModel.embed(query).content().vector()));

        //  加载集合
        LoadCollectionReq loadCollectionReq = LoadCollectionReq.builder()
                .collectionName(collectionName)
                .build();
        milvusClient.loadCollection(loadCollectionReq);

        // 构建SearchParam
        Map<String, Object> searchParams = new HashMap<>();
        searchParams.put("nprobe", 8);
        SearchReq searchReq = SearchReq.builder()
                .collectionName(collectionName)
                .data(queryVector)
                .topK(topK)
                .outputFields(Arrays.asList("file_name", "file_type", "content"))
                .annsField("embedding")
                .metricType(IndexParam.MetricType.COSINE)
                .searchParams(searchParams)
                .build();

        SearchResp searchResp = milvusClient.search(searchReq);
        List<List<SearchResp.SearchResult>> searchResultList = searchResp.getSearchResults();

        // 释放集合
        ReleaseCollectionReq releaseCollectionReq = ReleaseCollectionReq.builder()
                .collectionName(collectionName)
                .build();
        milvusClient.releaseCollection(releaseCollectionReq);

        return searchResultList;
    }

    /**
     * 提取文档中的所有二、三级标题
     */
    private String extractAllTitles(File transferFile) throws Exception {
        StringBuilder titlesBuilder = new StringBuilder();
        String filename = transferFile.getName().toLowerCase();

        if (filename.endsWith(".docx")) {
            try (XWPFDocument document = new XWPFDocument(new FileInputStream(transferFile))) {
                for (XWPFParagraph paragraph : document.getParagraphs()) {
                    String text = paragraph.getText().trim();
                    if (text.isEmpty()) continue;
                    if (paragraph.getStyle() != null) {
                        if (paragraph.getStyle().equals("2") || paragraph.getStyle().equals("3")) {
                            titlesBuilder.append(text).append("\n");
                        }
                    }
                }
            }
        } else if (filename.endsWith(".doc")) {
            try (HWPFDocument document = new HWPFDocument(new FileInputStream(transferFile))) {
                Range range = document.getRange();
                for (int i = 0; i < range.numParagraphs(); i++) {
                    Paragraph paragraph = range.getParagraph(i);
                    String text = paragraph.text().trim();
                    if (text.isEmpty()) continue;
                    short styleIndex = paragraph.getStyleIndex();
                    if (styleIndex == 2 || styleIndex == 3) {
                        titlesBuilder.append(text).append("\n");
                    }
                }
            }
        }
        return titlesBuilder.toString();
    }

    /**
     * 检索知识库
     */
    private List<TextSegment> splitDocument(File transferFile) throws Exception {
        // 加载文档
        Document document;
        InputStream fileInputStream = new FileInputStream(transferFile);
        String filename = transferFile.getName().toLowerCase();
        if (filename.endsWith(".docx")) {
            // 使用XWPFDocument处理DOCX文件，按二级标题分割（二级标题样式为2）
            List<TextSegment> segments = new ArrayList<>();
            try (XWPFDocument xwpfDocument = new XWPFDocument(fileInputStream)) {
                StringBuilder currentLevel2Content = new StringBuilder();
                boolean inLevel2Section = false;

                for (XWPFParagraph paragraph : xwpfDocument.getParagraphs()) {
                    String text = paragraph.getText().trim();
                    if (text.isEmpty()) continue;

                    if (paragraph.getStyle() != null) {
                        // 二级标题（样式2）开始新的分段
                        if (paragraph.getStyle().equals("2")) {
                            // 保存当前二级标题下的内容
                            if (currentLevel2Content.length() != 0) {
                                // 检查当前二级标题内容的字节数
                                int level2Length = currentLevel2Content.toString().getBytes().length;
                                if (level2Length <= 65535) {
                                    // 字数不大于65535，按二级标题分割
                                    TextSegment segment = TextSegment.from(currentLevel2Content.toString());
                                    segments.add(segment);
                                } else {
                                    // 字数大于65535，按三级标题分割
                                    // 将当前二级标题内容按三级标题重新分割
                                    StringBuilder currentLevel3Content = new StringBuilder();
                                    String[] paragraphs = currentLevel2Content.toString().split("\n");
                                    for (String para : paragraphs) {
                                        if (para.trim().isEmpty()) continue;

                                        // 检查是否是三级标题（简单判断：如果是三级标题，样式应该是3，但这里需要重新解析）
                                        // 由于已经将内容转为字符串，这里采用另一种方式：假设三级标题以数字+点+空格开头（如"1.1."）
                                        // 或者可以重新遍历段落，但为了效率，这里采用简单的判断方式
                                        boolean isLevel3Title = false;
                                        for (XWPFParagraph p : xwpfDocument.getParagraphs()) {
                                            if (p.getText().trim().equals(para.trim()) && p.getStyle() != null && p.getStyle().equals("3")) {
                                                isLevel3Title = true;
                                                break;
                                            }
                                        }

                                        if (isLevel3Title) {
                                            // 保存当前三级标题内容
                                            if (currentLevel3Content.length() != 0) {
                                                TextSegment segment = TextSegment.from(currentLevel3Content.toString());
                                                segments.add(segment);
                                                currentLevel3Content = new StringBuilder();
                                            }
                                            // 开始新的三级标题内容
                                            currentLevel3Content.append(para).append("\n");
                                        } else {
                                            // 普通内容，添加到当前三级标题
                                            if (currentLevel3Content.length() != 0) {
                                                currentLevel3Content.append(para).append("\n");
                                            }
                                        }
                                    }
                                    // 保存最后一个三级标题内容
                                    if (currentLevel3Content.length() != 0) {
                                        TextSegment segment = TextSegment.from(currentLevel3Content.toString());
                                        segments.add(segment);
                                    }
                                }
                                currentLevel2Content = new StringBuilder();
                            }
                            // 开始新的二级标题内容
                            currentLevel2Content.append(text).append("\n");
                            inLevel2Section = true;
                        }
                        // 其他标题样式（包括三级标题）
                        else {
                            if (inLevel2Section) {
                                currentLevel2Content.append(text).append("\n");
                            }
                        }
                    }
                    else {
                        // 普通内容段落
                        if (inLevel2Section) {
                            currentLevel2Content.append(text).append("\n");
                        }
                    }
                }

                // 保存最后一个二级标题内容
                if (currentLevel2Content.length() != 0) {
                    // 检查字节数
                    int level2Length = currentLevel2Content.toString().getBytes().length;
                    if (level2Length <= 65535) {
                        // 字数不大于65535，按二级标题分割
                        TextSegment segment = TextSegment.from(currentLevel2Content.toString());
                        segments.add(segment);
                    } else {
                        // 字数大于65535，按三级标题分割
                        StringBuilder currentLevel3Content = new StringBuilder();
                        String[] paragraphs = currentLevel2Content.toString().split("\n");
                        for (String para : paragraphs) {
                            if (para.trim().isEmpty()) continue;

                            boolean isLevel3Title = false;
                            for (XWPFParagraph p : xwpfDocument.getParagraphs()) {
                                if (p.getText().trim().equals(para.trim()) && p.getStyle() != null && p.getStyle().equals("3")) {
                                    isLevel3Title = true;
                                    break;
                                }
                            }

                            if (isLevel3Title) {
                                // 保存当前三级标题内容
                                if (currentLevel3Content.length() != 0) {
                                    TextSegment segment = TextSegment.from(currentLevel3Content.toString());
                                    segments.add(segment);
                                    currentLevel3Content = new StringBuilder();
                                }
                                // 开始新的三级标题内容
                                currentLevel3Content.append(para).append("\n");
                            } else {
                                // 普通内容，添加到当前三级标题
                                if (currentLevel3Content.length() != 0) {
                                    currentLevel3Content.append(para).append("\n");
                                }
                            }
                        }
                        // 保存最后一个三级标题内容
                        if (currentLevel3Content.length() != 0) {
                            TextSegment segment = TextSegment.from(currentLevel3Content.toString());
                            segments.add(segment);
                        }
                    }
                }
            }
            return segments;
        }
        else if (filename.endsWith(".doc")) {
            // 使用HWPFDocument处理DOC文件
            List<TextSegment> segments = new ArrayList<>();
            try (HWPFDocument hwpfDocument = new HWPFDocument(fileInputStream)) {
                StringBuilder currentLevel2Content = new StringBuilder();
                boolean inLevel2Section = false;

                Range range = hwpfDocument.getRange();
                for (int i = 0; i < range.numParagraphs(); i++) {
                    Paragraph paragraph = range.getParagraph(i);
                    String text = paragraph.text().trim();
                    if (text.isEmpty()) continue;

                    // 获取段落样式索引
                    short styleIndex = paragraph.getStyleIndex();

                    if (styleIndex == 2) {
                        // 二级标题，开始新的分段
                        // 保存当前二级标题下的内容
                        if (currentLevel2Content.length() != 0) {
                            // 检查当前二级标题内容的字节数
                            int level2Length = currentLevel2Content.toString().getBytes().length;
                            if (level2Length <= 65535) {
                                // 字数不大于65535，按二级标题分割
                                TextSegment segment = TextSegment.from(currentLevel2Content.toString());
                                segments.add(segment);
                            } else {
                                // 字数大于65535，按三级标题分割
                                // 将当前二级标题内容按三级标题重新分割
                                StringBuilder currentLevel3Content = new StringBuilder();
                                Range level2Range = hwpfDocument.getRange();
                                boolean foundCurrentLevel2 = false;

                                for (int j = 0; j < level2Range.numParagraphs(); j++) {
                                    Paragraph p = level2Range.getParagraph(j);
                                    String paraText = p.text().trim();
                                    if (paraText.isEmpty()) continue;

                                    // 找到当前二级标题的开始
                                    if (p.getStyleIndex() == 2 && paraText.equals(currentLevel2Content.toString().split("\n")[0].trim())) {
                                        foundCurrentLevel2 = true;
                                    }

                                    if (foundCurrentLevel2) {
                                        short paraStyleIndex = p.getStyleIndex();

                                        if (paraStyleIndex == 3) {
                                            // 三级标题
                                            // 保存当前三级标题内容
                                            if (currentLevel3Content.length() != 0) {
                                                TextSegment segment = TextSegment.from(currentLevel3Content.toString());
                                                segments.add(segment);
                                                currentLevel3Content = new StringBuilder();
                                            }
                                            // 开始新的三级标题内容
                                            currentLevel3Content.append(paraText).append("\n");
                                        } else if (paraStyleIndex == 2 && !paraText.equals(currentLevel2Content.toString().split("\n")[0].trim())) {
                                            // 下一个二级标题，结束当前二级标题的处理
                                            break;
                                        } else {
                                            // 普通内容或当前二级标题
                                            if (currentLevel3Content.length() != 0 || paraStyleIndex == 2) {
                                                currentLevel3Content.append(paraText).append("\n");
                                            }
                                        }
                                    }
                                }

                                // 保存最后一个三级标题内容
                                if (currentLevel3Content.length() != 0) {
                                    TextSegment segment = TextSegment.from(currentLevel3Content.toString());
                                    segments.add(segment);
                                }
                            }
                            currentLevel2Content = new StringBuilder();
                        }
                        // 开始新的二级标题内容
                        currentLevel2Content.append(text).append("\n");
                        inLevel2Section = true;
                    } else {
                        // 非二级标题或普通内容段落
                        if (inLevel2Section) {
                            currentLevel2Content.append(text).append("\n");
                        }
                    }
                }

                // 保存最后一个二级标题内容
                if (currentLevel2Content.length() != 0) {
                    // 检查字节数
                    int level2Length = currentLevel2Content.toString().getBytes().length;
                    if (level2Length <= 65535) {
                        // 字数不大于65535，按二级标题分割
                        TextSegment segment = TextSegment.from(currentLevel2Content.toString());
                        segments.add(segment);
                    } else {
                        // 字数大于65535，按三级标题分割
                        StringBuilder currentLevel3Content = new StringBuilder();
                        Range level2Range = hwpfDocument.getRange();
                        boolean foundCurrentLevel2 = false;

                        for (int j = 0; j < level2Range.numParagraphs(); j++) {
                            Paragraph p = level2Range.getParagraph(j);
                            String paraText = p.text().trim();
                            if (paraText.isEmpty()) continue;

                            // 找到当前二级标题的开始
                            if (p.getStyleIndex() == 2 && paraText.equals(currentLevel2Content.toString().split("\n")[0].trim())) {
                                foundCurrentLevel2 = true;
                            }

                            if (foundCurrentLevel2) {
                                short paraStyleIndex = p.getStyleIndex();

                                if (paraStyleIndex == 3) {
                                    // 三级标题
                                    // 保存当前三级标题内容
                                    if (currentLevel3Content.length() != 0) {
                                        TextSegment segment = TextSegment.from(currentLevel3Content.toString());
                                        segments.add(segment);
                                        currentLevel3Content = new StringBuilder();
                                    }
                                    // 开始新的三级标题内容
                                    currentLevel3Content.append(paraText).append("\n");
                                } else if (paraStyleIndex == 2 && !paraText.equals(currentLevel2Content.toString().split("\n")[0].trim())) {
                                    // 下一个二级标题，结束当前二级标题的处理
                                    break;
                                } else {
                                    // 普通内容或当前二级标题
                                    if (currentLevel3Content.length() != 0 || paraStyleIndex == 2) {
                                        currentLevel3Content.append(paraText).append("\n");
                                    }
                                }
                            }
                        }

                        // 保存最后一个三级标题内容
                        if (currentLevel3Content.length() != 0) {
                            TextSegment segment = TextSegment.from(currentLevel3Content.toString());
                            segments.add(segment);
                        }
                    }
                }
            }
            return segments;
        }
        else if (filename.endsWith(".pdf")) {
            document = new ApachePdfBoxDocumentParser().parse(fileInputStream);
        }
        else if (filename.endsWith(".txt")) {
            document = new TextDocumentParser().parse(fileInputStream);
        }
        else {
            throw new UnsupportedOperationException("不支持文件类型: " + filename);
        }
        DocumentByParagraphSplitter splitter = new DocumentByParagraphSplitter(300,50);
        return splitter.split(document);
    }

}