package com.gxwebsoft.ai.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent1EightRegConstants;
import com.gxwebsoft.ai.service.AuditContent1EightRegService;
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.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AuditContent1EightRegServiceImpl extends AbstractAuditContentService implements AuditContent1EightRegService {

    // 八项规定工作流配置
    private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-hwUG7mEAZtN0jeZkebtIJYrU";
    
    // 八项规定分类定义 - 按照要求的顺序
    private static final List<String> CATEGORY_ORDER = Arrays.asList(
        AuditContent1EightRegConstants.CATEGORY_RESEARCH,
        AuditContent1EightRegConstants.CATEGORY_MEETINGS,
        AuditContent1EightRegConstants.CATEGORY_DOCUMENTS,
        AuditContent1EightRegConstants.CATEGORY_VISITS,
        AuditContent1EightRegConstants.CATEGORY_GUARD_WORK,
        AuditContent1EightRegConstants.CATEGORY_NEWS_REPORT,
        AuditContent1EightRegConstants.CATEGORY_PUBLICATIONS,
        AuditContent1EightRegConstants.CATEGORY_ECONOMY
    );

    // 八项规定标题映射
    private static final Map<String, String> POLICY_TITLE_MAP = new HashMap<>();
    static {
        POLICY_TITLE_MAP.put(AuditContent1EightRegConstants.CATEGORY_RESEARCH, "一");
        POLICY_TITLE_MAP.put(AuditContent1EightRegConstants.CATEGORY_MEETINGS, "二");
        POLICY_TITLE_MAP.put(AuditContent1EightRegConstants.CATEGORY_DOCUMENTS, "三");
        POLICY_TITLE_MAP.put(AuditContent1EightRegConstants.CATEGORY_VISITS, "四");
        POLICY_TITLE_MAP.put(AuditContent1EightRegConstants.CATEGORY_GUARD_WORK, "五");
        POLICY_TITLE_MAP.put(AuditContent1EightRegConstants.CATEGORY_NEWS_REPORT, "六");
        POLICY_TITLE_MAP.put(AuditContent1EightRegConstants.CATEGORY_PUBLICATIONS, "七");
        POLICY_TITLE_MAP.put(AuditContent1EightRegConstants.CATEGORY_ECONOMY, "八");
    }

    @Override
    public JSONObject generateEightRegTableData(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 {
            // 异步并行处理每个分类
            Map<String, CompletableFuture<JSONArray>> futures = processCategoriesAsync(
                CATEGORY_ORDER, 
                category -> generateCategoryDataAsync(category, kbIds, libraryKbIds, projectLibrary, userName, history, suggestion)
            );
            
            // 等待所有异步任务完成
            CompletableFuture.allOf(futures.values().toArray(new CompletableFuture[0])).join();
            
            // 合并所有分类的结果，并按照八项规定顺序排序
            JSONArray allData = mergeAndSortCategoryResults(CATEGORY_ORDER, futures);
            
            log.info("八项规定对比分析表生成成功 - 记录数: {}, 处理时间: {}ms", allData.size(), (System.currentTimeMillis() - startTime));
            
            return buildSuccessResponse(allData, startTime, "eight_regulation_audit");
            
        } catch (Exception e) {
            log.error("生成八项规定对比分析表失败", e);
            return buildErrorResponse("生成八项规定对比分析表失败: " + e.getMessage());
        }
    }

    /**
     * 合并并按照八项规定顺序排序分类结果
     */
    private JSONArray mergeAndSortCategoryResults(List<String> categoryOrder, Map<String, CompletableFuture<JSONArray>> futures) {
        JSONArray allData = new JSONArray();
        
        // 按照八项规定顺序遍历每个分类
        for (String category : categoryOrder) {
            CompletableFuture<JSONArray> future = futures.get(category);
            if (future != null) {
                try {
                    JSONArray categoryData = future.get();
                    if (categoryData != null) {
                        // 为当前分类的数据设置排序标识
                        for (Object obj : categoryData) {
                            if (obj instanceof JSONObject) {
                                JSONObject item = (JSONObject) obj;
                                // 设置排序标识，用于前端展示
                                item.put("categoryOrder", POLICY_TITLE_MAP.get(category));
                                item.put("categoryName", category);
                            }
                        }
                        allData.addAll(categoryData);
                    }
                } catch (Exception e) {
                    log.error("获取分类 {} 数据失败", category, e);
                }
            }
        }
        
        return allData;
    }

    /**
     * 异步生成单个分类的数据
     */
    @Async
    public CompletableFuture<JSONArray> generateCategoryDataAsync(String category, String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion) {
        return CompletableFuture.supplyAsync(() -> {
            try {
                log.info("开始生成八项规定分类 {} 的数据", category);
                
                // 1. 为当前分类召回相关知识
                Map<String, List<String>> knowledgeSources = retrieveKnowledgeForCategory(
                    category, kbIds, libraryKbIds, projectLibrary
                );
                
                // 2. 构建完整的知识上下文（包含固定内容和动态内容）
                String knowledgeContext = buildCompleteKnowledgeContext(
                    category, knowledgeSources, history, suggestion
                );
                
                // 3. 调用工作流生成数据
                JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
                JSONArray categoryData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "八项规定-" + category);
                
                log.info("八项规定分类 {} 数据生成完成，生成 {} 条记录", category, categoryData.size());
                return categoryData;
                
            } catch (Exception e) {
                log.error("生成八项规定分类 {} 数据失败", category, e);
                return new JSONArray();
            }
        });
    }

    /**
     * 为单个分类检索相关知识
     */
    private Map<String, List<String>> retrieveKnowledgeForCategory(String category, 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<>());
        
        // 构建当前分类的查询词
        List<String> categoryQueries = buildCategoryQueries(category);
        
        // 企业单位库检索
        if (StrUtil.isNotBlank(kbIds)) {
            Arrays.stream(kbIds.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .forEach(kbId -> knowledgeSources.get("enterprise")
                    .addAll(queryKnowledgeBase(kbId, categoryQueries, 100)));
        }
        
        // 公共法律法规库检索
        if (StrUtil.isNotBlank(libraryKbIds)) {
            Arrays.stream(libraryKbIds.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .forEach(libId -> knowledgeSources.get("regulation")
                    .addAll(queryKnowledgeBase(libId, categoryQueries, 80)));
        }
        
        // 审计案例库检索
        if (StrUtil.isNotBlank(projectLibrary)) {
            knowledgeSources.get("auditCase").addAll(
                queryKnowledgeBase(projectLibrary, categoryQueries, 60));
        }
        
        // 智能去重和排序
        knowledgeSources.forEach((key, list) -> {
            List<String> processed = list.stream()
                    .distinct()
                    .sorted(this::eightRegComparator)
                    .limit(getLimitBySourceType(key))
                    .collect(Collectors.toList());
            knowledgeSources.put(key, processed);
        });
        
        log.debug("八项规定分类 {} 知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条", 
                 category, 
                 knowledgeSources.get("enterprise").size(),
                 knowledgeSources.get("regulation").size(),
                 knowledgeSources.get("auditCase").size());
        
        return knowledgeSources;
    }

    /**
     * 构建分类特定的查询词
     */
    private List<String> buildCategoryQueries(String category) {
        switch (category) {
            case AuditContent1EightRegConstants.CATEGORY_RESEARCH:
                return Arrays.asList("调查研究 基层调研 调研陪同", "调研接待 调研规定");
            case AuditContent1EightRegConstants.CATEGORY_MEETINGS:
                return Arrays.asList("会议活动 会议费 会议规模", "会议审批 会议时长");
            case AuditContent1EightRegConstants.CATEGORY_DOCUMENTS:
                return Arrays.asList("文件简报 文件数量 文风", "简报精简 文件管理");
            case AuditContent1EightRegConstants.CATEGORY_VISITS:
                return Arrays.asList("出访活动 因公出国 出访经费", "出访审批 出访陪同");
            case AuditContent1EightRegConstants.CATEGORY_GUARD_WORK:
                return Arrays.asList("警卫工作 交通管制 封路", "安保工作 警卫规定");
            case AuditContent1EightRegConstants.CATEGORY_NEWS_REPORT:
                return Arrays.asList("新闻报道 新闻稿 宣传报道", "媒体采访 新闻审批");
            case AuditContent1EightRegConstants.CATEGORY_PUBLICATIONS:
                return Arrays.asList("文稿发表 出版著作 题词题字", "发表文章 出版审批");
            case AuditContent1EightRegConstants.CATEGORY_ECONOMY:
                return Arrays.asList("勤俭节约 三公经费 公务接待", "差旅费 会议费 培训费");
            default:
                return Arrays.asList(category + " 八项规定");
        }
    }

    /**
     * 构建完整的知识上下文 - 包含固定内容和动态内容
     */
    private String buildCompleteKnowledgeContext(String category, Map<String, List<String>> knowledgeSources, String history, String suggestion) {
        StringBuilder context = new StringBuilder();
        
        // 1. 八项规定对比分析要求
        context.append("## 八项规定对比分析要求 - ").append(category).append("\n");
        context.append("请基于以下知识生成").append(category).append("相关的八项规定对比分析表数据：\n\n");
        context.append("1. 仅关注与八项规定直接相关的制度内容，过滤不相关制度\n");
        context.append("2. 对比分析中共中央八项规定与公司制度的差异\n");
//        context.append("3. 重点关注调查研究、会议活动、文件简报、出访活动、警卫工作、新闻报道、文稿发表、勤俭节约等八个方面\n");
        context.append("3. 重点关注").append(category).append("方面\n");
        context.append("4. 识别制度执行中的风险和问题\n");
        context.append("5. 严格判断测试结果，只有证据充分才能判定为通过，证据不足或存在差异必须判定为不通过\n");
        
        // 增加分类限制要求
        context.append("\n**特别重要要求：**\n");
        context.append("1. **只生成与").append(category).append("（对应八项规定第").append(POLICY_TITLE_MAP.get(category)).append("条）相关的内容**\n");
        context.append("2. **所有记录的title字段必须为\"").append(POLICY_TITLE_MAP.get(category)).append("\"**\n");
        context.append("3. **不得包含其他七项规定的内容**\n");
        
        // 如果是厉行勤俭节约分类，增加费用核定特别要求
        if (AuditContent1EightRegConstants.CATEGORY_ECONOMY.equals(category)) {
            context.append("\n**费用核定特别要求：**\n");
            context.append("1. **每次活动单独计算**：每笔凭证、每次招待活动必须单独计算费用合规性\n");
            context.append("2. **单独计算人均费用**：每次活动的总费用除以该次活动的总人数，得出该次活动的人均费用\n");
            context.append("3. **单独对比标准**：将每次活动的人均费用单独与公司标准对比，判定是否合规\n");
            context.append("4. **不得合并计算**：不得将多笔凭证、多次活动合并计算平均值\n");
            context.append("5. **逐笔描述**：每笔凭证的检查结果应作为独立记录\n");
        }

        // 3. 参考数据（从常量类中获取）
        context.append("## 参考数据\n");
        context.append("### 政策内容\n").append(AuditContent1EightRegConstants.POLICY_CONTENTS.get(category)).append("\n\n");
        context.append("### 实施细则\n").append(AuditContent1EightRegConstants.IMPLEMENTATION_DETAILS.get(category)).append("\n\n");

        // 4. 审计建议 - 新增部分
        String auditSuggestion = AuditContent1EightRegConstants.AUDIT_SUGGESTIONS.get(category);
        if (StrUtil.isNotBlank(auditSuggestion)) {
            context.append("## 审计建议\n");
            context.append("如发现被审计单位在").append(category).append("方面存在不符合中央八项规定的情况，可参考以下审计建议：\n\n");
            context.append(auditSuggestion).append("\n\n");
        }

        // 4. 历史内容
        if (StrUtil.isNotBlank(history)) {
            context.append("## 历史生成内容\n");
            context.append("以下是之前生成的内容，请基于此进行优化：\n");
            context.append(history).append("\n\n");
        }

        // 5. 用户建议
        if (StrUtil.isNotBlank(suggestion)) {
            context.append("## 用户优化建议\n");
            context.append("请根据以下建议对生成内容进行调整：\n");
            context.append(suggestion).append("\n\n");
        }

        // 6. 企业单位知识
        if (!knowledgeSources.get("enterprise").isEmpty()) {
            context.append("## 企业单位知识\n");
            knowledgeSources.get("enterprise").forEach(knowledge ->
                    context.append(knowledge).append("\n"));
            context.append("\n");
        }

        // 7. 法律法规知识
        if (!knowledgeSources.get("regulation").isEmpty()) {
            context.append("## 法律法规知识\n");
            knowledgeSources.get("regulation").forEach(knowledge ->
                    context.append(knowledge).append("\n"));
            context.append("\n");
        }

        // 8. 审计案例知识
        if (!knowledgeSources.get("auditCase").isEmpty()) {
            context.append("## 审计案例知识\n");
            knowledgeSources.get("auditCase").forEach(knowledge ->
                    context.append(knowledge).append("\n"));
        }
        
        // 2. 数据格式要求
        context.append("\n## 数据格式要求\n");
        context.append("需要生成").append(category).append("分类的数据，尽可能生成多个实例、多条记录：\n");
        context.append("- ").append(category).append("：").append(AuditContent1EightRegConstants.CATEGORY_DESCRIPTIONS.get(category)).append("\n");
        context.append("\n");
        
        context.append("每条记录应包含5个字段：\n");
//        context.append("- title：审计标题（必须按照八项规定顺序输出：一、二、三...八，对应八项规定的八个方面）\n");
        context.append("- title：审计标题（必须按照八项规定顺序输出：").append(POLICY_TITLE_MAP.get(category)).append("，对应").append(category).append("）\n");
        context.append("- content：审计内容（具体中共中央八项规定/具体中央八项规定实施细则）\n");
        context.append("- testContent：审计检查的证据，需详细描述查阅过程、查阅的具体文件和内容\n");
        context.append("- result：审计测试的结果（通过/不通过），严格判断，从严掌握通过标准\n");
//        context.append("- workPaperIndex：相关《参考文件FileId》，必须是实际存在的完整文件FileId，不能使用附表标题，确保能在文件夹中搜索到\n");
        context.append("- workPaperIndex：相关[\"实际存在的完整文件名||FileUrl\"]，必须是实际存在的完整文件名，不能使用附表标题，确保能在文件夹中搜索到\n");
        context.append("\n注意：\n");
        context.append("1. 请根据知识库内容尽可能全面地生成所有相关制度规定和检查点\n");
        context.append("2. 工作底稿索引必须准确对应实际文件名称，避免使用附表或章节标题\n");
        context.append("3. 测试结果判定需严格，对于制度不一致、执行不到位、证据不充分的情况必须判定为不通过\n");
//        context.append("4. title字段必须按照八项规定顺序输出：一、二、三...八\n\n");
        context.append("4. **title字段必须为\"").append(POLICY_TITLE_MAP.get(category)).append("\"，不得生成其他标题**\n\n");
        context.append("5. 除了本次说明中提供的数据知识等依据，不能从其他地方读取数据，不能凭空捏造数据\n");
        
        return context.toString();
    }

    /**
     * 八项规定相关性比较器
     */
    private int eightRegComparator(String reg1, String reg2) {
        int score1 = calculateEightRegRelevanceScore(reg1);
        int score2 = calculateEightRegRelevanceScore(reg2);
        return Integer.compare(score2, score1);
    }

    /**
     * 计算八项规定相关性分数
     */
    private int calculateEightRegRelevanceScore(String content) {
        return AuditContent1EightRegConstants.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 100;
            case "regulation": return 80;
            case "auditCase": return 60;
            default: return 50;
        }
    }
}