package com.lesingle.edu.common.security;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * JWT Token Redis 服务
 * 用于将 JWT token 存储到 Redis 中，支持 token 黑名单、刷新等功能
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class JwtTokenRedisService {

    private final RedisTemplate<String, Object> redisTemplate;

    /**
     * Token 前缀
     */
    private static final String TOKEN_PREFIX = "token:";

    /**
     * 黑名单前缀
     */
    private static final String BLACKLIST_PREFIX = "blacklist:";

    /**
     * 存储 token 到 Redis
     *
     * @param username 用户名
     * @param token    JWT token
     * @param expiration 过期时间（毫秒）
     */
    public void storeToken(String username, String token, long expiration) {
        String key = TOKEN_PREFIX + username;
        redisTemplate.opsForValue().set(key, token, expiration, TimeUnit.MILLISECONDS);
        log.debug("Token stored for user: {}", username);
    }

    /**
     * 获取存储的 token
     *
     * @param username 用户名
     * @return token，如果不存在返回 null
     */
    public String getStoredToken(String username) {
        String key = TOKEN_PREFIX + username;
        Object token = redisTemplate.opsForValue().get(key);
        return token != null ? token.toString() : null;
    }

    /**
     * 删除 token（用于 logout）
     *
     * @param username 用户名
     */
    public void deleteToken(String username) {
        String key = TOKEN_PREFIX + username;
        redisTemplate.delete(key);
        log.debug("Token deleted for user: {}", username);
    }

    /**
     * 将 token 加入黑名单
     *
     * @param token      JWT token
     * @param expiration 剩余过期时间（秒）
     */
    public void addToBlacklist(String token, long expiration) {
        String key = BLACKLIST_PREFIX + token;
        redisTemplate.opsForValue().set(key, "blacklisted", expiration, TimeUnit.SECONDS);
        log.debug("Token added to blacklist, ttl: {} seconds", expiration);
    }

    /**
     * 检查 token 是否在黑名单中
     *
     * @param token JWT token
     * @return true 如果在黑名单中
     */
    public boolean isBlacklisted(String token) {
        String key = BLACKLIST_PREFIX + token;
        return Boolean.TRUE.equals(redisTemplate.hasKey(key));
    }

    /**
     * 验证 token 是否有效
     * 1. 检查是否在黑名单中
     *
     * 注意：为支持多地点同时登录，不再检查 token 是否与 Redis 中存储的一致
     * JWT token 本身有过期时间，安全性足够
     *
     * @param username 用户名
     * @param token    JWT token
     * @return true 如果有效
     */
    public boolean validateToken(String username, String token) {
        // 仅检查是否在黑名单中
        if (isBlacklisted(token)) {
            log.debug("Token is blacklisted: {}", token.substring(0, Math.min(20, token.length())));
            return false;
        }

        // 不再检查是否与存储的 token 一致，允许同一账号有多个有效 token
        return true;
    }

    /**
     * 清理过期的 token（可选的定时任务）
     * 由于 Redis 会自动过期，此方法主要用于手动清理
     */
    public void cleanupExpiredTokens() {
        log.info("Cleaning up expired tokens (no action needed, Redis handles expiration)");
    }
}
