package com.seer.teach.common.cache;

import com.seer.teach.common.cache.dto.DeviceMetricDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;
import java.time.Duration;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * 设备指标信息缓存（仅 Redis 操作版本）。
 * 通过 Redis Hash 存储设备在线信息。
 */
@Slf4j
@Component
public class DeviceMetricsCache {

    /** Redis 主 key */
    private static final String DEVICE_ONLINE_KEY = "deviceOnline";

    /** 缓存有效期（默认 10 分钟） */
    private static final Duration L2_TTL = Duration.ofMinutes(10);

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 获取指定设备的指标信息。
     * 直接从 Redis 获取。
     *
     * @param deviceKey 设备唯一标识
     * @return 设备指标信息，未找到返回 null
     */
    public DeviceMetricDTO get(String deviceKey) {
        HashOperations<String, String, DeviceMetricDTO> ops = redisTemplate.opsForHash();
        return ops.get(DEVICE_ONLINE_KEY, deviceKey);
    }

    /**
     * 将设备指标信息写入 Redis。
     *
     * @param deviceKey 设备唯一标识
     * @param dto       设备指标数据
     */
    public void put(String deviceKey, DeviceMetricDTO dto) {
        HashOperations<String, String, DeviceMetricDTO> ops = redisTemplate.opsForHash();
        ops.put(DEVICE_ONLINE_KEY, deviceKey, dto);
        redisTemplate.expire(DEVICE_ONLINE_KEY, L2_TTL.toMillis(), TimeUnit.MILLISECONDS);
    }

    /**
     * 删除指定设备的缓存数据。
     *
     * @param deviceKey 设备唯一标识
     */
    public void invalidate(String deviceKey) {
        redisTemplate.opsForHash().delete(DEVICE_ONLINE_KEY, deviceKey);
        log.debug("从 Redis 删除设备缓存: {}", deviceKey);
    }

    /**
     * 查询所有在线设备的指标信息。
     *
     * @return 所有在线设备的指标映射表
     */
    @SuppressWarnings("unchecked")
    public Map<String, DeviceMetricDTO> getAllOnline() {
        Map<Object, Object> all = redisTemplate.opsForHash().entries(DEVICE_ONLINE_KEY);
        return Optional.ofNullable((Map<String, DeviceMetricDTO>) (Object) all)
                .orElse(Collections.emptyMap());
    }

    /**
     * 判断指定设备是否存在于 Redis 中。
     *
     * @param deviceKey 设备唯一标识
     * @return true=存在，false=不存在
     */
    public boolean exists(String deviceKey) {
        Boolean result = redisTemplate.opsForHash().hasKey(DEVICE_ONLINE_KEY, deviceKey);
        return Boolean.TRUE.equals(result);
    }
}
