import { HttpStatus, Injectable } from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler';
import { AppException, ErrorCode } from '../../common/errors';

/**
 * Rate limits voice extraction per user rather than per IP.
 *
 * The default tracker keys on `req.ip`, which behind nginx means the whole deployment
 * shares one bucket unless `trust proxy` is set — and an abuser rotating IPs would bypass
 * it entirely. Since v1 ships with no plan gate, this is the only control on metered
 * vendor spend, so it has to key on something the client cannot change.
 *
 * Guard order matters: the controller's JwtAuthGuard runs before this method-level guard,
 * so `req.user` is populated by the time `getTracker` is called.
 */
@Injectable()
export class VoiceThrottlerGuard extends ThrottlerGuard {
  protected getTracker(req: Record<string, unknown>): Promise<string> {
    const user = req?.user as { id?: unknown } | undefined;
    if (typeof user?.id === 'string' && user.id) {
      return Promise.resolve(`voice:user:${user.id}`);
    }
    // Unauthenticated requests never reach here, but fall back rather than share a bucket.
    const ip = typeof req?.ip === 'string' ? req.ip : 'unknown';
    return Promise.resolve(`voice:ip:${ip}`);
  }

  /** Without this, ThrottlerException surfaces as INTERNAL_ERROR — there is no 429 fallback. */
  protected throwThrottlingException(): Promise<void> {
    throw new AppException(
      ErrorCode.VOICE_RATE_LIMITED,
      HttpStatus.TOO_MANY_REQUESTS,
    );
  }
}
