// lib/reflection/evaluator.ts

import { isVerbose } from './flags';
import { SIGNALS, type Signal, type SignalEvaluator, type EvaluationResult } from './types';

// ========================================
//   Configuration (SLOs)
// ========================================

const EVALUATORS: Record<string, SignalEvaluator & { direction?: 'higher' | 'lower' }> = {
  [SIGNALS.WINDOW_CHURN]: {
    signal: SIGNALS.WINDOW_CHURN,
    // higher churn is worse
    direction: 'higher',
    slos: [
      { threshold: 4, status: 'CRITICAL' }, // > 4 events/sec
      { threshold: 3, status: 'WARNING' }, // > 3 events/sec
    ],
  },
  [SIGNALS.FOCUS_STABILITY]: {
    signal: SIGNALS.FOCUS_STABILITY,
    // lower stability is worse (0..1 range)
    direction: 'lower',
    slos: [
      { threshold: 0.4, status: 'CRITICAL' }, // < 0.4 is critical
      { threshold: 0.6, status: 'WARNING' }, // < 0.6 is warning
    ],
  },
  [SIGNALS.LATENCY_SUMMARY]: {
    signal: SIGNALS.LATENCY_SUMMARY,
    slos: [],
  },
  [SIGNALS.IDLE_RATIO]: {
    signal: SIGNALS.IDLE_RATIO,
    slos: [],
  },
  [SIGNALS.WINDOW_LIFETIME]: {
    signal: SIGNALS.WINDOW_LIFETIME,
    slos: [],
  },
};

// ========================================
//   Public API
// ========================================

/**
 * Evaluates a given signal against its configured SLOs.
 * @param signal The signal to evaluate.
 * @returns An EvaluationResult object.
 */
export function evaluateSignal(signal: Signal): EvaluationResult {
  const evaluator = EVALUATORS[signal.type as string];
  if (!evaluator || evaluator.slos.length === 0) {
    return {
      signal,
      status: 'NORMAL',
      slo: null,
      timestamp: performance.now(),
    };
  }

  // Iterate through SLOs (ordered most to least critical). Honor direction.
  const direction = (evaluator as any).direction ?? 'higher';
  for (const slo of evaluator.slos) {
    const breached =
      direction === 'higher' ? signal.value > slo.threshold : signal.value < slo.threshold;
    if (breached) {
      const result: EvaluationResult = {
        signal,
        status: slo.status,
        slo,
        timestamp: performance.now(),
      };

      if (isVerbose()) {
        console.log(
          `[Reflection/Evaluator] Signal evaluated: ${signal.type} is ${slo.status}`,
          result
        );
      }
      return result;
    }
  }

  // If no threshold was breached, the status is normal
  const result: EvaluationResult = {
    signal,
    status: 'NORMAL',
    slo: null,
    timestamp: performance.now(),
  };

  if (isVerbose()) {
    console.log(`[Reflection/Evaluator] Signal evaluated: ${signal.type} is NORMAL`, result);
  }

  return result;
}

/**
 * Convenience: evaluate an array or object of signals and return EvaluationResult[]
 */
export function evaluateSignals(signals: any): EvaluationResult[] {
  const list: Signal[] = [];
  if (Array.isArray(signals)) {
    for (const s of signals) list.push(s);
  } else if (signals && typeof signals === 'object') {
    for (const key of Object.keys(signals)) {
      const val = (signals as any)[key];
      if (val && typeof val === 'object' && 'type' in val) list.push(val as Signal);
    }
  }
  return list.map((s) => evaluateSignal(s));
}

/**
 * Test helper (no-op for now) to reset evaluator-internal state.
 */
export function _resetEvaluatorForTests(): void {
  // reserved for future internal caches
}
