/**
 * ╔═══════════════════════════════════════════════════════════════╗
 * ║  FeatureFlagGuard — Guard для проверки Feature Flags          ║
 * ╚═══════════════════════════════════════════════════════════════╝
 *
 * Как использовать:
 *
 *   // 1. На уровне контроллера — весь контроллер требует флаг
 *   @UseGuards(FeatureFlagGuard)
 *   @RequireFeature('HISTORIAN')
 *   @Controller('api/historian')
 *   export class HistorianController {}
 *
 *   // 2. На уровне отдельного роута
 *   @Get('trend')
 *   @RequireFeature('HISTORIAN')
 *   @UseGuards(FeatureFlagGuard)
 *   getTrend() {}
 *
 *   // 3. Несколько флагов (все должны быть включены)
 *   @RequireFeature('HISTORIAN', 'METRICS')
 *
 * Если флаг выключен — возвращает 503 Service Unavailable
 * с телом { error: "Feature HISTORIAN disabled", feature: "HISTORIAN" }
 * Фронтенд v6.4 обрабатывает это как "функция недоступна".
 */

import {
  Injectable, CanActivate, ExecutionContext,
  ServiceUnavailableException, SetMetadata,
} from '@nestjs/common';
import { Reflector }          from '@nestjs/core';
import { FeatureFlagsService } from '../../config/feature-flags.service';
import { IFeatureFlags }       from '../../config/feature-flags.config';

/** Ключ metadata для хранения требуемых флагов */
export const FEATURE_KEY = 'required_features';

/**
 * Декоратор @RequireFeature('FLAG_NAME', ...)
 * Применяется к контроллеру или методу.
 */
export const RequireFeature = (...flags: Array<keyof IFeatureFlags>) =>
  SetMetadata(FEATURE_KEY, flags);

@Injectable()
export class FeatureFlagGuard implements CanActivate {
  constructor(
    private readonly reflector: Reflector,
    private readonly features:  FeatureFlagsService,
  ) {}

  canActivate(ctx: ExecutionContext): boolean {
    // Читаем требуемые флаги из metadata метода или класса
    const required = this.reflector.getAllAndOverride<Array<keyof IFeatureFlags>>(
      FEATURE_KEY,
      [ctx.getHandler(), ctx.getClass()],
    );

    // Если декоратор не применён — пропускаем (Guard не мешает)
    if (!required || required.length === 0) return true;

    // Проверяем каждый требуемый флаг
    for (const flag of required) {
      if (!this.features.isEnabled(flag)) {
        throw new ServiceUnavailableException({
          error:   `Feature ${flag} disabled`,
          feature: flag,
          hint:    `Включите флаг через Admin → Feature Flags или PATCH /api/features`,
        });
      }
    }

    return true;
  }
}
