package com.gxwebsoft.ai.service.impl;

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

import cn.hutool.core.util.StrUtil;

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

@Slf4j
@Service
public class AuditContent1ExpenseServiceImpl extends AbstractAuditContentService implements AuditContent1ExpenseService {

    // 工作流配置
    private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-xwWxGF6hERgdeKB5OPpj9Tq8";

    @Override
    public JSONObject generateExpenseTableData(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 = retrieveKnowledgeForExpense(kbIds, libraryKbIds, projectLibrary);
            
            // 2. 构建完整的知识上下文
            String knowledgeContext = buildCompleteKnowledgeContext(knowledgeSources, history, suggestion);
            
            // 3. 调用工作流生成数据
            JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
            JSONArray expenseData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "支出情况表");
            
            // 4. 按 expenseType 和 year 排序
            if (expenseData != null && !expenseData.isEmpty()) {
                expenseData.sort((o1, o2) -> {
                    JSONObject obj1 = (JSONObject) o1;
                    JSONObject obj2 = (JSONObject) o2;
                    // 先按 expenseType 排序
                    int typeCompare = obj1.getString("expenseType").compareTo(obj2.getString("expenseType"));
                    if (typeCompare != 0) {
                        return typeCompare;
                    }
                    // 再按 year 排序
                    return obj1.getString("year").compareTo(obj2.getString("year"));
                });
            }
            
