/**
 * Apply Shield runtime config from Gateway env (S2).
 * Operator guide: docs/GATEWAY-SHIELD-S2.md
 */

import type { Shield, ShieldConfig } from '@4runr/shield';
import { createLogger } from '@4runr/shared';

const logger = createLogger('Gateway:Shield');

export type ShieldMode = 'enforce' | 'monitor' | 'off';

export function buildShieldConfigFromEnv(shieldMode: ShieldMode): Partial<ShieldConfig> {
  return {
    enabled: shieldMode !== 'off',
    mode: shieldMode,
  };
}

/**
 * Sync @4runr/shield singleton with SENTINEL_SHIELD_MODE (and related defaults).
 */
export function applyShieldConfigFromEnv(
  shield: Shield,
  shieldMode: ShieldMode
): ShieldConfig {
  const partial = buildShieldConfigFromEnv(shieldMode);
  shield.updateConfig(partial);
  return shield.getConfig();
}

export type ShieldConfigValidation = {
  warnings: string[];
};

/**
 * Get Shield misconfiguration warnings (S5 fix: single source of truth)
 * Used by both startup validation and health checks
 */
export function getShieldMisconfigurationWarnings(
  config: ShieldConfig,
  openAiApiKey?: string
): string[] {
  const warnings: string[] = [];

  // Check for contradictory config
  if (config.enabled && config.mode === 'off') {
    warnings.push('Shield enabled flag true but mode is off');
  }

  // Check for rewrite without API key
  if (
    config.mode === 'enforce' &&
    config.hallucination.enabled &&
    config.hallucination.action === 'rewrite' &&
    config.rewrite?.enabled !== false &&
    !openAiApiKey?.trim()
  ) {
    warnings.push('Hallucination rewrite enabled but OPENAI_API_KEY not set');
  }

  return warnings;
}

/**
 * Startup checks so staging/prod are not surprised by demo-style defaults.
 */
export function validateShieldProductionConfig(
  config: ShieldConfig,
  options: { nodeEnv: string; openAiApiKey?: string }
): ShieldConfigValidation {
  const warnings: string[] = [];
  const isProduction = options.nodeEnv === 'production';

  if (!config.enabled || config.mode === 'off') {
    if (isProduction) {
      warnings.push(
        'Shield is disabled (SENTINEL_SHIELD_MODE=off): run input/output are not filtered on the queue path'
      );
    }
    return { warnings };
  }

  if (isProduction && config.mode === 'monitor') {
    warnings.push(
      'SENTINEL_SHIELD_MODE=monitor in production: injection/PII/hallucination are logged (flag) but not blocked or masked on the run path'
    );
  }

  // S5 fix: use shared helper for misconfig detection
  const misconfigWarnings = getShieldMisconfigurationWarnings(config, options.openAiApiKey);
  warnings.push(...misconfigWarnings.map(w => 
    w === 'Hallucination rewrite enabled but OPENAI_API_KEY not set'
      ? 'Shield hallucination rewrite is enabled but OPENAI_API_KEY is unset: rewrite will fail and runs will keep the original agent output'
      : w
  ));

  return { warnings };
}

export function logShieldConfigValidation(
  shield: Shield,
  shieldMode: ShieldMode,
  nodeEnv: string
): void {
  const config = shield.getConfig();
  const openAiApiKey = process.env['OPENAI_API_KEY'];
  const { warnings } = validateShieldProductionConfig(config, {
    nodeEnv,
    ...(openAiApiKey && { openAiApiKey }),
  });

  logger.info('Shield configuration applied', {
    shieldMode,
    enabled: shield.isEnabled(),
    mode: config.mode,
    detectors: {
      pii: config.pii.enabled,
      injection: config.injection.enabled,
      hallucination: config.hallucination.enabled,
    },
    injectionAction: config.injection.action,
    hallucinationAction: config.hallucination.action,
    rewriteEnabled: config.rewrite?.enabled ?? false,
  });

  if (warnings.length > 0) {
    logger.warn('Shield configuration warnings', { warnings });
  }
}
