package com.qingyun.service.compare.service;

import cn.hutool.core.collection.CollectionUtil;
import com.agentsflex.core.llm.response.AiMessageResponse;
import com.agentsflex.core.message.AiMessage;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qingyun.common.exception.ServiceException;
import com.qingyun.service.agent.LlmStrategy;
import com.qingyun.service.agent.LlmStrategyFactory;
import com.qingyun.service.agent.TemplateManager;
import com.qingyun.service.compare.FetchAllPagesContent;
import com.qingyun.service.domain.ContractModelConfig;
import com.qingyun.service.domain.ContractReviewResult;
import com.qingyun.service.domain.ContractReviewTask;
import com.qingyun.service.mapper.ContractModelConfigMapper;
import com.qingyun.service.mapper.ContractReviewResultMapper;
import com.qingyun.service.mapper.ContractReviewTaskMapper;
import com.qingyun.service.utils.MarkdownUtils;
import com.qingyun.service.utils.PdfUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.text.PDFTextStripper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;


@Slf4j
@Component
@SuppressWarnings("all")
public class ReviewTaskService {

    @Autowired
    private ContractReviewTaskMapper baseMapper;

    @Autowired
    private ContractReviewResultMapper resultBaseMapper;

    @Autowired
    private ContractModelConfigMapper modelBaseMapper;

    @Autowired
    private PdfUtil pdfUtil;

    @Autowired
    private FetchAllPagesContent fetchAllPagesContent;

    // 使用Semaphore控制并发数
    private static final Semaphore semaphore = new Semaphore(5);