            // 5. 不进行数据验证和补充，直接返回大模型输出
            log.info("支出情况表生成成功 - 记录数: {}, 处理时间: {}ms", expenseData.size(), (System.currentTimeMillis() - startTime));
            return buildSuccessResponse(expenseData, startTime, "expense_audit");
        } catch (Exception e) {
            log.error("生成支出情况表失败", e);
            return buildErrorResponse("生成支出情况表失败: " + e.getMessage());
        }
    }

    /**
     * 检索支出情况表相关知识 - 优化查询策略，排除工程类报表
     */
    private Map<String, List<String>> retrieveKnowledgeForExpense(String kbIds, String libraryKbIds, String projectLibrary) {
        Map<String, List<String>> knowledgeSources = new HashMap<>();
        knowledgeSources.put("financial", new ArrayList<>());
        knowledgeSources.put("regulation", new ArrayList<>());
        knowledgeSources.put("auditCase", new ArrayList<>());
        
        // 构建更精确的查询词，专门针对四类支出
        List<String> queries = buildPreciseExpenseQueries();
        
        // 财务数据库检索
        if (StrUtil.isNotBlank(kbIds)) {
            Arrays.stream(kbIds.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .forEach(kbId -> {
                    List<String> financialKnowledge = queryKnowledgeBase(kbId, queries, 200);
                    
                    // 过滤掉工程类报表内容
                    financialKnowledge = filterOutEngineeringReports(financialKnowledge);
                    
                    knowledgeSources.get("financial").addAll(financialKnowledge);
                    log.debug("财务知识库 {} 检索到 {} 条相关知识", kbId, financialKnowledge.size());
                });
        }
        
        // 公共法律法规库检索
        if (StrUtil.isNotBlank(libraryKbIds)) {
            Arrays.stream(libraryKbIds.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .forEach(libId -> {
                    List<String> regulationKnowledge = queryKnowledgeBase(libId, queries, 50);
                    knowledgeSources.get("regulation").addAll(regulationKnowledge);
                });
        }
        
        // 审计案例库检索
        if (StrUtil.isNotBlank(projectLibrary)) {
            List<String> auditCaseKnowledge = queryKnowledgeBase(projectLibrary, queries, 30);
            knowledgeSources.get("auditCase").addAll(auditCaseKnowledge);
        }
        
        // 智能去重、排序和过滤
        knowledgeSources.forEach((key, list) -> {
            List<String> processed = list.stream()
                    .distinct()
                    .filter(this::isRelevantExpenseContent)  // 过滤相关性
                    .sorted(this::expenseComparator)
                    .limit(getLimitBySourceType(key))
                    .collect(Collectors.toList());
            knowledgeSources.put(key, processed);
        });
        
        log.info("支出情况表知识检索完成 - 财务: {}条, 法规: {}条, 案例: {}条", 
                 knowledgeSources.get("financial").size(),
                 knowledgeSources.get("regulation").size(),
                 knowledgeSources.get("auditCase").size());
        
        return knowledgeSources;
    }

    /**
     * 构建精确的支出情况表查询词
     */
    private List<String> buildPreciseExpenseQueries() {
        return Arrays.asList(
            // 直接针对四类支出的查询
            "公务接待 接待费 招待费 餐饮费 公务用餐",
            "出国 出境 国际差旅 境外考察 出国费用",
            "公车运行维护 车辆费 汽车费 交通费 公务用车",
            "会议培训费 会议费 培训费 会务费 培训支出",
            
            // 财务文档查询（排除工程类）
            "决算报表 公务接待 出国 公车 会议培训",
            "预算报表 三公经费 支出明细",
            "部门决算 公务支出 费用统计",
            "部门预算 经费预算 支出预算",
            
            // 通用年度查询，不指定具体年份，让知识库返回所有年份数据
            "年度 公务接待 出国 公车 会议培训",
            "决算 公务接待 出国 公车 会议培训",
            "预算 公务接待 出国 公车 会议培训",
            "三公经费 支出 决算 预算"
        );
    }

    /**
     * 过滤掉工程类报表内容
     */
    private List<String> filterOutEngineeringReports(List<String> knowledgeList) {
        return knowledgeList.stream()
                .filter(content -> {
                    // 检查是否包含工程类关键词
                    for (String excludeKeyword : AuditContent1ExpenseConstants.ENGINEERING_EXCLUDE_KEYWORDS) {
                        if (content.contains(excludeKeyword)) {
                            log.debug("过滤工程类内容: {}", content.substring(0, Math.min(50, content.length())));
                            return false;
                        }
                    }
                    return true;
                })
                .collect(Collectors.toList());
    }

    /**
     * 检查内容是否与支出相关
     */
    private boolean isRelevantExpenseContent(String content) {
        String lowerContent = content.toLowerCase();
        
        // 必须包含至少一个支出类型关键词
        boolean hasExpenseType = lowerContent.contains("公务接待") || 
                                lowerContent.contains("接待费") ||
                                lowerContent.contains("出国") || 
                                lowerContent.contains("出境") ||
                                lowerContent.contains("公车") || 
                                lowerContent.contains("车辆费") ||
                                lowerContent.contains("会议") || 
                                lowerContent.contains("培训") ||
                                lowerContent.contains("三公经费");
        
        // 排除工程类内容
        boolean isEngineering = false;
        for (String excludeKeyword : AuditContent1ExpenseConstants.ENGINEERING_EXCLUDE_KEYWORDS) {
            if (content.contains(excludeKeyword)) {
                isEngineering = true;
                break;
            }
        }
        
        return hasExpenseType && !isEngineering;
    }

    /**
     * 构建完整的知识上下文 - 简化版本，只传递知识内容
     */
    private String buildCompleteKnowledgeContext(Map<String, List<String>> knowledgeSources, String history, String suggestion) {
        StringBuilder context = new StringBuilder();
        
        // 1. 审计关注要点（简化版）
        context.append("## 审计关注要点\n");
        context.append("请基于以下知识生成完整的公务接待/出国/公车运行维护/会议培训费等支出情况表数据。\n");
        context.append("重点关注以下审计要点：\n");
        context.append("1. 检查公务接待、出国、公车、会议培训四类支出的预算执行情况\n");
        context.append("2. 对比年初预算数和决算报表数，分析增减情况\n");
        context.append("3. 关注是否存在未经预算批准变相公款消费的情况\n");
        context.append("4. 检查报销手续是否完善，是否存在超支使用\n\n");
        
        // 3. 历史内容
        if (StrUtil.isNotBlank(history)) {
            context.append("## 历史生成内容参考\n");
            context.append(history).append("\n\n");
        }
        
        // 4. 用户建议
        if (StrUtil.isNotBlank(suggestion)) {
            context.append("## 用户优化建议\n");
            context.append(suggestion).append("\n\n");
        }
        
        // 5. 财务知识（核心内容）
        if (!knowledgeSources.get("financial").isEmpty()) {
            context.append("## 财务知识库内容\n");
            context.append("以下是财务相关的报表和文件信息，请仔细分析并提取所有支出数据：\n\n");
            knowledgeSources.get("financial").forEach(knowledge -> 
                context.append(knowledge).append("\n"));
            context.append("\n");
        }
        
        // 6. 法律法规知识
        if (!knowledgeSources.get("regulation").isEmpty()) {
            context.append("## 法律法规参考\n");
            knowledgeSources.get("regulation").forEach(knowledge -> 
                context.append(knowledge).append("\n"));
            context.append("\n");
        }
        
        // 7. 审计案例知识
        if (!knowledgeSources.get("auditCase").isEmpty()) {
            context.append("## 审计案例参考\n");
            knowledgeSources.get("auditCase").forEach(knowledge -> 
                context.append(knowledge).append("\n"));
        }

        // 2. 特别提醒
        context.append("## 特别提醒\n");
        context.append("1. 必须准确识别支出类型：只提取\"公务接待\"、\"出国\"、\"公车运行维护\"、\"会议培训费\"四类支出\n");
        context.append("2. 不要将《工程造价和概（预）算执行情况表》等工程类报表误识别为\"三公经费\"报表\n");
//        context.append("3. 工作底稿索引必须使用实际存在的完整文件名称作为FileId\n\n");
        context.append("3. 工作底稿索引必须使用实际存在的完整文件名||FileUrl\n\n");
        context.append("4. 除了本次说明中提供的数据知识等依据，不能从其他地方读取数据，不能凭空捏造数据\n");
        
        log.debug("构建的知识上下文长度: {}", context.length());
        return context.toString();
    }

    /**
     * 支出情况表相关性比较器
     */
    private int expenseComparator(String content1, String content2) {
        int score1 = calculateExpenseRelevanceScore(content1);
        int score2 = calculateExpenseRelevanceScore(content2);
        return Integer.compare(score2, score1);
    }

    /**
     * 计算支出情况表相关性分数
     */
    private int calculateExpenseRelevanceScore(String content) {
        return AuditContent1ExpenseConstants.KEYWORD_WEIGHTS.entrySet().stream()
                .filter(entry -> content.contains(entry.getKey()))
                .mapToInt(Map.Entry::getValue)
                .sum();
    }

    private int getLimitBySourceType(String sourceType) {
        switch (sourceType) {
            case "financial": return 100;  // 减少数量，提高质量
            case "regulation": return 50;
            case "auditCase": return 30;
            default: return 50;
        }
    }
}