import { timingSafeEqual } from 'crypto';
import {
  CanActivate,
  ExecutionContext,
  Injectable,
  UnauthorizedException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Reflector } from '@nestjs/core';
import { Request } from 'express';
import { IS_INTERNAL_KEY } from '../decorators/auth.decorators';

@Injectable()
export class InternalGuard implements CanActivate {
  constructor(
    private readonly config: ConfigService,
    private readonly reflector: Reflector,
  ) {}

  canActivate(ctx: ExecutionContext): boolean {
    const isInternal = this.reflector.getAllAndOverride<boolean>(IS_INTERNAL_KEY, [
      ctx.getHandler(),
      ctx.getClass(),
    ]);
    if (!isInternal) return true; // Not an internal route, skip this guard

    const req = ctx.switchToHttp().getRequest<Request>();
    const headerSecret = String(req.headers['x-cron-secret'] ?? '');
    const expected = this.config.get<string>('CRON_SECRET') ?? '';
    if (!expected) throw new UnauthorizedException('CRON_SECRET not configured');
    // Use constant-time comparison to prevent timing-based secret enumeration
    const aBytes = Buffer.from(headerSecret);
    const bBytes = Buffer.from(expected);
    const valid = aBytes.length === bBytes.length && timingSafeEqual(aBytes, bBytes);
    if (!valid) throw new UnauthorizedException('Invalid cron secret');
    return true;
  }
}
