package com.ruoyi.oa.utils;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.oa.domain.vo.SysOaAiConfigVo;
import com.ruoyi.oa.domain.vo.SysOaAiMessageVo;
import com.ruoyi.oa.service.ISysOaAiConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.time.Duration;
import java.util.*;

/**
 * AI服务工具类
 *
 * @author ruoyi
 * @date 2024-12-19
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AiServiceUtil {

    private final ISysOaAiConfigService configService;
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

    // Redis缓存key前缀
    private static final String AI_CONFIG_CACHE_KEY = "ai:config:active";
    private static final String AI_CONVERSATION_CACHE_KEY = "ai:conversation:";
    private static final String AI_RESPONSE_CACHE_KEY = "ai:response:";

    /**
     * 调用DeepSeek AI服务（单次对话）
     *
     * @param message 用户消息
     * @return AI回复
     */
    public String callDeepSeek(String message) {
        return callDeepSeekWithHistory(message, null);
    }

    /**
     * 调用DeepSeek AI服务（连续对话）
     *
     * @param message 用户消息
     * @param conversationHistory 对话历史
     * @return AI回复
     */
    public String callDeepSeekWithHistory(String message, List<SysOaAiMessageVo> conversationHistory) {
        try {
            // 1. 检查缓存中是否有相同的请求
            String cacheKey = generateCacheKey(message, conversationHistory);
            String cachedResponse = RedisUtils.getCacheObject(cacheKey);
            if (cachedResponse != null) {
                log.info("从Redis缓存获取AI回复");
                return cachedResponse;
            }

            // 2. 获取AI配置（优先从缓存获取）
            SysOaAiConfigVo config = getCachedAiConfig();
            if (config == null) {
                throw new RuntimeException("未找到可用的AI配置");
            }

            // 3. 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + config.getApiKey());

            // 4. 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("model", config.getModelName());
            requestBody.put("temperature", config.getTemperature());
            requestBody.put("max_tokens", config.getMaxTokens());

            List<Map<String, String>> messages = new ArrayList<>();
            
            // 5. 添加对话历史
            if (conversationHistory != null && !conversationHistory.isEmpty()) {
                for (SysOaAiMessageVo historyMessage : conversationHistory) {
                    Map<String, String> historyMsg = new HashMap<>();
                    historyMsg.put("role", historyMessage.getRole());
                    historyMsg.put("content", historyMessage.getContent());
                    messages.add(historyMsg);
                }
            }
            
            // 6. 添加当前用户消息
            Map<String, String> userMessage = new HashMap<>();
            userMessage.put("role", "user");
            userMessage.put("content", message);
            messages.add(userMessage);
            
            requestBody.put("messages", messages);

            // 7. 发送请求
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
            String url = config.getBaseUrl() + "/chat/completions";
            
            log.info("调用DeepSeek API: {}, 消息数量: {}", url, messages.size());
            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);

            if (response.getStatusCode() == HttpStatus.OK) {
                JsonNode jsonNode = objectMapper.readTree(response.getBody());
                String aiResponse = jsonNode.path("choices").path(0).path("message").path("content").asText();
                
                // 8. 记录token使用情况
                int totalTokens = jsonNode.path("usage").path("total_tokens").asInt();
                log.info("AI回复成功，消耗token: {}", totalTokens);
                
                // 9. 缓存AI回复（缓存一天）
                RedisUtils.setCacheObject(cacheKey, aiResponse, Duration.ofDays(1));
                
                return aiResponse;
            } else {
                log.error("DeepSeek API调用失败: {}", response.getStatusCode());
                throw new RuntimeException("AI服务调用失败");
            }
        } catch (Exception e) {
            log.error("调用DeepSeek服务异常", e);
            throw new RuntimeException("AI服务调用异常: " + e.getMessage());
        }
    }

    /**
     * 获取缓存的AI配置
     */
    private SysOaAiConfigVo getCachedAiConfig() {
        // 先从Redis缓存获取
        SysOaAiConfigVo cachedConfig = RedisUtils.getCacheObject(AI_CONFIG_CACHE_KEY);
        if (cachedConfig != null) {
            log.debug("从Redis缓存获取AI配置");
            return cachedConfig;
        }

        // 缓存中没有，从数据库获取
        SysOaAiConfigVo config = configService.getActiveConfig();
        if (config != null) {
            // 缓存配置（缓存一天）
            RedisUtils.setCacheObject(AI_CONFIG_CACHE_KEY, config, Duration.ofDays(1));
            log.debug("AI配置已缓存到Redis");
        }

        return config;
    }

    /**
     * 生成缓存key
     */
    private String generateCacheKey(String message, List<SysOaAiMessageVo> conversationHistory) {
        StringBuilder keyBuilder = new StringBuilder(AI_RESPONSE_CACHE_KEY);
        keyBuilder.append(message.hashCode());
        
        if (conversationHistory != null && !conversationHistory.isEmpty()) {
            for (SysOaAiMessageVo history : conversationHistory) {
                keyBuilder.append(":").append(history.getContent().hashCode());
            }
        }
        
        return keyBuilder.toString();
    }

    /**
     * 缓存对话历史
     */
    public void cacheConversationHistory(Long conversationId, List<SysOaAiMessageVo> messages) {
        String cacheKey = AI_CONVERSATION_CACHE_KEY + conversationId;
        RedisUtils.setCacheObject(cacheKey, messages, Duration.ofDays(1));
        log.debug("对话历史已缓存到Redis, conversationId: {}", conversationId);
    }

    /**
     * 获取缓存的对话历史
     */
    public List<SysOaAiMessageVo> getCachedConversationHistory(Long conversationId) {
        String cacheKey = AI_CONVERSATION_CACHE_KEY + conversationId;
        List<SysOaAiMessageVo> cachedMessages = RedisUtils.getCacheObject(cacheKey);
        if (cachedMessages != null) {
            log.debug("从Redis缓存获取对话历史, conversationId: {}", conversationId);
        }
        return cachedMessages;
    }

    /**
     * 清除对话历史缓存
     */
    public void clearConversationCache(Long conversationId) {
        String cacheKey = AI_CONVERSATION_CACHE_KEY + conversationId;
        RedisUtils.deleteObject(cacheKey);
        log.debug("已清除对话历史缓存, conversationId: {}", conversationId);
    }

    /**
     * 清除AI配置缓存
     */
    public void clearAiConfigCache() {
        RedisUtils.deleteObject(AI_CONFIG_CACHE_KEY);
        log.debug("已清除AI配置缓存");
    }

    /**
     * 计算费用（示例：每1000个token 0.002美元）
     *
     * @param tokens token数量
     * @return 费用
     */
    public BigDecimal calculateCost(int tokens) {
        // 这里可以根据实际的定价策略计算费用
        BigDecimal costPerToken = new BigDecimal("0.000002"); // 每token 0.000002美元
        return costPerToken.multiply(new BigDecimal(tokens));
    }
} 