/**
 * Memory File Reader
 *
 * Reads current memory state for context injection:
 * - Load memory files for Buba's context window
 * - Filter relevant patterns by task type
 * - Surface recent similar feedback
 */

import * as fs from "node:fs";
import * as path from "node:path";

// ═══════════════════════════════════════════════════════════════
// MEMORY FILE READING
// ═══════════════════════════════════════════════════════════════

export interface MemoryState {
  feedbackPatterns: string | null;
  qualityStandards: string | null;
  jakePreferences: string | null;
  improvementLog: string | null;
}

/**
 * Load all memory files into a combined state.
 */
export function loadMemoryState(memoryDir: string): MemoryState {
  return {
    feedbackPatterns: readMemoryFile(memoryDir, "feedback-patterns.md"),
    qualityStandards: readMemoryFile(memoryDir, "quality-standards.md"),
    jakePreferences: readMemoryFile(memoryDir, "jake-preferences.md"),
    improvementLog: readMemoryFile(memoryDir, "improvement-log.md"),
  };
}

/**
 * Read a single memory file. Returns null if it doesn't exist.
 */
export function readMemoryFile(
  memoryDir: string,
  filename: string
): string | null {
  const filePath = path.join(memoryDir, filename);
  if (!fs.existsSync(filePath)) return null;
  return fs.readFileSync(filePath, "utf-8");
}

/**
 * Check if a memory file exists and when it was last updated.
 */
export function getMemoryFileInfo(
  memoryDir: string,
  filename: string
): { exists: boolean; lastModified: Date | null; sizeBytes: number } {
  const filePath = path.join(memoryDir, filename);
  if (!fs.existsSync(filePath)) {
    return { exists: false, lastModified: null, sizeBytes: 0 };
  }
  const stats = fs.statSync(filePath);
  return {
    exists: true,
    lastModified: stats.mtime,
    sizeBytes: stats.size,
  };
}

/**
 * Get a summary of all memory files for context injection.
 */
export function getMemorySummary(memoryDir: string): {
  files: Array<{
    name: string;
    exists: boolean;
    lastModified: Date | null;
    sizeBytes: number;
  }>;
  totalSizeBytes: number;
} {
  const fileNames = [
    "feedback-patterns.md",
    "quality-standards.md",
    "jake-preferences.md",
    "improvement-log.md",
  ];

  const files = fileNames.map((name) => ({
    name,
    ...getMemoryFileInfo(memoryDir, name),
  }));

  return {
    files,
    totalSizeBytes: files.reduce((sum, f) => sum + f.sizeBytes, 0),
  };
}

// ═══════════════════════════════════════════════════════════════
// CONTEXTUAL MEMORY RETRIEVAL
// ═══════════════════════════════════════════════════════════════

export interface RelevantMemory {
  /** Always loaded (small, high-value) */
  preferences: string | null;
  standards: string | null;
  /** Task-type specific patterns */
  relevantPatterns: string[];
  /** Recent improvement log entries */
  recentImprovements: string | null;
}

/**
 * Get relevant memory context for a specific task type.
 *
 * This filters memory content to only include information
 * relevant to the current task, keeping the context window lean.
 */
export function getRelevantMemory(
  memoryDir: string,
  context: {
    serverType?: string;
    pipelineStage?: string;
    dimensions?: string[];
  }
): RelevantMemory {
  const state = loadMemoryState(memoryDir);

  // Always include preferences and standards
  const preferences = state.jakePreferences;
  const standards = state.qualityStandards;

  // Filter patterns by relevance
  const relevantPatterns: string[] = [];
  if (state.feedbackPatterns) {
    const lines = state.feedbackPatterns.split("\n");
    for (const line of lines) {
      const lower = line.toLowerCase();
      // Include if it mentions the server type or relevant dimensions
      if (context.serverType && lower.includes(context.serverType.toLowerCase())) {
        relevantPatterns.push(line.trim());
      }
      if (context.dimensions) {
        for (const dim of context.dimensions) {
          if (lower.includes(dim.toLowerCase().replace("_", " "))) {
            relevantPatterns.push(line.trim());
            break;
          }
        }
      }
    }
  }

  // Get recent improvement log (last 5 entries)
  let recentImprovements: string | null = null;
  if (state.improvementLog) {
    const sections = state.improvementLog.split(/^## /m);
    // Take first 5 date sections (most recent are at the top)
    const recent = sections.slice(1, 6);
    if (recent.length > 0) {
      recentImprovements = recent.map((s) => `## ${s}`).join("");
    }
  }

  return {
    preferences,
    standards,
    relevantPatterns: [...new Set(relevantPatterns)],
    recentImprovements,
  };
}
