package org.xyzh.ai.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.xyzh.ai.mapper.AiKnowledgeMapper;
import org.xyzh.ai.service.AiKnowledgeRedisService;
import org.xyzh.common.dto.ai.TbAiKnowledge;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @description AI知识库Redis管理服务实现类
 * @filename AiKnowledgeRedisServiceImpl.java
 * @author AI Assistant
 * @copyright xyzh
 * @since 2025-11-06
 */
@Slf4j
@Service
public class AiKnowledgeRedisServiceImpl implements AiKnowledgeRedisService, CommandLineRunner {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private AiKnowledgeMapper knowledgeMapper;

    // Redis Key前缀：ai:dept:knowledge:{deptId}
    private static final String REDIS_KEY_DEPT_KNOWLEDGE = "ai:dept:knowledge:";

    // Redis过期时间（7天）
    private static final long REDIS_EXPIRE_DAYS = 7;

    /**
     * 系统启动时自动初始化
     */
    @Override
    public void run(String... args) throws Exception {
        log.info("=== 开始初始化知识库到Redis ===");
        initializeAllKnowledgeToRedis();
        log.info("=== 知识库初始化完成 ===");
    }

    @Override
    public void initializeAllKnowledgeToRedis() {
        try {
            // 查询所有已同步到Dify的知识库
            List<TbAiKnowledge> allKnowledges = knowledgeMapper.selectAllKnowledges(new TbAiKnowledge());
            
            // 按部门分组知识库
            Map<String, List<String>> deptKnowledgeMap = new HashMap<>();
            
            for (TbAiKnowledge knowledge : allKnowledges) {
                // 只处理已同步到Dify且未删除的知识库
                if (knowledge.getDifyDatasetId() != null && !knowledge.getDifyDatasetId().isEmpty() 
                        && !knowledge.getDeleted()) {
                    
                    String deptId = knowledge.getCreatorDept();
                    if (deptId == null || deptId.isEmpty()) {
                        log.warn("知识库 {} 没有部门信息，跳过", knowledge.getID());
                        continue;
                    }
                    
                    // 将知识库添加到对应部门的列表中
                    deptKnowledgeMap.computeIfAbsent(deptId, k -> new ArrayList<>())
                            .add(knowledge.getDifyDatasetId());
                }
            }

            if (deptKnowledgeMap.isEmpty()) {
                log.warn("未找到已同步到Dify且有部门信息的知识库");
                return;
            }

            // 为每个部门设置知识库
            int totalCount = 0;
            for (Map.Entry<String, List<String>> entry : deptKnowledgeMap.entrySet()) {
                String deptId = entry.getKey();
                List<String> knowledgeIds = entry.getValue();
                setDeptKnowledgeIds(deptId, knowledgeIds);
                totalCount += knowledgeIds.size();
                log.info("已设置部门 {} 的知识库，共 {} 个", deptId, knowledgeIds.size());
            }
            
            log.info("知识库初始化完成，共 {} 个部门，{} 个知识库", deptKnowledgeMap.size(), totalCount);

        } catch (Exception e) {
            log.error("初始化知识库到Redis失败", e);
        }
    }

    /**
     * 设置部门的知识库ID列表
     */
    public void setDeptKnowledgeIds(String deptId, List<String> knowledgeIds) {
        try {
            String key = REDIS_KEY_DEPT_KNOWLEDGE + deptId;
            redisTemplate.opsForValue().set(key, knowledgeIds, REDIS_EXPIRE_DAYS, TimeUnit.DAYS);
            log.debug("已设置部门 {} 的知识库: {}", deptId, knowledgeIds);
        } catch (Exception e) {
            log.error("设置部门知识库失败: deptId={}", deptId, e);
        }
    }

