/**
 * 速率限制器门面（audit-P1-6）
 *
 * 公共 API 与原 `rate-limit.ts` 单文件保持一致，差异：
 * - `rateLimit()` 与 `resetRateLimit()` 改为 `Promise` 返回，以支持异步后端
 * - 内部根据 `RATE_LIMIT_DRIVER` 环境变量选择实现：
 *   - `memory`（默认）：单实例内存滑动窗口
 *   - `redis`：基于 @upstash/ratelimit + @upstash/redis 的分布式实现
 * - 调用方需 `await rateLimit(...)` / `await resetRateLimit(...)`
 *
 * `rateLimitKey` / `RATE_LIMIT_RULES` / `rateLimitHeaders` 保持同步纯函数。
 */

import { env } from "@/env.mjs"

import type { RateLimiter, RateLimitParams, RateLimitResult } from "./types"

export type { RateLimiter, RateLimitParams, RateLimitResult } from "./types"
export { RATE_LIMIT_RULES, rateLimitHeaders, rateLimitKey } from "./rules"

import { MemoryRateLimiter } from "./memory-limiter"

/**
 * 单例限流器实例（按 env 选择实现，进程级复用）。
 *
 * Redis 实现通过动态 `import("./redis-limiter")` 按需加载，
 * 仅当 `RATE_LIMIT_DRIVER=redis` 时才会拉入 `redis-limiter.ts` 模块及其
 * `@upstash/ratelimit` / `@upstash/redis` 依赖。默认内存模式下该模块不进入
 * 模块图，避免可选依赖缺失导致编译失败。
 */
let singleton: RateLimiter | null = null

/**
 * 获取当前进程的限流器实例。
 *
 * - 默认返回内存实现
 * - 当 `RATE_LIMIT_DRIVER=redis` 时动态加载 Redis 实现
 * - Redis 实现懒加载 @upstash/* 依赖，未安装时首次调用抛错
 *
 * 返回 `Promise<RateLimiter>`：Redis 实现需动态 import 模块，故为异步。
 */
export async function getRateLimiter(): Promise<RateLimiter> {
  if (singleton) return singleton

  if (env.RATE_LIMIT_DRIVER === "redis") {
    const { RedisRateLimiter } = await import("./redis-limiter")
    singleton = new RedisRateLimiter()
  } else {
    singleton = new MemoryRateLimiter()
  }
  return singleton
}

/**
 * 检查请求是否应被允许。
 *
 * 无论成功失败均累加计数（便于失败次数累计锁定）。
 *
 * **变更**：返回 `Promise<RateLimitResult>`，调用方需 `await`。
 */
export function rateLimit(params: RateLimitParams): Promise<RateLimitResult> {
  return getRateLimiter().then((limiter) => limiter.limit(params))
}

/**
 * 重置指定 key 的计数。
 *
 * 用于成功登录后清除失败计数等场景。
 *
 * **变更**：返回 `Promise<void>`，调用方需 `await`。
 */
export function resetRateLimit(key: string): Promise<void> {
  return getRateLimiter().then((limiter) => limiter.reset(key))
}
