/**
 * Token Blacklist Manager
 * Redis-based storage for revoked tokens
 * Supports distributed systems with automatic TTL-based expiration
 */

import { redisConnection } from "$connections/index.js";

/**
 * Generate Redis key for a blacklisted token
 * @param {string} token - JWT token
 * @returns {string} Redis key
 */
const getBlacklistKey = (token) => {
  return `blacklist:token:${token}`;
};

/**
 * Add a token to the blacklist
 * @param {string} token - JWT token to revoke
 * @param {number} expiresIn - Time in seconds until token expires (default: 24 hours)
 * @returns {Promise<void>}
 */
export const revokeToken = async (token, expiresIn = 86400) => {
  try {
    const key = getBlacklistKey(token);
    // Store token with automatic expiration (TTL)
    // Value is timestamp when token was revoked
    await redisConnection.setex(key, expiresIn, Date.now().toString());
  } catch (error) {
    console.error("❌ Error revoking token:", error);
    throw new Error("Failed to revoke token");
  }
};

/**
 * Check if a token is blacklisted
 * @param {string} token - JWT token to check
 * @returns {Promise<boolean>} True if token is revoked
 */
export const isTokenRevoked = async (token) => {
  try {
    const key = getBlacklistKey(token);
    const exists = await redisConnection.exists(key);
    return exists === 1;
  } catch (error) {
    console.error("❌ Error checking token blacklist:", error);
    // In case of Redis error, fail securely by treating token as revoked
    return true;
  }
};

/**
 * Get count of blacklisted tokens
 * @returns {Promise<number>} Number of revoked tokens
 */
export const getBlacklistSize = async () => {
  try {
    const keys = await redisConnection.keys("blacklist:token:*");
    return keys.length;
  } catch (error) {
    console.error("❌ Error getting blacklist size:", error);
    return 0;
  }
};

/**
 * Clear all blacklisted tokens (for testing purposes)
 * WARNING: This will remove all blacklisted tokens from Redis
 * @returns {Promise<void>}
 */
export const clearBlacklist = async () => {
  try {
    const keys = await redisConnection.keys("blacklist:token:*");
    if (keys.length > 0) {
      await redisConnection.del(...keys);
    }
  } catch (error) {
    console.error("❌ Error clearing blacklist:", error);
    throw new Error("Failed to clear blacklist");
  }
};

/**
 * Remove a specific token from the blacklist (for testing/admin purposes)
 * @param {string} token - JWT token to remove from blacklist
 * @returns {Promise<boolean>} True if token was removed
 */
export const removeTokenFromBlacklist = async (token) => {
  try {
    const key = getBlacklistKey(token);
    const result = await redisConnection.del(key);
    return result === 1;
  } catch (error) {
    console.error("❌ Error removing token from blacklist:", error);
    return false;
  }
};