    /**
     * 根据部门路径获取知识库ID列表（包含父部门的知识库）
     * @param deptPath 部门路径，例如：/1/3/5/
     * @return 知识库ID列表（已去重）
     */
    @SuppressWarnings("unchecked")
    public List<String> getKnowledgeIdsByDeptPath(String deptPath) {
        Set<String> knowledgeIdSet = new HashSet<>();
        
        try {
            if (deptPath == null || deptPath.isEmpty()) {
                log.warn("部门路径为空，返回空知识库列表");
                return new ArrayList<>();
            }

            // 解析部门路径，例如：/1/3/5/ -> [1, 3, 5]
            Set<String> deptIdList = new HashSet<>(Arrays.asList(deptPath.split("/")));
            deptIdList.add("root_department");
            

            if (deptIdList.isEmpty()) {
                log.warn("解析部门路径失败: {}", deptPath);
                return new ArrayList<>();
            }

            // 依次查询当前部门及所有父部门的知识库
            for (String deptId : deptIdList) {
                String key = REDIS_KEY_DEPT_KNOWLEDGE + deptId;
                Object result = redisTemplate.opsForValue().get(key);
                if (result != null) {
                    List<String> deptKnowledgeIds = (List<String>) result;
                    knowledgeIdSet.addAll(deptKnowledgeIds);
                    log.debug("从部门 {} 获取到 {} 个知识库", deptId, deptKnowledgeIds.size());
                }
            }


            List<String> resultList = new ArrayList<>(knowledgeIdSet);
            log.info("根据部门路径 {} 获取到 {} 个知识库（已去重）", deptPath, resultList.size());
            return resultList;

        } catch (Exception e) {
            log.error("根据部门路径获取知识库失败: deptPath={}", deptPath, e);
            return new ArrayList<>();
        }
    }

    @Override
    public void clearAllKnowledgeConfig() {
        try {
            // 删除所有知识库相关的Redis Key
            redisTemplate.delete(redisTemplate.keys(REDIS_KEY_DEPT_KNOWLEDGE + "*"));
            log.info("已清除所有知识库配置");
        } catch (Exception e) {
            log.error("清除所有知识库配置失败", e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void addKnowledgeToDeptCache(String deptId, String difyDatasetId) {
        try {
            if (deptId == null || deptId.isEmpty()) {
                log.warn("部门ID为空，无法添加知识库到缓存");
                return;
            }
            if (difyDatasetId == null || difyDatasetId.isEmpty()) {
                log.warn("Dify知识库ID为空，无法添加到缓存");
                return;
            }

            String key = REDIS_KEY_DEPT_KNOWLEDGE + deptId;
            
            // 获取现有的知识库列表
            List<String> knowledgeIds = (List<String>) redisTemplate.opsForValue().get(key);
            if (knowledgeIds == null) {
                knowledgeIds = new ArrayList<>();
            }
            
            // 避免重复添加
            if (!knowledgeIds.contains(difyDatasetId)) {
                knowledgeIds.add(difyDatasetId);
                // 更新到Redis
                redisTemplate.opsForValue().set(key, knowledgeIds, REDIS_EXPIRE_DAYS, TimeUnit.DAYS);
                log.info("已添加知识库到部门缓存: deptId={}, difyDatasetId={}", deptId, difyDatasetId);
            } else {
                log.debug("知识库已存在于部门缓存中: deptId={}, difyDatasetId={}", deptId, difyDatasetId);
            }
        } catch (Exception e) {
            log.error("添加知识库到部门缓存失败: deptId={}, difyDatasetId={}", deptId, difyDatasetId, e);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void removeKnowledgeFromDeptCache(String deptId, String difyDatasetId) {
        try {
            if (deptId == null || deptId.isEmpty()) {
                log.warn("部门ID为空，无法从缓存移除知识库");
                return;
            }
            if (difyDatasetId == null || difyDatasetId.isEmpty()) {
                log.warn("Dify知识库ID为空，无法从缓存移除");
                return;
            }

            String key = REDIS_KEY_DEPT_KNOWLEDGE + deptId;
            
            // 获取现有的知识库列表
            List<String> knowledgeIds = (List<String>) redisTemplate.opsForValue().get(key);
            if (knowledgeIds == null || knowledgeIds.isEmpty()) {
                log.debug("部门缓存为空，无需移除: deptId={}", deptId);
                return;
            }
            
            // 移除知识库
            if (knowledgeIds.remove(difyDatasetId)) {
                // 更新到Redis
                if (knowledgeIds.isEmpty()) {
                    // 如果列表为空，删除整个key
                    redisTemplate.delete(key);
                    log.info("部门缓存已空，已删除key: deptId={}", deptId);
                } else {
                    redisTemplate.opsForValue().set(key, knowledgeIds, REDIS_EXPIRE_DAYS, TimeUnit.DAYS);
                }
                log.info("已从部门缓存移除知识库: deptId={}, difyDatasetId={}", deptId, difyDatasetId);
            } else {
                log.debug("知识库不存在于部门缓存中: deptId={}, difyDatasetId={}", deptId, difyDatasetId);
            }
        } catch (Exception e) {
            log.error("从部门缓存移除知识库失败: deptId={}, difyDatasetId={}", deptId, difyDatasetId, e);
        }
    }
}

