// lib/reflection/memory.ts

import type { ReflectionMemoryEntry, ReflectionSnapshot } from './types';

// ========================================
//   Configuration
// ========================================

const MEMORY_CAPACITY = 100; // Maximum number of entries to keep in memory

// ========================================
//   Module State
// ========================================

const memoryBuffer: ReflectionMemoryEntry[] = [];
let currentSequence = 0;
let head = 0; // Pointer to the next slot to write to

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

/**
 * Adds a new entry to the reflection memory.
 * Overwrites the oldest entry if capacity is reached.
 * @param entry The partial memory entry to add.
 */
export function addToMemory(entry: Omit<ReflectionMemoryEntry, 'sequence' | 'timestamp'>): void {
  const newEntry: ReflectionMemoryEntry = {
    ...entry,
    sequence: ++currentSequence,
    timestamp: performance.now(),
  };

  memoryBuffer[head] = newEntry;
  head = (head + 1) % MEMORY_CAPACITY;
}

/**
 * Returns a copy of all entries currently in the reflection memory.
 * The entries are not guaranteed to be in chronological order.
 * @returns An array of memory entries.
 */
export function getMemorySnapshot(): Readonly<ReflectionMemoryEntry[]> {
  return [...memoryBuffer];
}

/**
 * Returns the most recent `n` entries from memory, ordered from newest to oldest.
 * @param count The number of recent entries to retrieve.
 * @returns An array of the most recent memory entries.
 */
export function getRecentMemory(count: number): Readonly<ReflectionMemoryEntry[]> {
  const snapshot = [...memoryBuffer];
  // Sort by sequence number in descending order to get the newest first
  snapshot.sort((a, b) => b.sequence - a.sequence);
  return snapshot.slice(0, count);
}

/**
 * Resets the reflection memory to its initial state.
 * (For testing purposes)
 */
export function _resetMemory(): void {
  memoryBuffer.length = 0;
  currentSequence = 0;
  head = 0;
}

// ------------------------------------------------------------------
// Backwards compatible API expected by tests
// ------------------------------------------------------------------

const snapshotBuffer: ReflectionSnapshot[] = [];

export function storeReflectionSnapshot(snapshot: ReflectionSnapshot): void {
  snapshotBuffer.push(snapshot);
}

export function getReflectionHistory(): ReflectionSnapshot[] {
  return [...snapshotBuffer].sort((a, b) => a.timestamp - b.timestamp);
}

export function getLastReflection(): ReflectionSnapshot | null {
  if (snapshotBuffer.length === 0) return null;
  return snapshotBuffer[snapshotBuffer.length - 1];
}

export function clearReflectionMemory(): void {
  snapshotBuffer.length = 0;
}

export function _resetMemoryForTests(): void {
  _resetMemory();
  clearReflectionMemory();
}

/**
 * Tests expect introspection to expose a "latest signals" buffer.
 */
const latestSignals: any[] = [];
export function _pushLatestSignals(signals: any[]) {
  latestSignals.push(...signals);
  // keep small
  if (latestSignals.length > 100) latestSignals.splice(0, latestSignals.length - 100);
}

export function getLatestSignals(): any[] {
  return [...latestSignals];
}
