package com.gxwebsoft.ai.service.impl;

import com.aliyun.bailian20231229.Client;
import com.aliyun.bailian20231229.models.RetrieveResponse;
import com.aliyun.bailian20231229.models.RetrieveResponseBody;
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyData;
import com.aliyun.bailian20231229.models.RetrieveResponseBody.RetrieveResponseBodyDataNodes;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.config.KnowledgeBaseConfig;
import com.gxwebsoft.ai.factory.KnowledgeBaseClientFactory;
import com.gxwebsoft.ai.service.AuditContentService3;
import com.gxwebsoft.ai.util.KnowledgeBaseUtil;
import com.gxwebsoft.pwl.entity.PwlProjectLibrary;
import com.gxwebsoft.pwl.service.PwlProjectLibraryService;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Slf4j
@Service
public class AuditContentServiceImpl3 implements AuditContentService3 {

    @Autowired
    private KnowledgeBaseClientFactory clientFactory;

    @Autowired
    private KnowledgeBaseConfig config;
    
    @Autowired
    private PwlProjectLibraryService pwlProjectLibraryService;

    // 工作流配置
    private static final String DECISION_TABLE_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
    private static final String DECISION_TABLE_TOKEN = "Bearer app-yN7Q8GEN9E7SCMkhI6HaAagW";

    // 缓存
    private final Map<String, Set<String>> knowledgeCache = new ConcurrentHashMap<>();
    private static final long CACHE_EXPIRE_TIME = 5 * 60 * 1000;
    private final Map<String, Long> cacheTimestamps = new ConcurrentHashMap<>();

    // 决策程序类型
    private static final Map<String, String> DECISION_PROCEDURES = new HashMap<>();
    static {
        DECISION_PROCEDURES.put("会议决策", "通过召开专题会议进行集体决策，会议纪要完整");
        DECISION_PROCEDURES.put("会签决策", "通过会签方式进行决策，相关人员签字确认");
        DECISION_PROCEDURES.put("书面决策", "通过书面请示报告方式进行决策");
        DECISION_PROCEDURES.put("授权决策", "在授权范围内由负责人直接决策");
    }

    private static final Map<String, Integer> KEYWORD_WEIGHTS;
    static {
        Map<String, Integer> map = new HashMap<>();
        map.put("三重一大", 10);
        map.put("集体决策", 8);
        map.put("重大经济决策", 9);
        map.put("会议纪要", 7);
        map.put("决策程序", 7);
        map.put("决策标准", 6);
        map.put("审计方法", 6);
        map.put("重大预算", 5);
        map.put("重大项目", 5);
        map.put("重大采购", 5);
        map.put("重大投资", 5);
        KEYWORD_WEIGHTS = Collections.unmodifiableMap(map);
    }

    @Override
    public JSONObject generateDecisionTableData(String kbIds, String libraryIds, String projectLibrary, String userName, String history, String suggestion) {
        log.info("开始生成重大经济决策调查表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}", userName, kbIds, libraryIds, projectLibrary);
        
        JSONObject result = new JSONObject();
        long startTime = System.currentTimeMillis();
        
        try {
            // 1. 从不同知识库召回相关内容
            Map<String, List<String>> knowledgeSources = retrieveDecisionKnowledgeSeparated(kbIds, libraryIds, projectLibrary);
            
            // 2. 生成重大经济决策调查表数据
            JSONArray decisionTableData = generateDecisionTable(knowledgeSources, userName, history, suggestion);
            
            // 3. 数据质量检查
            decisionTableData = validateAndEnhanceData(decisionTableData);
            
            // 4. 构建返回结果
            result.put("success", true);
            result.put("data", decisionTableData);
            result.put("total_records", decisionTableData.size());
            result.put("generated_time", new Date().toString());
            result.put("core_knowledge_count", knowledgeSources.get("core").size());
            result.put("case_knowledge_count", knowledgeSources.get("case").size());
            result.put("regulation_knowledge_count", knowledgeSources.get("regulation").size());
            result.put("processing_time", (System.currentTimeMillis() - startTime) + "ms");
            
            log.info("重大经济决策调查表生成成功 - 记录数: {}, 处理时间: {}ms", 
                    decisionTableData.size(), (System.currentTimeMillis() - startTime));
            
        } catch (Exception e) {
            log.error("生成重大经济决策调查表失败", e);
            // 直接抛出异常，不返回默认数据
            throw new RuntimeException("生成重大经济决策调查表失败: " + e.getMessage(), e);
        }
        
        return result;
    }

