import { Injectable } from "@nestjs/common";
import { getRedis } from "../../config/redis.js";

const PERMISSION_CACHE_TTL_SECONDS = 300; // 5 分钟

/**
 * 权限缓存服务（I3 裁决：DB 驱动 + Redis 缓存）。
 *
 * 缓存策略：
 * - Key: `iam:perm:{userId}` → JSON string[] 权限名列表
 * - TTL: 5 分钟，超时自动失效重新从 DB 加载
 * - 失效：角色变更 / 权限变更时主动 del（通过 Outbox 事件触发）
 *
 * 使用 ioredis 单例（config/redis.ts 管理），不重复创建连接。
 */
@Injectable()
export class PermissionCacheService {
  private static buildKey(userId: string): string {
    return `iam:perm:${userId}`;
  }

  async getPermissions(userId: string): Promise<string[] | null> {
    const redis = getRedis();
    const raw = await redis.get(PermissionCacheService.buildKey(userId));
    if (!raw) return null;
    try {
      const parsed = JSON.parse(raw) as unknown;
      if (Array.isArray(parsed) && parsed.every((p) => typeof p === "string")) {
        return parsed as string[];
      }
      return null;
    } catch {
      return null;
    }
  }

  async setPermissions(userId: string, permissions: string[]): Promise<void> {
    const redis = getRedis();
    await redis.set(
      PermissionCacheService.buildKey(userId),
      JSON.stringify(permissions),
      "EX",
      PERMISSION_CACHE_TTL_SECONDS,
    );
  }

  async invalidate(userId: string): Promise<void> {
    const redis = getRedis();
    await redis.del(PermissionCacheService.buildKey(userId));
  }
}