    @Transactional(rollbackFor = Exception.class)
    public void execute(ContractReviewTask contractReviewTask, Long modelId) {
        ExecutorService executor = null;
        try {
            String contractUrl = contractReviewTask.getContractUrl();
            String reviewElement = contractReviewTask.getReviewElement();
            String reviewRule = contractReviewTask.getReviewRule();

            String rulePromptTemp = TemplateManager.getTemplate("classpath:prompt/contractReview.txt");
            String elementPromptTemp = TemplateManager.getTemplate("classpath:prompt/reviewElement.txt");

            ContractModelConfig contractModelConfig = null;
            if (modelId !=  null) {
                contractModelConfig = modelBaseMapper.selectById(contractReviewTask.getModelId());
            }
            LlmStrategy strategy = LlmStrategyFactory.getStrategy(contractModelConfig);
            // 1. 并发获取所有页面内容
            String contractContentMd = contractReviewTask.getContractContentMd();
            if (StringUtils.isBlank(contractContentMd)) {
                parsePdf(contractReviewTask);
                contractContentMd = contractReviewTask.getContractContentMd();
            }

            // 获取所有页面内容, 数组索引为页码，从0开始
            List<String> pagesContent = JSONArray.parseArray(contractReviewTask.getContractContentMd(), String.class);
            if (CollectionUtil.isEmpty(pagesContent)) {
                log.error("合同内容为空，无法解析");
                contractReviewTask.setStatus(4);
                contractReviewTask.setErrorMsg("合同内容为空");
                baseMapper.updateById(contractReviewTask);
                return;
            }

            int totalPages = pagesContent.size();

            // 将页面分组：每3页一组
            List<List<String>> pageGroups = new ArrayList<>();
            List<List<Integer>> pageNumbers = new ArrayList<>(); // 记录每组对应的页码（从1开始）

            for (int i = 0; i < totalPages; i += 3) {
                List<String> group = new ArrayList<>();
                List<Integer> nums = new ArrayList<>();
                for (int j = i; j < i + 3 && j < totalPages; j++) {
                    group.add(pagesContent.get(j));
                    nums.add(j + 1); // 页码从1开始
                }
                pageGroups.add(group);
                pageNumbers.add(nums);
            }
            List<ContractReviewResult> allResults = new ArrayList<>();
            // 并发处理每组
            List<CompletableFuture<Void>> futures = new ArrayList<>();

            for (int i = 0; i < pageGroups.size(); i++) {
                List<String> group = pageGroups.get(i);
                List<Integer> pageNums = pageNumbers.get(i);

                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    try {
                        semaphore.acquire(); // 获取信号量

                        try {
                            // 构建 JSON 格式的上下文
                            JSONArray contextArray = new JSONArray();
                            for (int idx = 0; idx < group.size(); idx++) {
                                JSONObject item = new JSONObject();
                                item.put("pageNum", pageNums.get(idx));
                                item.put("context", StringUtils.defaultString(group.get(idx)));
                                contextArray.add(item);
                            }
                            String fullContextJson = contextArray.toJSONString();

                            if (StringUtils.isBlank(fullContextJson)) {
                                log.warn("分组页码 {} 内容为空，跳过", pageNums);
                                return;
                            }

                            // 构建参数
                            Map<String, String> elementParams = new HashMap<>();
                            elementParams.put("rules", reviewElement);
                            elementParams.put("context", fullContextJson);

                            Map<String, String> ruleParams = new HashMap<>();
                            ruleParams.put("rules", reviewRule);
                            ruleParams.put("context", fullContextJson);

                            AiMessageResponse elementResponse = null;
                            AiMessageResponse ruleResponse = null;

                            if (StringUtils.isNotBlank(reviewElement)) {
                                elementResponse = strategy.chat(elementPromptTemp, elementParams);
                                log.info("Element Response for pages {}: {}", pageNums, elementResponse);
                            }

                            if (StringUtils.isNotBlank(reviewRule)) {
                                ruleResponse = strategy.chat(rulePromptTemp, ruleParams);
                                log.info("Rule Response for pages {}: {}", pageNums, ruleResponse);
                            }

                            // 处理响应
                            synchronized (allResults) {
                                processResponses(elementResponse, ruleResponse, contractReviewTask, allResults);
                            }

                        } catch (Exception e) {
                            log.error("处理页码组 {} 时出错", pageNums, e);
                        } finally {
                            semaphore.release(); // 释放信号量
                        }
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        log.error("线程被中断", e);
                    }
                });

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

            // === 所有处理完成，现在统一入库 ===
            if (!allResults.isEmpty()) {
                resultBaseMapper.insertBatch(allResults);
            }

            contractReviewTask.setErrorMsg("执行成功");
            contractReviewTask.setStatus(3); // 成功
        } catch (ServiceException e) {
            log.error("执行任务失败", e.getMessage());
            contractReviewTask.setStatus(4);
            contractReviewTask.setErrorMsg(e.getMessage());
        } catch (Exception e) {
            log.error("contractReviewTask.{} 执行任务失败: {}", contractReviewTask.getTaskId(), e);
            contractReviewTask.setStatus(4);
            contractReviewTask.setErrorMsg("执行任务失败");

        } finally {
            if (executor != null) {
                executor.shutdown();
            }
        }
        baseMapper.updateById(contractReviewTask);
    }

    // 修改原有的 fetchAllPagesContent 方法以复用新方法
    private List<String> fetchAllPagesContent(String contractUrl, String contractName) throws Exception {
        File pdfFile = pdfUtil.downloadFile(contractUrl, contractName);
        try {
            return fetchAllPagesContent.extractPDFPagesContent(pdfFile);
        } finally {
            // 清理下载的原始文件
            Files.deleteIfExists(pdfFile.toPath());
        }
    }

    // 获取当前页的前一页末尾内容
    private String getPrevContext(List<String> pagesContent, int pageNum) {
        if (pageNum <= 0 || pageNum >= pagesContent.size()) return "";
        String prevContent = pagesContent.get(pageNum - 1);
        if (prevContent == null || prevContent.isEmpty()) return "";
        return prevContent.length() > 20 ? prevContent.substring(prevContent.length() - 20) : prevContent;
    }

    // 获取当前页的后一页开头内容
    private String getNextContext(List<String> pagesContent, int pageNum) {
        if (pageNum >= pagesContent.size() - 1) return "";
        String nextContent = pagesContent.get(pageNum + 1);
        if (nextContent == null || nextContent.isEmpty()) return "";
        return nextContent.length() > 20 ? nextContent.substring(0, 20) : nextContent;
    }

    // 解析保存审查结果
    private void processResponses(AiMessageResponse elementResponse,
                                  AiMessageResponse ruleResponse,
                                  ContractReviewTask task,
                                  List<ContractReviewResult> results) {
        processResponse(ruleResponse, task, 1, results);
        processResponse(elementResponse, task, 2, results);
    }

    /**
     * 处理单个响应并保存审查结果
     * [
     *   {
     *     "pageNum": "页码",
     *     "contractContent": "原文内容",
     *     "reviewBasis": "审查判断依据",
     *     "riskTips": "审查异常风险提示",
     *     "riskLevel": "无风险",
     *     "modifyExample": "建议修改示例"
     *   }
     * ]
     */
    private void processResponse(AiMessageResponse response, ContractReviewTask task, Integer specType, List<ContractReviewResult> results) {
        Optional.ofNullable(response)
            .map(AiMessageResponse::getMessage)
            .map(AiMessage::getContent)
            .filter(content -> !content.isEmpty())
            .ifPresent(content -> {
                // 移除 <think> 标签及其内容
                String cleanedContent = content.replaceAll("(?s)<think>.*?</think>", "");

                // 提取所有 JSON block
                List<String> jsonBlocks = MarkdownUtils.extractJsonBlocks(cleanedContent);
                if (jsonBlocks == null || jsonBlocks.isEmpty()) {
                    log.warn("未提取到有效的 JSON 内容，响应内容: {}", cleanedContent.substring(0, Math.min(200, cleanedContent.length())));
                    return;
                }
                String firstBlock = jsonBlocks.get(0);
                try {
                    List<ContractReviewResult> resultList = JSONArray.parseArray(firstBlock, ContractReviewResult.class);
                    if (resultList != null && !resultList.isEmpty()) {
                        resultList.forEach(result -> {
                            result.setTaskId(task.getTaskId());
                            result.setSpecType(specType);
                            results.add(result);
                        });

                    }
                } catch (Exception e) {
                    log.error("解析 JSON 失败", e);
                    e.printStackTrace(); // JSON 解析失败处理
                }
            });
    }


    /**
     * L base64 M 临时文件 R 是否内容为图片
     * @param pdfFile
     * @return
     * @throws IOException
     */
    private List<Triple<String, Object, Boolean>> splitPdfToBase64Pages(File pdfFile) throws IOException {
        List<Triple<String, Object, Boolean>> base64Pages = new ArrayList<>();
        try (PDDocument document = Loader.loadPDF(pdfFile)) {
            int pageCount = document.getNumberOfPages();
            for (int i = 0; i < pageCount; i++) {
                PDDocument pageDoc = new PDDocument();
                PDPage page = document.getPage(i);
                pageDoc.addPage(page);

                // 使用 try-with-resources 确保临时文件被正确处理
                File tempPageFile = null;
                try {
                    // 创建唯一的临时文件
                    tempPageFile = File.createTempFile("page_" + System.currentTimeMillis() + "_" + i, ".pdf");

                    // 保存页面到临时文件
                    pageDoc.save(tempPageFile);

                    // 转换为 Base64
                    byte[] pageBytes = Files.readAllBytes(tempPageFile.toPath());
                    String base64 = Base64.getEncoder().encodeToString(pageBytes);

                    // 判断是否扫描件
                    boolean scannedPdf = true;
                    try (PDDocument temp = Loader.loadPDF(tempPageFile)) {
                        PDFTextStripper stripper = new PDFTextStripper();
                        String text = stripper.getText(temp);
                        if (text != null && !text.trim().isEmpty()) {
                            scannedPdf = false;
                        }
                    }

                    base64Pages.add(ImmutableTriple.of(base64, null, scannedPdf));

                } finally {
                    // 确保在任何情况下都关闭并删除临时文件
                    pageDoc.close();
                    if (tempPageFile != null && tempPageFile.exists()) {
                        Files.deleteIfExists(tempPageFile.toPath());
                    }
                }
            }
        }
        return base64Pages;
    }

    /**
     * 解析PDF文件 转成成MD格式
     * @param contractReviewTask 合同审查任务对象
     */
    //@Async
    @Transactional(rollbackFor = Exception.class)
    public void parsePdf(ContractReviewTask contractReviewTask) {
        File originalFile = null;
        File pdfFile = null;
        try {
            String contractUrl = contractReviewTask.getContractUrl();
            String contractName = contractReviewTask.getContractName();

            // 下载原始文件
            originalFile = pdfUtil.downloadFile(contractUrl, contractName);

            // 获取所有页面内容 MD格式
            List<String> pagesContent = fetchAllPagesContent.extractPDFPagesContent(originalFile);
            if (pagesContent != null && !pagesContent.isEmpty()) {
                contractReviewTask.setContractContentMd(JSONArray.toJSONString(pagesContent));
            }

        } catch (Exception e) {
            log.error("解析文件失败: {}", e.getMessage(), e);
            contractReviewTask.setStatus(4);
            throw new ServiceException("解析文件失败: " + e.getMessage());
        } finally {
            // 清理临时文件
            try {
                if (originalFile != null && originalFile.exists()) {
                    Files.deleteIfExists(originalFile.toPath());
                }
                if (pdfFile != null && pdfFile.exists() && !pdfFile.equals(originalFile)) {
                    Files.deleteIfExists(pdfFile.toPath());
                }
            } catch (IOException e) {
                log.warn("清理临时文件失败: {}", e.getMessage());
            }
            baseMapper.updateById(contractReviewTask);
        }
    }

    /**
     * 获取文件扩展名
     * @param fileName 文件名
     * @return 文件扩展名（包括点号）
     */
    private String getFileExtension(String fileName) {
        if (fileName == null || fileName.lastIndexOf('.') == -1) {
            return ""; // 没有扩展名
        }
        return fileName.substring(fileName.lastIndexOf('.'));
    }


}