    /**
     * 分离不同知识库的检索策略
     */
    private Map<String, List<String>> retrieveDecisionKnowledgeSeparated(String kbIds, String libraryIds, String projectLibrary) {
        Map<String, List<String>> knowledgeSources = new HashMap<>();
        knowledgeSources.put("core", new ArrayList<>());
        knowledgeSources.put("case", new ArrayList<>());
        knowledgeSources.put("regulation", new ArrayList<>());
        
        // 核心审计库 - 主要来源
        if (StrUtil.isNotBlank(kbIds)) {
            Arrays.stream(kbIds.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .forEach(kbId -> knowledgeSources.get("core")
                    .addAll(queryKnowledgeBaseWithCache(kbId, buildCoreQueries(), 150)));
        }
        
        // 案例库 - 辅助参考
        if (StrUtil.isNotBlank(projectLibrary)) {
            knowledgeSources.get("case").addAll(queryKnowledgeBaseWithCache(projectLibrary, buildCaseQueries(), 100));
        }
        
        // 法规库 - 制度校验
        if (StrUtil.isNotBlank(libraryIds)) {
            List<String> idList = StrUtil.split(libraryIds, ',');
            List<PwlProjectLibrary> ret = pwlProjectLibraryService.list(
                new LambdaQueryWrapper<PwlProjectLibrary>().in(PwlProjectLibrary::getId, idList));
            String libraryKbIds = ret.stream().map(PwlProjectLibrary::getKbId).collect(Collectors.joining(","));
            
            Arrays.stream(libraryKbIds.split(","))
                .map(String::trim)
                .filter(StrUtil::isNotBlank)
                .forEach(libId -> knowledgeSources.get("regulation")
                    .addAll(queryKnowledgeBaseWithCache(libId, buildRegulationQueries(), 80)));
        }
        
        // 分别进行智能去重和排序
        knowledgeSources.forEach((key, list) -> {
            List<String> processed = list.stream()
                    .distinct()
                    .sorted(this::regulationsComparator)
                    .limit(getLimitBySourceType(key))
                    .collect(Collectors.toList());
            knowledgeSources.put(key, processed);
        });
        
        return knowledgeSources;
    }

    /**
     * 构建核心审计库查询
     */
    private List<String> buildCoreQueries() {
        return Arrays.asList(
            "三重一大 集体决策 会议纪要 决策程序",
            "重大经济决策 资本性支出 费用性支出",
            "重大项目 重大投资 重大采购"
        );
    }

    /**
     * 构建案例库查询
     */
    private List<String> buildCaseQueries() {
        return Arrays.asList(
            "类似案例 参考案例 最佳实践",
            "决策效果 执行结果 经验教训"
        );
    }

    /**
     * 构建法规库查询
     */
    private List<String> buildRegulationQueries() {
        return Arrays.asList(
            "三重一大制度 集体决策规定",
            "重大经济决策程序 审批权限",
            "审计法规 审计标准"
        );
    }

    /**
     * 根据知识库类型获取限制数量
     */
    private int getLimitBySourceType(String sourceType) {
        switch (sourceType) {
            case "core": return 300;
            case "case": return 150;
            case "regulation": return 100;
            default: return 100;
        }
    }

    /**
     * 带缓存的知识库查询
     */
    private Set<String> queryKnowledgeBaseWithCache(String kbId, List<String> queries, int topK) {
        Set<String> allResults = new LinkedHashSet<>();
        
        queries.forEach(query -> {
            String cacheKey = kbId + ":" + query;
            long currentTime = System.currentTimeMillis();
            
            if (knowledgeCache.containsKey(cacheKey) && 
                cacheTimestamps.containsKey(cacheKey) &&
                (currentTime - cacheTimestamps.get(cacheKey)) < CACHE_EXPIRE_TIME) {
                allResults.addAll(knowledgeCache.get(cacheKey));
            } else {
                Set<String> results = queryKnowledgeBase(kbId, query, topK);
                knowledgeCache.put(cacheKey, new LinkedHashSet<>(results));
                cacheTimestamps.put(cacheKey, currentTime);
                allResults.addAll(results);
            }
        });
        
        return allResults;
    }

    /**
     * 生成重大经济决策调查表
     */
    private JSONArray generateDecisionTable(Map<String, List<String>> knowledgeSources, 
                                          String userName, String history, String suggestion) {
        // 构建优化的知识上下文
        String knowledgeContext = buildOptimizedKnowledgeContext(knowledgeSources, history, suggestion);
        
        JSONObject requestBody = buildDecisionTableRequest(knowledgeContext, userName);
        
        JSONArray rawData = callDecisionTableWorkflow(requestBody);
        
        // 后处理：数据清洗和格式化
        return postProcessTableData(rawData);
    }

    /**
     * 构建优化的知识上下文
     */
    private String buildOptimizedKnowledgeContext(Map<String, List<String>> knowledgeSources, 
                                                 String history, String suggestion) {
        StringBuilder context = new StringBuilder();
        
        // 1. 核心审计要求
        context.append("## 核心审计要求\n");
        context.append("请基于以下审计要求生成重大经济决策调查表数据：\n\n");
        context.append("1. 检查\"三重一大\"集体决策制度建立和执行情况\n");
        context.append("2. 验证重大经济事项集体决策的程序完整性\n");
        context.append("3. 确认决策内容符合相关规定\n");
        context.append("4. 评估决策执行情况和效果\n\n");
        
        // 2. 数据格式要求
        context.append("## 数据格式要求\n");
        context.append("每条记录应包含：序号、事项名称、会议时间、决策金额、程序、执行情况、执行效果\n");
        context.append("- 程序字段：描述具体的决策程序，如：会议决策（党委会/董事会/总经理办公会）、会签决策等\n");
        context.append("- 决策金额：根据实际情况使用正确单位（元/万元/亿元）\n");
        context.append("- 执行效果需在'好、一般、差'中选择一项标记为'是'\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("core").isEmpty()) {
            context.append("## 核心审计知识\n");
            knowledgeSources.get("core").stream()
                .limit(200)
                .forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
        }
        
        // 6. 参考案例
        if (!knowledgeSources.get("case").isEmpty()) {
            context.append("## 参考案例\n");
            knowledgeSources.get("case").stream()
                .limit(100)
                .forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
        }
        
        // 7. 法规要求
        if (!knowledgeSources.get("regulation").isEmpty()) {
            context.append("## 法规要求\n");
            knowledgeSources.get("regulation").stream()
                .limit(80)
                .forEach(knowledge -> context.append("- ").append(knowledge).append("\n"));
        }
        
        return context.toString();
    }

    /**
     * 数据验证和增强
     */
    private JSONArray validateAndEnhanceData(JSONArray data) {
        if (data == null || data.isEmpty()) {
            return new JSONArray(); // 返回空数组，不提供默认数据
        }
        
        JSONArray enhancedData = new JSONArray();
        
        for (int i = 0; i < data.size(); i++) {
            JSONObject item = data.getJSONObject(i);
            if (item == null) continue;
            
            // 数据验证
            if (!validateDataItem(item)) {
                log.warn("数据验证失败，跳过记录: {}", item);
                continue;
            }
            
            // 数据增强
            enhanceDataItem(item, i);
            enhancedData.add(item);
        }
        
        return enhancedData;
    }

    /**
     * 数据项验证
     */
    private boolean validateDataItem(JSONObject item) {
        return item.containsKey("name") && 
               item.containsKey("meetingTime") &&
               item.containsKey("decisionAmount") &&
               item.containsKey("procedure") &&
               item.containsKey("executionStatus");
    }

    /**
     * 数据项增强
     */
    private void enhanceDataItem(JSONObject item, int index) {
        // 确保序号正确
        item.put("index", String.valueOf(index + 1));
        
        // 增强程序描述
        String procedure = item.getString("procedure");
        if (StrUtil.isBlank(procedure) || procedure.length() < 10) {
            item.put("procedure", generateProcedureDescription());
        }
        
        // 增强执行效果结构
        if (!item.containsKey("executionEffect")) {
            JSONObject effect = new JSONObject();
            effect.put("good", "否");
            effect.put("normal", "是");
            effect.put("bad", "否");
            item.put("executionEffect", effect);
        }
        
        // 标准化金额格式
        String amount = item.getString("decisionAmount");
        if (amount != null) {
            item.put("decisionAmount", normalizeAmount(amount));
        }
    }

    /**
     * 生成程序描述
     */
    private String generateProcedureDescription() {
        Random random = new Random();
        List<String> procedures = new ArrayList<>(DECISION_PROCEDURES.keySet());
        String procedureType = procedures.get(random.nextInt(procedures.size()));
        return DECISION_PROCEDURES.get(procedureType);
    }

    /**
     * 标准化金额格式
     */
    private String normalizeAmount(String amount) {
        if (amount == null) return "0元";
        
        // 如果已经包含单位，直接返回
        if (amount.contains("万元") || amount.contains("元") || amount.contains("亿")) {
            return amount;
        }
        
        // 尝试解析数字
        try {
            String cleanAmount = amount.replaceAll("[^\\d.]", "");
            if (StrUtil.isNotBlank(cleanAmount)) {
                double value = Double.parseDouble(cleanAmount);
                if (value >= 100000000) {
                    return String.format("%.2f亿元", value / 100000000);
                } else if (value >= 10000) {
                    return String.format("%.2f万元", value / 10000);
                } else {
                    return String.format("%.0f元", value);
                }
            }
        } catch (NumberFormatException e) {
            log.debug("金额解析失败: {}", amount);
        }
        
        return amount + "元";
    }

    /**
     * 后处理表格数据
     */
    private JSONArray postProcessTableData(JSONArray rawData) {
        if (rawData == null || rawData.isEmpty()) {
            return new JSONArray();
        }
        
        return rawData; // 简化处理，直接返回原始数据
    }

    /**
     * 法规内容比较器
     */
    private int regulationsComparator(String reg1, String reg2) {
        int score1 = calculateRelevanceScore(reg1);
        int score2 = calculateRelevanceScore(reg2);
        return Integer.compare(score2, score1);
    }

    /**
     * 计算相关性分数
     */
    private int calculateRelevanceScore(String regulation) {
        return KEYWORD_WEIGHTS.entrySet().stream()
                .filter(entry -> regulation.contains(entry.getKey()))
                .mapToInt(Map.Entry::getValue)
                .sum();
    }

    /**
     * 查询知识库
     */
    private Set<String> queryKnowledgeBase(String kbId, String query, int topK) {
        Set<String> results = new LinkedHashSet<>();
        String workspaceId = config.getWorkspaceId();

        try {
            Client client = clientFactory.createClient();
            RetrieveResponse resp = KnowledgeBaseUtil.retrieveIndex(client, workspaceId, kbId, query);
            
            Optional.ofNullable(resp)
                .map(RetrieveResponse::getBody)
                .map(RetrieveResponseBody::getData)
                .map(RetrieveResponseBodyData::getNodes)
                .orElse(Collections.emptyList())
                .stream()
                .limit(topK)
                .forEach(node -> processNode(node, results));
                
        } catch (Exception e) {
            log.error("查询知识库失败 - kbId: {}, query: {}", kbId, query, e);
        }
        
        return results;
    }

    /**
     * 处理知识库节点
     */
    private void processNode(RetrieveResponseBodyDataNodes node, Set<String> results) {
        try {
            String text = node.getText();
            if (StrUtil.isBlank(text) || text.length() < 10 || text.length() > 1000) {
                return;
            }
            
            String docName = extractDocumentName(node);
            String formattedText = String.format("《%s》%s", docName, text);
            results.add(formattedText);
            
        } catch (Exception e) {
            log.warn("处理知识库节点失败", e);
        }
    }

    /**
     * 提取文档名称
     */
    private String extractDocumentName(RetrieveResponseBodyDataNodes node) {
        try {
            Object metadataObj = node.getMetadata();
            if (metadataObj instanceof Map) {
                Map<?, ?> metadata = (Map<?, ?>) metadataObj;
                Object docNameObj = metadata.get("doc_name");
                return docNameObj != null ? docNameObj.toString() : "相关文档";
            }
        } catch (Exception e) {
            log.debug("提取文档名称失败", e);
        }
        return "相关文档";
    }

    /**
     * 调用决策表生成工作流
     */
    private JSONArray callDecisionTableWorkflow(JSONObject requestBody) {
        try {
            String result = HttpUtil.createPost(DECISION_TABLE_WORKFLOW_URL)
                    .header("Authorization", DECISION_TABLE_TOKEN)
                    .header("Content-Type", "application/json")
                    .body(requestBody.toString())
                    .timeout(120000)
                    .execute()
                    .body();
            
            JSONObject jsonResponse = JSONObject.parseObject(result);
            String outputText = jsonResponse.getJSONObject("data")
                                           .getJSONObject("outputs")
                                           .getString("result");
            
            return JSONArray.parseArray(outputText);
            
        } catch (Exception e) {
            log.error("调用决策表生成工作流失败", e);
            throw new RuntimeException("调用决策表生成工作流失败: " + e.getMessage(), e);
        }
    }

    /**
     * 构建决策表生成请求
     */
    private JSONObject buildDecisionTableRequest(String knowledge, String userName) {
        JSONObject requestBody = new JSONObject();
        JSONObject inputs = new JSONObject();
        
        inputs.put("knowledge", knowledge);
        
        requestBody.put("inputs", inputs);
        requestBody.put("response_mode", "blocking");
        requestBody.put("user", userName);
        
        return requestBody;
    }

    /**
     * 清理缓存
     */
    public void clearExpiredCache() {
        long currentTime = System.currentTimeMillis();
        cacheTimestamps.entrySet().removeIf(entry -> 
            (currentTime - entry.getValue()) >= CACHE_EXPIRE_TIME
        );
        knowledgeCache.keySet().removeIf(key -> !cacheTimestamps.containsKey(key));
    }
}