package com.qaup.collision.common.service;

import com.qaup.collision.common.model.base.CacheConstants;
import com.qaup.collision.common.model.spatial.VehicleLocation;
import lombok.extern.slf4j.Slf4j;
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 java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 空间查询缓存服务类
 * 基于Redis实现空间查询结果的高性能缓存
 * 
 * 主要功能：
 * 1. 空间查询结果缓存
 * 2. 区域内载具查询缓存
 * 3. 载具位置查询缓存
 * 4. 缓存失效和刷新策略
 */
@Slf4j
@Service
public class SpatialQueryCacheService {

    private final RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    public SpatialQueryCacheService(
            @Qualifier("redisTemplate") RedisTemplate<Object, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 缓存空间查询结果
     * 
     * @param queryId 查询ID
     * @param result 查询结果
     * @param expireSeconds 过期时间（秒）
     */
    public void cacheQueryResult(String queryId, Object result, long expireSeconds) {
        try {
            String key = CacheConstants.buildSpatialQueryKey(queryId);
            redisTemplate.opsForValue().set(key, result, expireSeconds, TimeUnit.SECONDS);
            
            log.debug("缓存空间查询结果: queryId={}, expireSeconds={}", queryId, expireSeconds);
        } catch (Exception e) {
            log.warn("缓存空间查询结果失败: queryId={}", queryId, e);
        }
    }

    /**
     * 获取空间查询结果
     * 
     * @param queryId 查询ID
     * @return 查询结果，不存在则返回null
     */
    public Object getQueryResult(String queryId) {
        try {
            String key = CacheConstants.buildSpatialQueryKey(queryId);
            Object result = redisTemplate.opsForValue().get(key);
            
            log.debug("获取空间查询结果: queryId={}, found={}", queryId, result != null);
            return result;
        } catch (Exception e) {
            log.warn("获取空间查询结果失败: queryId={}", queryId, e);
            return null;
        }
    }

    /**
     * 缓存区域内载具查询结果
     * 
     * @param areaName 区域名称
     * @param vehicles 载具列表
     */
    public void cacheVehiclesInArea(String areaName, List<VehicleLocation> vehicles) {
        try {
            String key = CacheConstants.VEHICLES_IN_AREA_PREFIX + areaName;
            redisTemplate.opsForValue()
                .set(key, vehicles, CacheConstants.SPATIAL_QUERY_EXPIRE, TimeUnit.SECONDS);
            
            log.debug("缓存区域内载具查询结果: areaName={}, vehicleCount={}", areaName, vehicles.size());
        } catch (Exception e) {
            log.warn("缓存区域内载具查询结果失败: areaName={}", areaName, e);
        }
    }

    /**
     * 获取区域内载具查询结果
     * 
     * @param areaName 区域名称
     * @return 载具列表，不存在则返回null
     */
    @SuppressWarnings("unchecked")
    public List<VehicleLocation> getVehiclesInArea(String areaName) {
        try {
            String key = CacheConstants.VEHICLES_IN_AREA_PREFIX + areaName;
            Object result = redisTemplate.opsForValue().get(key);
            
            if (result instanceof List) {
                List<VehicleLocation> vehicles = (List<VehicleLocation>) result;
                log.debug("获取区域内载具查询结果: areaName={}, vehicleCount={}", areaName, vehicles.size());
                return vehicles;
            }
            
            log.debug("区域内载具查询结果缓存未命中: areaName={}", areaName);
            return null;
        } catch (Exception e) {
            log.warn("获取区域内载具查询结果失败: areaName={}", areaName, e);
            return null;
        }
    }

    /**
     * 删除空间查询缓存
     * 
     * @param queryId 查询ID
     */
    public void evictQueryResult(String queryId) {
        try {
            String key = CacheConstants.buildSpatialQueryKey(queryId);
            redisTemplate.delete(key);
            
            log.debug("清除空间查询结果缓存: queryId={}", queryId);
        } catch (Exception e) {
            log.warn("清除空间查询结果缓存失败: queryId={}", queryId, e);
        }
    }

    /**
     * 清除所有空间查询缓存
     */
    public void clearAllQueryCache() {
        try {
            String pattern = CacheConstants.SPATIAL_QUERY_PREFIX + "*";
            Set<Object> keys = redisTemplate.keys(pattern);
            
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
                log.info("清除所有空间查询缓存: count={}", keys.size());
            }
        } catch (Exception e) {
            log.warn("清除所有空间查询缓存失败", e);
        }
    }

    /**
     * 获取缓存统计信息
     * 
     * @return 缓存统计信息
     */
    public Map<String, Object> getCacheStatistics() {
        try {
            Map<String, Object> stats = new HashMap<>();
            
            // 空间查询缓存数量
            String queryPattern = CacheConstants.SPATIAL_QUERY_PREFIX + "*";
            Set<Object> queryKeys = redisTemplate.keys(queryPattern);
            stats.put("spatialQueryCacheCount", queryKeys != null ? queryKeys.size() : 0);
            
            // 区域内载具缓存数量
            String vehiclePattern = CacheConstants.VEHICLES_IN_AREA_PREFIX + "*";
            Set<Object> vehicleKeys = redisTemplate.keys(vehiclePattern);
            stats.put("vehiclesInAreaCacheCount", vehicleKeys != null ? vehicleKeys.size() : 0);
            
            return stats;
        } catch (Exception e) {
            log.warn("获取空间查询缓存统计信息失败", e);
            return Collections.emptyMap();
        }
    }
} 