// tests/reflection/memory.spec.ts
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import {
  storeReflectionSnapshot,
  getReflectionHistory,
  getLastReflection,
  clearReflectionMemory,
  _resetMemoryForTests,
} from '@/lib/reflection/memory';
import type { ReflectionSnapshot } from '@/lib/reflection/types';

/**
 * Reflection Memory Engine Tests
 *
 * Ensures:
 * - Proper storage & retrieval of snapshots
 * - Temporal ordering of entries
 * - Last reflection retrieval
 * - Clear & reset behavior
 * - Handles identical timestamps safely
 */

describe('Reflection Memory Engine', () => {
  beforeEach(() => {
    vi.useRealTimers();
    vi.useFakeTimers();
    vi.setSystemTime(0);
    _resetMemoryForTests?.();
  });

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

  // ---------------------------------------------------------
  // 1. Storage & Retrieval
  // ---------------------------------------------------------
  it('should store and retrieve reflection snapshots in order', () => {
    const snap1: ReflectionSnapshot = {
      timestamp: 1000,
      evaluationCount: 2,
      appliedDecisions: ['THROTTLE_WINDOWS'],
      metrics: { churn: 3.2, focus: 0.9 },
    };

    const snap2: ReflectionSnapshot = {
      timestamp: 2000,
      evaluationCount: 3,
      appliedDecisions: ['ADJUST_PREFETCH'],
      metrics: { churn: 4.5, focus: 0.7 },
    };

    storeReflectionSnapshot(snap1);
    storeReflectionSnapshot(snap2);

    const history = getReflectionHistory();
    expect(history.length).toBe(2);
    expect(history[0].timestamp).toBeLessThan(history[1].timestamp);
  });

  // ---------------------------------------------------------
  // 2. Retrieve Last Reflection
  // ---------------------------------------------------------
  it('should return the last stored reflection snapshot', () => {
    const snap: ReflectionSnapshot = {
      timestamp: 3000,
      evaluationCount: 1,
      appliedDecisions: ['TUNE_FOCUS_TIMEOUT'],
      metrics: { churn: 1.1, focus: 0.95 },
    };

    storeReflectionSnapshot(snap);
    const last = getLastReflection();

    expect(last).not.toBeNull();
    expect(last?.appliedDecisions).toContain('TUNE_FOCUS_TIMEOUT');
    expect(last?.metrics.focus).toBeCloseTo(0.95);
  });

  // ---------------------------------------------------------
  // 3. Clearing Memory
  // ---------------------------------------------------------
  it('should clear all stored reflections', () => {
    storeReflectionSnapshot({
      timestamp: 4000,
      evaluationCount: 2,
      appliedDecisions: ['DEFER_ANIMATIONS'],
      metrics: { churn: 2.2, focus: 0.8 },
    });

    const before = getReflectionHistory();
    expect(before.length).toBe(1);

    clearReflectionMemory();
    const after = getReflectionHistory();
    expect(after.length).toBe(0);
  });

  // ---------------------------------------------------------
  // 4. Temporal Consistency
  // ---------------------------------------------------------
  it('should always return snapshots ordered by timestamp', () => {
    const snapA: ReflectionSnapshot = {
      timestamp: 7000,
      evaluationCount: 2,
      appliedDecisions: ['THROTTLE_WINDOWS'],
      metrics: { churn: 3.1, focus: 0.9 },
    };

    const snapB: ReflectionSnapshot = {
      timestamp: 5000,
      evaluationCount: 1,
      appliedDecisions: ['ADJUST_PREFETCH'],
      metrics: { churn: 2.9, focus: 0.7 },
    };

    storeReflectionSnapshot(snapA);
    storeReflectionSnapshot(snapB);

    const history = getReflectionHistory();
    expect(history[0].timestamp).toBeLessThanOrEqual(history[1].timestamp);
  });

  // ---------------------------------------------------------
  // 5. Identical Timestamp Handling
  // ---------------------------------------------------------
  it('should handle snapshots with identical timestamps gracefully', () => {
    const snap1: ReflectionSnapshot = {
      timestamp: 9000,
      evaluationCount: 1,
      appliedDecisions: ['A'],
      metrics: { churn: 1.0, focus: 0.8 },
    };
    const snap2: ReflectionSnapshot = {
      timestamp: 9000,
      evaluationCount: 2,
      appliedDecisions: ['B'],
      metrics: { churn: 2.0, focus: 0.9 },
    };

    storeReflectionSnapshot(snap1);
    storeReflectionSnapshot(snap2);

    const history = getReflectionHistory();
    expect(history.length).toBe(2);
    expect(history[0].timestamp).toBe(history[1].timestamp);
  });

  // ---------------------------------------------------------
  // 6. Reset Internal Memory
  // ---------------------------------------------------------
  it('should reset internal state correctly between tests', () => {
    storeReflectionSnapshot({
      timestamp: 9500,
      evaluationCount: 3,
      appliedDecisions: ['THROTTLE_WINDOWS'],
      metrics: { churn: 4.0, focus: 0.6 },
    });

    _resetMemoryForTests?.();
    const history = getReflectionHistory();
    expect(history.length).toBe(0);
  });
});
