import { Redis } from "ioredis";
import { env } from "../../config/env.js";
import { logger } from "../observability/logger.js";

/**
 * Redis 客户端（对齐 02-architecture-design.md §3.1）。
 *
 * 用于：
 * - ChildGuard 绑定列表缓存（30s TTL）
 * - 聚合结果缓存（15-600s TTL，P4.6）
 *
 * 连接策略：
 * - 懒连接（首次命令时连接）
 * - 连接失败时记录警告，不阻塞服务启动（降级为直连下游）
 * - SIGTERM 时优雅关闭
 */
let redisClient: Redis | null = null;
let connectionAttempted = false;

export function getRedisClient(): Redis | null {
  if (!connectionAttempted) {
    connectionAttempted = true;
    try {
      redisClient = new Redis(env.REDIS_URL, {
        maxRetriesPerRequest: 2,
        enableReadyCheck: true,
        lazyConnect: true,
        keyPrefix: env.REDIS_KEY_PREFIX,
      });

      redisClient.on("error", (err) => {
        logger.warn({ err, url: env.REDIS_URL }, "Redis connection error");
      });

      redisClient.on("connect", () => {
        logger.info({ url: env.REDIS_URL }, "Redis connected");
      });

      redisClient.on("close", () => {
        logger.warn("Redis connection closed");
      });
    } catch (err) {
      logger.warn({ err }, "Failed to create Redis client, caching disabled");
      redisClient = null;
    }
  }
  return redisClient;
}

/**
 * 安全执行 Redis 操作，失败时返回 null（降级策略）。
 */
export async function safeRedis<T>(
  fn: (client: Redis) => Promise<T>,
  fallback: T,
): Promise<T> {
  const client = getRedisClient();
  if (!client) {
    return fallback;
  }
  try {
    return await fn(client);
  } catch (err) {
    logger.warn({ err }, "Redis operation failed, using fallback");
    return fallback;
  }
}

/**
 * 优雅关闭 Redis 连接。
 */
export async function closeRedisClient(): Promise<void> {
  if (redisClient) {
    await redisClient.quit();
    redisClient = null;
    connectionAttempted = false;
  }
}
