/**
 * MemoryStore — common surface for chat's long-term memory.
 *
 * Two implementations:
 *  - TemperClient (lib/chat/temper.ts): HTTP-backed, with semantic +
 *    graph search via Graphiti.
 *  - LocalMemoryStore (lib/chat/local-memory.ts): SQLite-backed
 *    fallback when Temper isn't configured. Same block API; search is
 *    keyword LIKE over stored block values + episode content.
 *
 * The factory `getMemoryStore()` picks one based on settings:
 *   temperUrl + temperKey present → Temper; otherwise → Local.
 *
 * Both report `enabled = true` once they have somewhere to read/write,
 * so the chat loop registers the memory_* tools either way.
 */

import { loadSettings } from '../settings';
import { TemperClient } from './temper';
import { LocalMemoryStore } from './local-memory';
import type { EpisodeInput, MemoryBlock, SearchHit } from './temper';

export type { EpisodeInput, MemoryBlock, SearchHit } from './temper';

export interface MemoryStore {
  readonly enabled: boolean;
  readonly currentNamespace: string;
  readonly kind: 'temper' | 'local';

  search(query: string, limit?: number): Promise<SearchHit[]>;
  writeEpisode(ep: EpisodeInput, asyncExtract?: boolean): Promise<boolean>;
  listBlocks(opts?: { pinned?: boolean; scope?: 'own' | 'global' | 'both' }): Promise<MemoryBlock[]>;
  getBlock(key: string, scope?: 'own' | 'global'): Promise<MemoryBlock | null>;
  putBlock(
    key: string,
    value: unknown,
    extras?: { pinned?: boolean; priority?: number; description?: string; scope?: 'own' | 'global' },
  ): Promise<boolean>;
  ping(): Promise<{ ok: boolean; message: string; pinned: number }>;
}

/**
 * Pick the active memory backend.
 *
 * Resolution order:
 *   - settings.memoryBackend === 'local'  → always LocalMemoryStore.
 *   - settings.memoryBackend === 'temper' → always TemperClient (even if
 *     credentials are missing — caller will see `enabled = false`).
 *   - 'auto' (default): Temper if both URL+key are set, else Local.
 *
 * Callers should NOT cache the result across settings edits — the
 * picker is cheap.
 */
export function getMemoryStore(): MemoryStore {
  const s = loadSettings();
  const url = (s.temperUrl || '').trim();
  const key = (s.temperKey || '').trim();
  const mode = s.memoryBackend || 'auto';

  if (mode === 'local') return new LocalMemoryStore();
  if (mode === 'temper') {
    return makeTemperWrapper(new TemperClient(url, key, s.temperNamespace || ''));
  }
  // auto
  if (url && key) {
    return makeTemperWrapper(new TemperClient(url, key, s.temperNamespace || ''));
  }
  return new LocalMemoryStore();
}

function makeTemperWrapper(c: TemperClient): MemoryStore {
  return {
    kind: 'temper',
    get enabled() {
      return c.enabled;
    },
    get currentNamespace() {
      return c.currentNamespace;
    },
    search: (q, n) => c.search(q, n),
    writeEpisode: (ep, a) => c.writeEpisode(ep, a),
    listBlocks: (opts) => c.listBlocks(opts ?? {}),
    getBlock: (k, scope) => c.getBlock(k, scope),
    putBlock: (k, v, extras) => c.putBlock(k, v, extras),
    ping: () => c.ping(),
  };
}
