import {
  Injectable,
  ExecutionContext,
  UnauthorizedException,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport';
import { IS_PUBLIC_KEY } from '../decorators/public.decorator';
import { RedisService } from '../../redis/redis.service';
import { JwtPayload } from '../decorators/current-user.decorator';

/**
 * JwtAuthGuard - Globaler Guard fuer JWT-Authentifizierung.
 *
 * - Standardmaessig aktiv auf ALLEN Routen
 * - @Public() dekorierte Routen werden uebersprungen
 * - Prueft zusaetzlich ob der Token revoked wurde (Redis Blocklist)
 */
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  constructor(
    private readonly reflector: Reflector,
    private readonly redis: RedisService,
  ) {
    super();
  }

  async canActivate(context: ExecutionContext): Promise<boolean> {
    // @Public() Routen ueberspringen
    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);

    if (isPublic) {
      return true;
    }

    // JWT validieren (Passport Strategy)
    const canActivate = await super.canActivate(context);
    if (!canActivate) {
      return false;
    }

    // Token-Revocation pruefen (Redis Blocklist)
    const request = context.switchToHttp().getRequest();
    const user = request.user as JwtPayload;

    if (user?.jti) {
      const isBlocked = await this.redis.isTokenBlocked(user.jti);
      if (isBlocked) {
        throw new UnauthorizedException('Token wurde widerrufen');
      }
    }

    return true;
  }

  handleRequest<T>(err: Error | null, user: T, info: Error | undefined): T {
    if (err || !user) {
      throw err || new UnauthorizedException('Zugriff verweigert');
    }
    return user;
  }
}
