package com.gxwebsoft.ai.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent5BudgetExecutionConstants;
import com.gxwebsoft.ai.service.AuditContent5BudgetExecutionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;

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

@Slf4j
@Service
public class AuditContent5BudgetExecutionServiceImpl extends AbstractAuditContentService implements AuditContent5BudgetExecutionService {

    // 工作流配置
    private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-40NwSJCFSFKkOwRdGe8nqVsA";
    
    @Override
    public JSONObject generateBudgetExecutionTableData(String kbIds, String libraryKbIds, String projectLibrary,
                                                  String userName, String history, String suggestion, Object data) {
        log.info("开始生成预算执行情况审计表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}", 
                userName, kbIds, libraryKbIds, projectLibrary);
        
        long startTime = System.currentTimeMillis();
        
        try {
            if (ObjectUtil.isEmpty(data)) {
            	JSONObject result = new JSONObject();
                log.warn("未传入预算管理审计数据，无法生成预算执行情况审计表");
                result.put("success", false);
                result.put("error", "需要预算管理审计数据作为生成依据");
                return result;
            }
            
            // 1. 检索相关知识
            Map<String, List<String>> knowledgeSources = retrieveKnowledgeForBudgetExecution(
                kbIds, libraryKbIds, projectLibrary
            );
            
            // 2. 构建完整的知识上下文（包含预算管理数据）
            String knowledgeContext = buildCompleteKnowledgeContext(knowledgeSources, history, suggestion, data.toString());
            
            // 3. 调用工作流生成数据
            JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
            JSONArray auditData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "预算执行情况审计");
            
            log.info("预算执行情况审计表生成成功 - 记录数: {}, 处理时间: {}ms", 
                    auditData.size(), (System.currentTimeMillis() - startTime));
            
            return buildSuccessResponse(auditData, startTime, "budget_execution_audit");
            
        } catch (Exception e) {
            log.error("生成预算执行情况审计表失败", e);
            return buildErrorResponse("生成预算执行情况审计表失败: " + e.getMessage());
        }
    }

    /**
     * 检索预算执行情况相关知识
     */
    private Map<String, List<String>> retrieveKnowledgeForBudgetExecution(String kbIds, String libraryKbIds, String projectLibrary) {
        Map<String, List<String>> knowledgeSources = new HashMap<>();
        knowledgeSources.put("enterprise", new ArrayList<>());
        knowledgeSources.put("regulation", new ArrayList<>());
        knowledgeSources.put("auditCase", new ArrayList<>());
        knowledgeSources.put("financial", new ArrayList<>());
        
        // 构建查询词 - 具体化，提高识别率
        List<String> queries = buildBudgetExecutionQueries();
        
        // 企业单位库检索 - 增加查询深度
        if (StrUtil.isNotBlank(kbIds)) {
            Arrays.stream(kbIds.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .forEach(kbId -> knowledgeSources.get("enterprise")
                    .addAll(queryKnowledgeBase(kbId, queries, 100)));
        }
        
        // 公共法律法规库检索
        if (StrUtil.isNotBlank(libraryKbIds)) {
            Arrays.stream(libraryKbIds.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .forEach(libId -> knowledgeSources.get("regulation")
                    .addAll(queryKnowledgeBase(libId, queries, 100)));
        }
        
        // 审计案例库检索
        if (StrUtil.isNotBlank(projectLibrary)) {
            knowledgeSources.get("auditCase").addAll(
                queryKnowledgeBase(projectLibrary, queries, 80));
        }
        
        // 财务知识库检索（预算执行相关）
        if (StrUtil.isNotBlank(kbIds)) {
            knowledgeSources.get("financial").addAll(
                queryKnowledgeBase(kbIds.split(",")[0], buildFinancialExecutionQueries(), 120));
        }
        
        // 智能去重和排序
        knowledgeSources.forEach((key, list) -> {
            List<String> processed = list.stream()
                    .map(String::trim)  // 去除首尾空格
                    .filter(str -> !StrUtil.isBlank(str))  // 过滤空字符串
                    .distinct()
                    .sorted(this::budgetExecutionComparator)
                    .limit(getLimitBySourceType(key))
                    .collect(Collectors.toList());
            knowledgeSources.put(key, processed);
        });
        
        log.debug("预算执行情况知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条, 财务: {}条", 
                 knowledgeSources.get("enterprise").size(),
                 knowledgeSources.get("regulation").size(),
                 knowledgeSources.get("auditCase").size(),
                 knowledgeSources.get("financial").size());
        
        return knowledgeSources;
    }
    
    /**
     * 构建预算执行情况查询词 - 具体化
     */
    private List<String> buildBudgetExecutionQueries() {
        return Arrays.asList(
            "预算执行率 执行进度 进度报表",
            "实际拨款 拨款到位 资金拨付",
            "预算调整 追加预算 调整审批",
            "预算执行分析 执行情况分析 执行报告",
            "项目执行 项目实施 项目进度",
            "资金使用 资金拨付 资金到位",
            "指标结余 预算结余 结转结余",
            "预算执行偏差 执行差异 差异分析",
            "月度执行 季度执行 年度执行",
            "预算执行监督 执行检查 执行审计",
            "预算执行效果 执行效益 执行成果",
            "预算执行合规 执行规范 执行合法",
            "预算执行台账 执行记录 执行日志",
            "拨款凭证 付款凭证 资金支付",
            "预算执行预警 执行风险 风险预警",
            "预算执行考核 执行评价 绩效考核",
            "预算执行整改 执行问题 整改措施",
            "预算执行信息化 执行系统 电子台账",
            "预算执行报告 执行汇报 执行总结",
            "预算执行公开 执行透明 信息公开"
        );
    }
    
    /**
     * 构建财务执行相关查询词
     */
    private List<String> buildFinancialExecutionQueries() {
        return Arrays.asList(
            "财务报表 财务报告 会计报表",
            "资金流水 银行流水 现金流水",
            "支付凭证 付款记录 银行回单",
            "预算执行表 执行进度表 执行明细",
            "决算报表 决算报告 决算分析",
            "费用报销 报销凭证 报销记录",
            "项目支出 项目付款 项目结算",
            "资金监管 资金监控 资金跟踪",
            "财务分析 执行分析 差异分析",
            "审计报告 审计意见 审计整改"
        );
    }

    /**
     * 构建完整的知识上下文
     */
    private String buildCompleteKnowledgeContext(Map<String, List<String>> knowledgeSources, 
                                               String history, String suggestion, String data) {
        StringBuilder context = new StringBuilder();
        
        // 1. 核心审计任务
        context.append("## 核心审计任务\n");
        context.append("审计分类：").append(AuditContent5BudgetExecutionConstants.CATEGORY_BUDGET_EXECUTION).append("\n");
        context.append("审计描述：检查预算执行的进度、合规性、效果，分析预算执行偏差原因，评估预算执行效益\n\n");
        
        // 2. 审计框架（审计规则）
        context.append("## 审计框架（审计规则）\n");
        context.append("以下审计框架定义了审计范围和要点，请基于此框架开展工作：\n");
        context.append(AuditContent5BudgetExecutionConstants.AUDIT_FRAMEWORK).append("\n\n");
        
        // 3. 审计目标
        context.append("## 审计目标\n");
        context.append(AuditContent5BudgetExecutionConstants.AUDIT_OBJECTIVE).append("\n\n");
        
        // 4. 审计工作原则
        context.append("## 审计工作原则\n");
        context.append(AuditContent5BudgetExecutionConstants.AUDIT_PRINCIPLES).append("\n\n");
        
        // 4.5. 预算管理审计数据（作为上下文）
        if (ObjectUtil.isNotEmpty(data)) {
            context.append("## 预算管理审计数据（作为参考上下文）\n");
            context.append(data).append("\n\n");
        }
        
        // 5. 企业单位知识（主要考察内容）
        if (!knowledgeSources.get("enterprise").isEmpty()) {
            context.append("## 企业单位知识（具体考察内容）\n");
            context.append("以下是企业单位的实际预算执行资料，请基于审计框架，结合这些具体内容生成审计记录：\n\n");
            knowledgeSources.get("enterprise").forEach(knowledge -> 
                context.append("• ").append(knowledge).append("\n"));
            context.append("\n");
        }
        
        // 6. 财务知识（预算执行相关）
        if (!knowledgeSources.get("financial").isEmpty()) {
            context.append("## 财务知识（预算执行相关）\n");
            context.append("以下是财务相关预算执行资料，包括预算执行进度、资金拨付等信息：\n\n");
            knowledgeSources.get("financial").forEach(knowledge -> 
                context.append("• ").append(knowledge).append("\n"));
            context.append("\n");
        }
        
        // 7. 审计要点提示
        context.append("## 审计要点提示\n");
        context.append(AuditContent5BudgetExecutionConstants.AUDIT_KEY_POINTS).append("\n\n");
        
        // 8. 数据格式要求
        context.append("## 数据格式要求\n");
        context.append("请生成JSON数组格式的审计表数据，每个审计条目包含以下字段：\n");
        context.append(AuditContent5BudgetExecutionConstants.OUTPUT_FORMAT).append("\n\n");
        
        // 9. 审计证据要求
        context.append("## 审计证据要求\n");
        context.append(AuditContent5BudgetExecutionConstants.AUDIT_EVIDENCE_REQUIREMENTS).append("\n\n");
        
        // 11. 审计项目参考
        context.append("## 审计项目参考（常见类型）\n");
        AuditContent5BudgetExecutionConstants.AUDIT_PROJECT_TYPES.forEach(project -> 
            context.append("• ").append(project).append("\n"));
        context.append("\n");
        
        // 12. 法规和案例参考
        if (!knowledgeSources.get("regulation").isEmpty()) {
            context.append("## 法律法规参考\n");
            knowledgeSources.get("regulation").forEach(knowledge -> 
                context.append("• ").append(knowledge).append("\n"));
            context.append("\n");
        }
        
        if (!knowledgeSources.get("auditCase").isEmpty()) {
            context.append("## 审计案例参考\n");
            knowledgeSources.get("auditCase").forEach(knowledge -> 
                context.append("• ").append(knowledge).append("\n"));
            context.append("\n");
        }
        
        // 13. 历史内容（如果有）
        if (StrUtil.isNotBlank(history)) {
            context.append("## 历史生成内容\n");
            context.append(history).append("\n\n");
        }
        
        // 14. 用户建议（如果有）
        if (StrUtil.isNotBlank(suggestion)) {
            context.append("## 用户建议\n");
            context.append(suggestion).append("\n\n");
        }

        // 10. 特别提醒 - 强调全面识别
        context.append("## 特别提醒\n");
        context.append("1. 必须全面分析预算执行全过程，包括执行进度、执行效果、执行合规性\n");
        context.append("2. 重点关注预算执行率、资金到位率、预算执行偏差等关键指标\n");
        context.append("3. 金额字段应填写具体数值，如\"1,000,000.00\"，不能填写简单的\"有\"或\"无\"\n");
//      context.append("4. workPaperIndex必须填写实际存在的完整文件FileId\n");
        context.append("4. workPaperIndex必须填写实际存在的完整文件名||FileUrl\n");
        context.append("5. 对于无数据的字段，可填写\"-\"或留空，但不能填写\"无\"\n");
        context.append("6. 基于预算执行全流程进行审计分析，包括月度、季度、年度执行情况\n");
        context.append("7. 重点关注预算执行偏差原因分析和整改措施\n");
        context.append("8. 尽可能多地生成审计记录，覆盖所有预算项目和执行环节\n\n");
        context.append("9. 除了本次说明中提供的数据知识等依据，不能从其他地方读取数据，不能凭空捏造数据\n");
        
        log.debug("预算执行情况审计知识上下文长度: {} 字符", context.length());
        
        return context.toString();
    }

    /**
     * 预算执行情况审计相关性比较器
     */
    private int budgetExecutionComparator(String reg1, String reg2) {
        int score1 = calculateBudgetExecutionRelevanceScore(reg1);
        int score2 = calculateBudgetExecutionRelevanceScore(reg2);
        return Integer.compare(score2, score1); // 降序排序
    }

    /**
     * 计算预算执行情况审计相关性分数
     */
    private int calculateBudgetExecutionRelevanceScore(String content) {
        return AuditContent5BudgetExecutionConstants.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 250;
            case "financial": return 150;
            case "regulation": return 60;
            case "auditCase": return 40;
            default: return 50;
        }
    }
    
}