// tests/reflection/evaluator.spec.ts
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { evaluateSignals, _resetEvaluatorForTests } from '@/lib/reflection/evaluator';
import { SIGNALS } from '@/lib/reflection/types';

/**
 * Reflection Evaluator Engine Tests
 *
 * Ensures the evaluator:
 * - Correctly classifies signals (NORMAL / WARNING / CRITICAL)
 * - Applies thresholds accurately
 * - Resets internal cache cleanly between runs
 * - Works predictably under fake timers
 */

describe('Reflection Evaluator Engine', () => {
  beforeEach(() => {
    vi.useRealTimers(); // 🔹 ensure fresh environment
    vi.useFakeTimers();
    vi.setSystemTime(0);
    _resetEvaluatorForTests?.();
  });

  afterEach(() => {
    vi.runOnlyPendingTimers();
    vi.useRealTimers();
    vi.restoreAllMocks();
  });

  // ---------------------------------------------------------
  // 1. Normal Signal Behavior
  // ---------------------------------------------------------
  it('should classify WINDOW_CHURN as NORMAL when below threshold', () => {
    const signals = {
      churnSignal: {
        type: SIGNALS.WINDOW_CHURN,
        value: 2.5,
        timestamp: 1000,
        metadata: { opens: 5, closes: 3, interval: 5000 },
      },
      focusSignal: {
        type: SIGNALS.FOCUS_STABILITY,
        value: 0.9,
        timestamp: 1000,
        metadata: { count: 8, interval: 5000 },
      },
    };

    const evaluations = evaluateSignals(signals);
    const churnEval = evaluations.find((e) => e.signal.type === SIGNALS.WINDOW_CHURN);
    expect(churnEval?.status).toBe('NORMAL');
  });

  // ---------------------------------------------------------
  // 2. Critical Threshold Detection
  // ---------------------------------------------------------
  it('should classify WINDOW_CHURN as CRITICAL when above threshold', () => {
    const signals = {
      churnSignal: {
        type: SIGNALS.WINDOW_CHURN,
        value: 5.2,
        timestamp: 2000,
        metadata: { opens: 21, closes: 0, interval: 5000 },
      },
      focusSignal: {
        type: SIGNALS.FOCUS_STABILITY,
        value: 0.2,
        timestamp: 2000,
        metadata: { count: 2, interval: 5000 },
      },
    };

    const evaluations = evaluateSignals(signals);
    const churnEval = evaluations.find((e) => e.signal.type === SIGNALS.WINDOW_CHURN);
    expect(churnEval?.status).toBe('CRITICAL');
    expect(churnEval?.slo?.threshold).toBeGreaterThan(0);
  });

  // ---------------------------------------------------------
  // 3. Focus Stability Interpretation
  // ---------------------------------------------------------
  it('should classify FOCUS_STABILITY as NORMAL when stable', () => {
    const signals = {
      churnSignal: {
        type: SIGNALS.WINDOW_CHURN,
        value: 1.5,
        timestamp: 3000,
        metadata: { opens: 2, closes: 1, interval: 5000 },
      },
      focusSignal: {
        type: SIGNALS.FOCUS_STABILITY,
        value: 0.85,
        timestamp: 3000,
        metadata: { count: 8, interval: 5000 },
      },
    };

    const evaluations = evaluateSignals(signals);
    const focusEval = evaluations.find((e) => e.signal.type === SIGNALS.FOCUS_STABILITY);
    expect(focusEval?.status).toBe('NORMAL');
  });

  it('should classify FOCUS_STABILITY as CRITICAL when focus drops drastically', () => {
    const signals = {
      churnSignal: {
        type: SIGNALS.WINDOW_CHURN,
        value: 0,
        timestamp: 4000,
        metadata: { opens: 0, closes: 0, interval: 5000 },
      },
      focusSignal: {
        type: SIGNALS.FOCUS_STABILITY,
        value: 0.1,
        timestamp: 4000,
        metadata: { count: 1, interval: 5000 },
      },
    };

    const evaluations = evaluateSignals(signals);
    const focusEval = evaluations.find((e) => e.signal.type === SIGNALS.FOCUS_STABILITY);
    expect(focusEval?.status).toBe('CRITICAL');
  });

  // ---------------------------------------------------------
  // 4. Mixed Case Evaluations
  // ---------------------------------------------------------
  it('should evaluate both signals simultaneously and return valid results', () => {
    const signals = {
      churnSignal: {
        type: SIGNALS.WINDOW_CHURN,
        value: 4.1,
        timestamp: 5000,
        metadata: { opens: 12, closes: 5, interval: 5000 },
      },
      focusSignal: {
        type: SIGNALS.FOCUS_STABILITY,
        value: 0.6,
        timestamp: 5000,
        metadata: { count: 3, interval: 5000 },
      },
    };

    const evaluations = evaluateSignals(signals);
    expect(evaluations.length).toBe(2);
    expect(evaluations.every((e) => ['NORMAL', 'CRITICAL', 'WARNING'].includes(e.status))).toBe(
      true
    );
  });

  // ---------------------------------------------------------
  // 5. Reset Behavior
  // ---------------------------------------------------------
  it('should reset internal evaluation cache correctly', () => {
    const signals = {
      churnSignal: {
        type: SIGNALS.WINDOW_CHURN,
        value: 3.5,
        timestamp: 6000,
        metadata: { opens: 10, closes: 8, interval: 5000 },
      },
      focusSignal: {
        type: SIGNALS.FOCUS_STABILITY,
        value: 0.7,
        timestamp: 6000,
        metadata: { count: 5, interval: 5000 },
      },
    };

    evaluateSignals(signals);
    _resetEvaluatorForTests();
    const newEval = evaluateSignals(signals);
    expect(newEval.length).toBe(2);
  });
});
