/**
 * agent-memory-gate.mjs — dependency-free ESM gate helper for hooks.
 *
 * Re-implements the SAME tri-state opt-in contract as
 * packages/core/src/memory/gate.ts inline. Hooks are standalone .mjs/.js files
 * distributed to operators' ~/.claude/scripts/hooks/ and cannot import
 * @olam/core at runtime — this module is imported by the agentmemory hooks.
 *
 * # Modes — KEEP IN SYNC WITH gate.ts
 *
 *   off       — no recall, no capture (default).
 *   readonly  — recall allowed; capture (write) NOT. Human-driven dev.
 *   editor    — recall AND capture allowed. Fully agentic dev.
 *
 * # Precedence (fail-closed)
 *
 *   1. env OLAM_AGENT_MEMORY — AUTHORITATIVE when set + non-empty
 *      (trimmed, case-insensitive):
 *        'readonly' → readonly · 'editor' → editor
 *        '1'|'true'|'on' → readonly  (legacy "on" → least-privilege)
 *        any other value → off
 *   2. flag file at $OLAM_HOME/agent-memory-enabled (or ~/.olam/…) when env unset:
 *        'readonly' → readonly · 'editor' → editor
 *        'true'|'1' → readonly  (legacy enable wrote TRUE)
 *        anything else / absent / read error → off
 *   3. default → off
 *
 * FAIL-CLOSED: any error → off. Legacy truthy values resolve to READONLY, never
 * EDITOR — write access must be opted into explicitly.
 *
 * Two implementations, one contract. If you change this logic, update
 * packages/core/src/memory/gate.ts to match (and vice-versa).
 */

import { readFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { join } from 'node:path';

/** @typedef {'off' | 'readonly' | 'editor'} AgentMemoryMode */

const ENV_MODE = new Map([
  ['readonly', 'readonly'],
  ['editor', 'editor'],
  ['1', 'readonly'],
  ['true', 'readonly'],
  ['on', 'readonly'],
]);
const FILE_MODE = new Map([
  ['readonly', 'readonly'],
  ['editor', 'editor'],
  ['true', 'readonly'],
  ['1', 'readonly'],
]);

/**
 * Resolve the agent-memory-enabled flag file path.
 * Mirrors agentMemoryEnabledPath() from @olam/core/src/paths/olam-paths.ts.
 * Re-reads process.env on every call (direnv-safe).
 */
function agentMemoryEnabledPath() {
  const fromEnv = process.env['OLAM_HOME'];
  const olamHome = (fromEnv && fromEnv.length > 0) ? fromEnv : join(homedir(), '.olam');
  return join(olamHome, 'agent-memory-enabled');
}

/**
 * Resolve the agent-memory access mode. Synchronous. Never throws — any I/O
 * error or unrecognised value → 'off' (fail-closed).
 *
 * @returns {AgentMemoryMode}
 */
export function agentMemoryMode() {
  const envVal = process.env['OLAM_AGENT_MEMORY'];
  if (envVal !== undefined && envVal.length > 0) {
    return ENV_MODE.get(envVal.trim().toLowerCase()) ?? 'off';
  }

  try {
    const raw = readFileSync(agentMemoryEnabledPath(), 'utf8').trim().toLowerCase();
    return FILE_MODE.get(raw) ?? 'off';
  } catch {
    return 'off';
  }
}

/**
 * Returns true iff agent-memory RECALL should run (readonly or editor).
 * Compatibility shim for existing read-path call sites.
 *
 * @returns {boolean}
 */
export function isAgentMemoryEnabled() {
  return agentMemoryMode() !== 'off';
}

/**
 * Returns true iff agent-memory CAPTURE (write) is permitted — editor only.
 *
 * @returns {boolean}
 */
export function canWriteAgentMemory() {
  return agentMemoryMode() === 'editor';
}
