import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
import { Reflector } from "@nestjs/core";
import { REQUIERE_FLAG_METADATA, RequiereFlagOpciones } from "./requiere-flag.decorator";
import { TallerParametroClave } from "./taller-parametros.catalogo";
import { TallerParametrosService } from "./taller-parametros.service";

const METODOS_DE_LECTURA = new Set(["GET", "HEAD", "OPTIONS"]);

// Tiene que registrarse DESPUES de TenantGuard / PublicTenantGuard: la lectura
// del parametro necesita el contexto de tenant que esos guards pueblan. Sin
// metadata es un no-op, asi se puede dejar en el @UseGuards de la clase aunque
// solo algunos handlers esten gateados.
@Injectable()
export class RequiereFlagGuard implements CanActivate {
  constructor(
    private readonly reflector: Reflector,
    private readonly tallerParametros: TallerParametrosService,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const meta = this.reflector.getAllAndOverride<
      ({ clave: TallerParametroClave } & RequiereFlagOpciones) | undefined
    >(REQUIERE_FLAG_METADATA, [context.getHandler(), context.getClass()]);
    if (!meta) return true;

    if (meta.soloEscritura) {
      const metodo = String(context.switchToHttp().getRequest()?.method ?? "").toUpperCase();
      if (METODOS_DE_LECTURA.has(metodo)) return true;
    }

    await this.tallerParametros.exigirHabilitado(meta.clave, {
      comoNoEncontrado: meta.comoNoEncontrado,
    });
    return true;
  }
}
