package com.qaup.collision.websocket.cache;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.qaup.collision.websocket.message.UniversalMessage;

import java.time.Duration;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * WebSocket消息缓存服务
 * 使用Redis缓存最近的消息，支持客户端重连后恢复遗漏消息
 */
@Service
public class MessageCacheService {
    
    private final RedisTemplate<String, Object> redisTemplate;
    
    // 缓存配置常量
    private static final String CACHE_KEY_PREFIX = "websocket:messages:";
    private static final int MAX_CACHED_MESSAGES = 100; // 每类型最多缓存100条消息
    private static final Duration CACHE_EXPIRY = Duration.ofMinutes(30); // 30分钟过期
    
    @Autowired
    public MessageCacheService(@Qualifier("websocketRedisTemplate") RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }
    
    /**
     * 缓存消息
     * @param message 要缓存的WebSocket消息
     */
    public void cacheMessage(UniversalMessage<?> message) {
        try {
            String key = CACHE_KEY_PREFIX + message.getType();
            
            // 将消息添加到列表头部
            redisTemplate.opsForList().leftPush(key, message);
            
            // 保留最近的消息，删除超出限制的旧消息
            redisTemplate.opsForList().trim(key, 0, MAX_CACHED_MESSAGES - 1);
            
            // 设置过期时间
            redisTemplate.expire(key, CACHE_EXPIRY);
            
        } catch (Exception e) {
            // 缓存失败不应影响主业务流程，记录错误但不抛异常
            System.err.println("Failed to cache message: " + e.getMessage());
        }
    }
    
    /**
     * 获取指定类型的最近消息
     * @param messageType 消息类型
     * @param count 获取消息数量
     * @return 最近的消息列表
     */
    public List<UniversalMessage<?>> getRecentMessages(String messageType, int count) {
        try {
            String key = CACHE_KEY_PREFIX + messageType;
            List<Object> objects = redisTemplate.opsForList().range(key, 0, count - 1);
            
            if (objects == null) {
                return List.of();
            }
            
            return objects.stream()
                    .filter(obj -> obj instanceof UniversalMessage)
                    .map(obj -> (UniversalMessage<?>) obj)
                    .collect(Collectors.toList());
                    
        } catch (Exception e) {
            System.err.println("Failed to get recent messages: " + e.getMessage());
            return List.of();
        }
    }
    
    /**
     * 获取所有类型的最近消息
     * @param count 每种类型获取的消息数量
     * @return 所有类型的最近消息列表
     */
    public List<UniversalMessage<?>> getAllRecentMessages(int count) {
        try {
            // 获取所有缓存键
            String pattern = CACHE_KEY_PREFIX + "*";
            Set<String> keys = redisTemplate.keys(pattern);
            
            if (keys == null || keys.isEmpty()) {
                return List.of();
            }
            
            return keys.stream()
                    .flatMap(key -> {
                        String messageType = key.substring(CACHE_KEY_PREFIX.length());
                        return getRecentMessages(messageType, count).stream();
                    })
                    .collect(Collectors.toList());
                    
        } catch (Exception e) {
            System.err.println("Failed to get all recent messages: " + e.getMessage());
            return List.of();
        }
    }
    
    /**
     * 清除指定类型的缓存消息
     * @param messageType 消息类型
     */
    public void clearCache(String messageType) {
        try {
            String key = CACHE_KEY_PREFIX + messageType;
            redisTemplate.delete(key);
        } catch (Exception e) {
            System.err.println("Failed to clear cache: " + e.getMessage());
        }
    }
    
    /**
     * 清除所有缓存消息
     */
    public void clearAllCache() {
        try {
            String pattern = CACHE_KEY_PREFIX + "*";
            Set<String> keys = redisTemplate.keys(pattern);
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
            }
        } catch (Exception e) {
            System.err.println("Failed to clear all cache: " + e.getMessage());
        }
    }
} 