import fs from "node:fs";
import path from "node:path";
import { resolvePaperclipInstanceRoot } from "../home-paths.js";
import { sanitizeMemoryFact } from "./memory-sanitizer.js";

const MAX_FACTS = 50;

interface AssistantMemory {
  facts: string[];
  updatedAt: string | null;
}

function resolveMemoryPath(companyId: string): string {
  return path.resolve(
    resolvePaperclipInstanceRoot(),
    "data",
    "assistant-memory",
    `${companyId}.json`,
  );
}

function readMemory(companyId: string): AssistantMemory {
  const filePath = resolveMemoryPath(companyId);
  try {
    const raw = fs.readFileSync(filePath, "utf-8");
    const parsed = JSON.parse(raw) as unknown;
    if (
      typeof parsed === "object" &&
      parsed !== null &&
      !Array.isArray(parsed) &&
      Array.isArray((parsed as Record<string, unknown>).facts) &&
      ((parsed as Record<string, unknown>).facts as unknown[]).every((f) => typeof f === "string")
    ) {
      const p = parsed as Record<string, unknown>;
      const updatedAt = typeof p.updatedAt === "string" ? p.updatedAt : null;
      return { facts: p.facts as string[], updatedAt };
    }
  } catch {
    // File does not exist or is corrupt — return default
  }
  return { facts: [], updatedAt: null };
}

function writeMemory(companyId: string, memory: AssistantMemory): void {
  const filePath = resolveMemoryPath(companyId);
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
  fs.writeFileSync(filePath, JSON.stringify(memory, null, 2), "utf-8");
}

export function assistantMemoryService() {
  async function get(companyId: string): Promise<AssistantMemory> {
    return readMemory(companyId);
  }

  async function append(companyId: string, rawFact: string): Promise<AssistantMemory> {
    const sanitized = sanitizeMemoryFact(rawFact);

    const current = readMemory(companyId);
    const facts = [...current.facts, sanitized];

    // FIFO eviction: cap at MAX_FACTS
    while (facts.length > MAX_FACTS) {
      facts.shift();
    }

    const updated: AssistantMemory = {
      facts,
      updatedAt: new Date().toISOString(),
    };
    writeMemory(companyId, updated);
    return updated;
  }

  async function clear(companyId: string): Promise<void> {
    writeMemory(companyId, { facts: [], updatedAt: null });
  }

  return { get, append, clear };
}
