package com.gxwebsoft.ai.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent11HistoryConstants;
import com.gxwebsoft.ai.service.AuditContent11HistoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import cn.hutool.core.util.StrUtil;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AuditContent11HistoryServiceImpl extends AbstractAuditContentService implements AuditContent11HistoryService {

    // 工作流配置
    private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-tMty75ly5NmqQXvBGZMxOKdk";
    
    @Override
    public JSONObject generateHistoryTableData(String kbIds, String libraryKbIds, String projectLibrary, 
                                              String userName, String history, String suggestion) {
        log.info("开始生成历史审计问题整改表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}", 
                userName, kbIds, libraryKbIds, projectLibrary);
        
        long startTime = System.currentTimeMillis();
        
        try {
            // 1. 检索相关知识
            Map<String, List<String>> knowledgeSources = retrieveHistoryAuditKnowledge(
                kbIds, libraryKbIds, projectLibrary
            );
            
            // 2. 构建完整的知识上下文
            String knowledgeContext = buildCompleteKnowledgeContext(
                knowledgeSources, history, suggestion
            );
            
            // 3. 调用工作流生成数据
            JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
            JSONArray tableData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "历史审计问题整改");
            
            // 4. 处理返回数据，确保格式正确
            JSONArray processedData = processTableData(tableData);
            
            log.info("历史审计问题整改表生成成功 - 记录数: {}, 处理时间: {}ms", 
                    processedData.size(), (System.currentTimeMillis() - startTime));
            
            return buildSuccessResponse(processedData, startTime, "history_audit_rectification");
            
        } catch (Exception e) {
            log.error("生成历史审计问题整改表失败", e);
            return buildErrorResponse("生成历史审计问题整改表失败: " + e.getMessage());
        }
    }
    
    /**
     * 检索历史审计问题相关知识
     */
    private Map<String, List<String>> retrieveHistoryAuditKnowledge(String kbIds, String libraryKbIds, String projectLibrary) {
        Map<String, List<String>> knowledgeSources = new HashMap<>();
        knowledgeSources.put("enterprise", new ArrayList<>());
        knowledgeSources.put("auditReports", new ArrayList<>());
        knowledgeSources.put("rectificationReports", new ArrayList<>());
        knowledgeSources.put("regulations", new ArrayList<>());
        
        // 构建查询关键词
        List<String> queries = buildHistoryAuditQueries();
        
        // 企业单位库检索（历史审计问题）
        if (StrUtil.isNotBlank(kbIds)) {
            Arrays.stream(kbIds.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .forEach(kbId -> knowledgeSources.get("enterprise")
                    .addAll(queryKnowledgeBase(kbId, queries, 150)));
        }
        
        // 审计报告库检索
        if (StrUtil.isNotBlank(libraryKbIds)) {
            Arrays.stream(libraryKbIds.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .forEach(libId -> {
                    knowledgeSources.get("auditReports")
                        .addAll(queryKnowledgeBase(libId, Arrays.asList("审计报告", "审计发现问题"), 100));
                    knowledgeSources.get("rectificationReports")
                        .addAll(queryKnowledgeBase(libId, Arrays.asList("整改报告", "整改情况", "整改措施"), 80));
                });
        }
        
        // 法律法规库检索（从项目库）
        if (StrUtil.isNotBlank(projectLibrary)) {
            knowledgeSources.get("regulations").addAll(
                queryKnowledgeBase(projectLibrary, 
                    Arrays.asList("审计制度", "整改机制", "责任追究"), 60));
        }
        
        // 智能去重和排序
        knowledgeSources.forEach((key, list) -> {
            List<String> processed = list.stream()
                    .distinct()
                    .sorted(this::historyAuditComparator)
                    .limit(getLimitBySourceType(key))
                    .collect(Collectors.toList());
            knowledgeSources.put(key, processed);
        });
        
        log.debug("历史审计问题知识检索完成 - 企业: {}条, 审计报告: {}条, 整改报告: {}条, 法规: {}条", 
                 knowledgeSources.get("enterprise").size(),
                 knowledgeSources.get("auditReports").size(),
                 knowledgeSources.get("rectificationReports").size(),
                 knowledgeSources.get("regulations").size());
        
        return knowledgeSources;
    }
    
    /**
     * 构建历史审计问题查询关键词
     */
    private List<String> buildHistoryAuditQueries() {
        return Arrays.asList(
            "审计发现问题 整改情况",
            "历史审计 遗留问题",
            "审计报告 整改报告",
            "问题整改 措施 效果",
            "审计年度 审计类型"
        );
    }
    
    /**
     * 构建完整的知识上下文
     */
    private String buildCompleteKnowledgeContext(Map<String, List<String>> knowledgeSources, 
                                                String history, String suggestion) {
        StringBuilder context = new StringBuilder();
        
        // 1. 审计内容11的要求
        context.append("## 审计内容11：历史审计问题整改\n");
        context.append("**审计重点：**\n");
        context.append("1. ").append(AuditContent11HistoryConstants.FOCUS_DESCRIPTIONS.get(AuditContent11HistoryConstants.FOCUS_SYSTEM_MECHANISM)).append("\n");
        context.append("2. ").append(AuditContent11HistoryConstants.FOCUS_DESCRIPTIONS.get(AuditContent11HistoryConstants.FOCUS_HISTORICAL_ISSUES)).append("\n");
        context.append("3. ").append(AuditContent11HistoryConstants.FOCUS_DESCRIPTIONS.get(AuditContent11HistoryConstants.FOCUS_RECTIFICATION_EFFECT)).append("\n");
        context.append("4. ").append(AuditContent11HistoryConstants.FOCUS_DESCRIPTIONS.get(AuditContent11HistoryConstants.FOCUS_SYSTEM_IMPROVEMENT)).append("\n");
        context.append("5. ").append(AuditContent11HistoryConstants.FOCUS_DESCRIPTIONS.get(AuditContent11HistoryConstants.FOCUS_SELF_RECTIFICATION)).append("\n\n");
        
        context.append("**审计方法及步骤：**\n");
        context.append("1. ").append(AuditContent11HistoryConstants.METHOD_DESCRIPTIONS.get(AuditContent11HistoryConstants.METHOD_REVIEW_REPORT)).append("\n");
        context.append("2. ").append(AuditContent11HistoryConstants.METHOD_DESCRIPTIONS.get(AuditContent11HistoryConstants.METHOD_REVIEW_RECTIFICATION)).append("\n");
        context.append("3. ").append(AuditContent11HistoryConstants.METHOD_DESCRIPTIONS.get(AuditContent11HistoryConstants.METHOD_VERIFY_RECTIFICATION)).append("\n");
        context.append("4. ").append(AuditContent11HistoryConstants.METHOD_DESCRIPTIONS.get(AuditContent11HistoryConstants.METHOD_INTERVIEW)).append("\n");
        context.append("5. ").append(AuditContent11HistoryConstants.METHOD_DESCRIPTIONS.get(AuditContent11HistoryConstants.METHOD_REVIEW_DOCS)).append("\n\n");
        
        // 2. 数据格式要求
        context.append("## 数据格式要求\n");
        context.append("需要生成历史审计问题整改表数据，尽可能生成多个年度、多种类型的审计问题，数量不限：\n\n");
        
        context.append("**表格字段说明：**\n");
        context.append("1. **审计年度**：审计报告所属年份，如：2023年\n");
        context.append("2. **审计类型**：内部审计、外部审计、专项审计、经济责任审计等\n");
        context.append("3. **审计发现的问题**：具体审计发现的问题描述，需详细说明\n");
        context.append("4. **整改要求**：对问题的整改要求，包括时间、内容等\n");
        context.append("5. **整改措施**：具体的整改措施和实施情况\n");
        context.append("6. **整改完成情况**：已完成、整改中、未整改、部分整改\n");
        context.append("7. **整改完成时间**：具体完成时间或计划完成时间\n");
        context.append("8. **整改责任人**：负责整改的责任人姓名和职务\n");
        context.append("9. **备注**：其他需要说明的情况\n");
        context.append("10. **工作底稿索引**：相关审计报告、整改报告等文件名称，必须是实际存在的完整文件名\n\n");
        
        context.append("**生成要求：**\n");
        context.append("1. 基于知识库内容，尽可能全面地生成历次审计发现的问题和整改情况\n");
        context.append("2. 每个问题应包含完整的审计年度、类型、问题描述、整改要求、措施、完成情况等\n");
        context.append("3. 重点关注整改措施的落实情况和实际效果\n");
        context.append("4. 工作底稿索引必须准确对应实际文件名称，确保能在文件夹中搜索到\n");
        context.append("5. 整改完成情况需根据实际情况判断，证据充分的才能判定为'已完成'\n");
        context.append("6. 对于历史遗留问题，需特别注明是否为非任期问题\n");
        context.append("7. 对于制度完善情况，需说明审计后是否建立了相关制度机制\n\n");
        
        // 3. 历史内容
        if (StrUtil.isNotBlank(history)) {
            context.append("## 历史生成内容\n");
            context.append("以下是之前生成的内容，请基于此进行优化：\n");
            context.append(history).append("\n\n");
        }
        
        // 4. 用户建议
        if (StrUtil.isNotBlank(suggestion)) {
            context.append("## 用户优化建议\n");
            context.append("请根据以下建议对生成内容进行调整：\n");
            context.append(suggestion).append("\n\n");
        }
        
        // 5. 企业单位知识（审计问题）
        if (!knowledgeSources.get("enterprise").isEmpty()) {
            context.append("## 企业单位审计问题知识\n");
            knowledgeSources.get("enterprise").forEach(knowledge -> 
                context.append(knowledge).append("\n"));
            context.append("\n");
        }
        
        // 6. 审计报告知识
        if (!knowledgeSources.get("auditReports").isEmpty()) {
            context.append("## 审计报告知识\n");
            knowledgeSources.get("auditReports").forEach(knowledge -> 
                context.append(knowledge).append("\n"));
            context.append("\n");
        }
        
        // 7. 整改报告知识
        if (!knowledgeSources.get("rectificationReports").isEmpty()) {
            context.append("## 整改报告知识\n");
            knowledgeSources.get("rectificationReports").forEach(knowledge -> 
                context.append(knowledge).append("\n"));
            context.append("\n");
        }
        
        // 8. 法规制度知识
        if (!knowledgeSources.get("regulations").isEmpty()) {
            context.append("## 审计整改相关法规制度\n");
            knowledgeSources.get("regulations").forEach(knowledge -> 
                context.append(knowledge).append("\n"));
        }
        
        return context.toString();
    }
    
    /**
     * 处理表格数据，确保格式正确
     */
    private JSONArray processTableData(JSONArray rawData) {
        JSONArray processedData = new JSONArray();
        
        for (int i = 0; i < rawData.size(); i++) {
            JSONObject item = rawData.getJSONObject(i);
            JSONObject processedItem = new JSONObject();
            
            // 设置序号
            processedItem.put("index", i + 1);
            
            // 复制所有字段
            processedItem.putAll(item);
            
            // 确保必填字段存在
            if (!processedItem.containsKey("auditYear")) {
                processedItem.put("auditYear", "2023年");
            }
            if (!processedItem.containsKey("auditType")) {
                processedItem.put("auditType", AuditContent11HistoryConstants.AUDIT_TYPE_INTERNAL);
            }
            if (!processedItem.containsKey("rectificationStatus")) {
                processedItem.put("rectificationStatus", AuditContent11HistoryConstants.STATUS_IN_PROGRESS);
            }
            
            processedData.add(processedItem);
        }
        
        return processedData;
    }
    
    /**
     * 历史审计问题相关性比较器
     */
    private int historyAuditComparator(String reg1, String reg2) {
        int score1 = calculateHistoryAuditRelevanceScore(reg1);
        int score2 = calculateHistoryAuditRelevanceScore(reg2);
        return Integer.compare(score2, score1);
    }
    
    /**
     * 计算历史审计问题相关性分数
     */
    private int calculateHistoryAuditRelevanceScore(String content) {
        return AuditContent11HistoryConstants.KEYWORD_WEIGHTS.entrySet().stream()
                .filter(entry -> content.contains(entry.getKey()))
                .mapToInt(Map.Entry::getValue)
                .sum();
    }
    
    private int getLimitBySourceType(String sourceType) {
        switch (sourceType) {
            case "enterprise": return 150;
            case "auditReports": return 100;
            case "rectificationReports": return 80;
            case "regulations": return 60;
            default: return 50;
        }
    }
}