package com.gxwebsoft.ai.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent5BudgetManageConstants;
import com.gxwebsoft.ai.service.AuditContent5BudgetManageService;
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 AuditContent5BudgetManageServiceImpl extends AbstractAuditContentService implements AuditContent5BudgetManageService {

    // 工作流配置
    private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-ZGILK3nfQ9A0jHot1r4Tta0r";
    
    @Override
    public JSONObject generateBudgetManageTableData(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("未传入审计内容6大数据，无法生成预算管理审计表");
                result.put("success", false);
                result.put("error", "需要审计内容6数据作为生成依据");
                return result;
            }
        	
            // 1. 检索相关知识
            Map<String, List<String>> knowledgeSources = retrieveKnowledgeForBudgetManagement(
                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_manage_audit");
            
        } catch (Exception e) {
            log.error("生成预算管理审计表失败", e);
            return buildErrorResponse("生成预算管理审计表失败: " + e.getMessage());
        }
    }

    /**
     * 检索预算管理相关知识
     */
    private Map<String, List<String>> retrieveKnowledgeForBudgetManagement(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 = buildBudgetManagementQueries();
        
        // 企业单位库检索 - 增加查询深度
        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], buildFinancialQueries(), 120));
        }
        
        // 智能去重和排序
        knowledgeSources.forEach((key, list) -> {
            List<String> processed = list.stream()
                    .map(String::trim)  // 去除首尾空格
                    .filter(str -> !StrUtil.isBlank(str))  // 过滤空字符串
                    .distinct()
                    .sorted(this::budgetManagementComparator)
                    .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> buildBudgetManagementQueries() {
        return Arrays.asList(
            "部门预算 预算编制 预算报表",
            "预算调整 追加预算 预算调剂",
            "预算执行 预算决算 决算报表",
            "指标来源 指标运用 指标结余",
            "财政拨款 资金拨付 经费拨款",
            "工资统发 人员经费 工资发放",
            "政府采购 采购预算 采购资金",
            "财政管理专户 专户管理 资金专户",
            "项目预算 项目申报 项目资金",
            "预算科目 科目设置 会计科目",
            "上年结余 结余资金 结转资金",
            "年初预算 年度预算 预算安排",
            "追加预算 预算追加 调整预算",
            "预算审批 审批手续 审批流程",
            "预算下达 预算批复 批复文件",
            "会计处理 账务处理 财务处理",
            "预算调剂 科目调剂 资金调剂",
            "经营收支 经营预算 企业预算",
            "可行性研究 项目评审 评审报告",
            "执行单位 实施单位 承办单位"
        );
    }
    
    /**
     * 构建财务相关查询词
     */
    private List<String> buildFinancialQueries() {
        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(AuditContent5BudgetManageConstants.CATEGORY_BUDGET_MANAGEMENT).append("\n");
        context.append("审计描述：检查预算编制的完整准确、预算调整审批的合规，以及预算支出的真实合法合规情况\n\n");
        
        // 2. 审计框架（审计规则）
        context.append("## 审计框架（审计规则）\n");
        context.append("以下审计框架定义了审计范围和要点，请基于此框架开展工作：\n");
        context.append(AuditContent5BudgetManageConstants.AUDIT_FRAMEWORK).append("\n\n");
        
        // 3. 审计目标
        context.append("## 审计目标\n");
        context.append(AuditContent5BudgetManageConstants.AUDIT_OBJECTIVE).append("\n\n");
        
        // 4. 审计工作原则
        context.append("## 审计工作原则\n");
        context.append(AuditContent5BudgetManageConstants.AUDIT_PRINCIPLES).append("\n\n");
        
        // 4.5. 国有资产的管理情况、政府采购执行情况，审计内容6数据（作为上下文）
        if (StrUtil.isNotBlank(data)) {
            context.append("## 国有资产的管理情况、政府采购执行情况，审计内容6分析数据（作为参考上下文）\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(AuditContent5BudgetManageConstants.AUDIT_KEY_POINTS).append("\n\n");
        
        // 8. 数据格式要求
        context.append("## 数据格式要求\n");
        context.append("请生成JSON数组格式的审计表数据，每个审计条目包含以下字段：\n");
        context.append(AuditContent5BudgetManageConstants.OUTPUT_FORMAT).append("\n\n");
        
        // 9. 审计证据要求
        context.append("## 审计证据要求\n");
        context.append(AuditContent5BudgetManageConstants.AUDIT_EVIDENCE_REQUIREMENTS).append("\n\n");
        
        // 11. 预算科目参考
        context.append("## 预算科目参考（常见类型）\n");
        AuditContent5BudgetManageConstants.BUDGET_SUBJECT_TYPES.forEach(subject -> 
            context.append("• ").append(subject).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\n");
        context.append("8. 除了本次说明中提供的数据知识等依据，不能从其他地方读取数据，不能凭空捏造数据\n");
        
        log.debug("预算管理审计知识上下文长度: {} 字符", context.length());
        
        return context.toString();
    }

    /**
     * 预算管理审计相关性比较器
     */
    private int budgetManagementComparator(String reg1, String reg2) {
        int score1 = calculateBudgetManagementRelevanceScore(reg1);
        int score2 = calculateBudgetManagementRelevanceScore(reg2);
        return Integer.compare(score2, score1); // 降序排序
    }

    /**
     * 计算预算管理审计相关性分数
     */
    private int calculateBudgetManagementRelevanceScore(String content) {
        return AuditContent5BudgetManageConstants.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;
        }
    }
    
}