import {
  init_ids,
  newId
} from "./chunk-F4WUVOLE.js";
import {
  init_clock,
  nowMs,
  toIso
} from "./chunk-HFDLUBWN.js";
import {
  getDrizzle,
  init_drizzle
} from "./chunk-RII4M3J2.js";
import {
  schema_exports
} from "./chunk-DDJOPRB7.js";

// src/db/memory.ts
init_drizzle();
init_ids();
init_clock();
import { createHash } from "crypto";
import { eq, and, asc, desc, like, or, sql, lt } from "drizzle-orm";
function hydrateStore(row) {
  return {
    id: row.id,
    name: row.name,
    description: row.description,
    agent_id: row.agent_id,
    archived_at: row.archived_at ? toIso(row.archived_at) : null,
    created_at: toIso(row.created_at),
    updated_at: toIso(row.updated_at)
  };
}
function hydrateVersion(row) {
  const v = {
    type: "memory_version",
    id: row.id,
    memory_store_id: row.store_id,
    memory_id: row.memory_id,
    path: row.path,
    operation: row.operation,
    created_at: toIso(row.created_at)
  };
  if (row.content != null) v.content = row.content;
  if (row.content_sha256 != null) v.content_sha256 = row.content_sha256;
  if (row.session_id != null) v.session_id = row.session_id;
  if (row.redacted_at != null) v.redacted_at = toIso(row.redacted_at);
  return v;
}
function hydrateMemory(row) {
  return {
    id: row.id,
    store_id: row.store_id,
    path: row.path,
    content: row.content,
    content_sha256: row.content_sha256,
    created_at: toIso(row.created_at),
    updated_at: toIso(row.updated_at)
  };
}
function sha256(content) {
  return createHash("sha256").update(content, "utf8").digest("hex");
}
function createMemoryStore(input) {
  const db = getDrizzle();
  const id = newId("memstore");
  const now = nowMs();
  db.insert(schema_exports.memoryStores).values({
    id,
    name: input.name,
    description: input.description ?? null,
    agent_id: input.agent_id ?? null,
    created_at: now,
    updated_at: now
  }).run();
  return getMemoryStore(id);
}
function getMemoryStore(id) {
  const db = getDrizzle();
  const row = db.select().from(schema_exports.memoryStores).where(eq(schema_exports.memoryStores.id, id)).get();
  return row ? hydrateStore(row) : null;
}
function listMemoryStores(opts = {}) {
  const db = getDrizzle();
  if (opts.tenantFilter != null) {
    if (opts.agent_id) {
      const rows3 = db.all(
        sql`SELECT ms.* FROM memory_stores ms LEFT JOIN agents a ON a.id = ms.agent_id WHERE ms.agent_id = ${opts.agent_id} AND a.tenant_id = ${opts.tenantFilter} ORDER BY ms.created_at DESC`
      );
      return rows3.map(hydrateStore);
    }
    const rows2 = db.all(
      sql`SELECT ms.* FROM memory_stores ms LEFT JOIN agents a ON a.id = ms.agent_id WHERE a.tenant_id = ${opts.tenantFilter} ORDER BY ms.created_at DESC`
    );
    return rows2.map(hydrateStore);
  }
  if (opts.agent_id) {
    const rows2 = db.select().from(schema_exports.memoryStores).where(eq(schema_exports.memoryStores.agent_id, opts.agent_id)).orderBy(desc(schema_exports.memoryStores.created_at)).all();
    return rows2.map(hydrateStore);
  }
  const rows = db.select().from(schema_exports.memoryStores).orderBy(desc(schema_exports.memoryStores.created_at)).all();
  return rows.map(hydrateStore);
}
function deleteMemoryStore(id) {
  const db = getDrizzle();
  const res = db.delete(schema_exports.memoryStores).where(eq(schema_exports.memoryStores.id, id)).run();
  return res.changes > 0;
}
function createOrUpsertMemory(storeId, path, content, sessionId) {
  const db = getDrizzle();
  const hash = sha256(content);
  const now = nowMs();
  const id = newId("mem");
  const existing = getMemoryByPath(storeId, path);
  const isUpdate = !!existing;
  db.insert(schema_exports.memories).values({
    id,
    store_id: storeId,
    path,
    content,
    content_sha256: hash,
    created_at: now,
    updated_at: now
  }).onConflictDoUpdate({
    target: [schema_exports.memories.store_id, schema_exports.memories.path],
    set: {
      content,
      content_sha256: hash,
      updated_at: now
    }
  }).run();
  const memory = getMemoryByPath(storeId, path);
  createMemoryVersion({
    storeId,
    memoryId: memory.id,
    operation: isUpdate ? "update" : "create",
    path,
    content,
    contentSha256: hash,
    sessionId
  });
  return memory;
}
function getMemory(id) {
  const db = getDrizzle();
  const row = db.select().from(schema_exports.memories).where(eq(schema_exports.memories.id, id)).get();
  return row ? hydrateMemory(row) : null;
}
function getMemoryByPath(storeId, path) {
  const db = getDrizzle();
  const row = db.select().from(schema_exports.memories).where(and(eq(schema_exports.memories.store_id, storeId), eq(schema_exports.memories.path, path))).get();
  return row ? hydrateMemory(row) : null;
}
function listMemories(storeId) {
  const db = getDrizzle();
  const rows = db.select().from(schema_exports.memories).where(eq(schema_exports.memories.store_id, storeId)).orderBy(asc(schema_exports.memories.path)).all();
  return rows.map(hydrateMemory);
}
function searchMemories(storeId, query) {
  const db = getDrizzle();
  const escaped = query.replace(/%/g, "\\%").replace(/_/g, "\\_");
  const pattern = `%${escaped}%`;
  const rows = db.select().from(schema_exports.memories).where(
    and(
      eq(schema_exports.memories.store_id, storeId),
      or(
        like(schema_exports.memories.path, pattern),
        like(schema_exports.memories.content, pattern)
      )
    )
  ).orderBy(asc(schema_exports.memories.path)).all();
  return rows.map(hydrateMemory);
}
function updateMemory(id, content, preconditionSha256, sessionId) {
  const db = getDrizzle();
  const existing = getMemory(id);
  if (!existing) return { memory: null, conflict: false };
  if (preconditionSha256 && existing.content_sha256 !== preconditionSha256) {
    return { memory: null, conflict: true };
  }
  const hash = sha256(content);
  const now = nowMs();
  db.update(schema_exports.memories).set({ content, content_sha256: hash, updated_at: now }).where(eq(schema_exports.memories.id, id)).run();
  const memory = getMemory(id);
  createMemoryVersion({
    storeId: existing.store_id,
    memoryId: id,
    operation: "update",
    path: existing.path,
    content,
    contentSha256: hash,
    sessionId
  });
  return { memory, conflict: false };
}
function deleteMemory(id, sessionId) {
  const db = getDrizzle();
  const existing = getMemory(id);
  const res = db.delete(schema_exports.memories).where(eq(schema_exports.memories.id, id)).run();
  if (res.changes > 0 && existing) {
    createMemoryVersion({
      storeId: existing.store_id,
      memoryId: id,
      operation: "delete",
      path: existing.path,
      sessionId
    });
  }
  return res.changes > 0;
}
function createMemoryVersion(opts) {
  const db = getDrizzle();
  const id = newId("memver");
  const now = nowMs();
  db.insert(schema_exports.memoryVersions).values({
    id,
    store_id: opts.storeId,
    memory_id: opts.memoryId,
    operation: opts.operation,
    path: opts.path,
    content: opts.content ?? null,
    content_sha256: opts.contentSha256 ?? null,
    session_id: opts.sessionId ?? null,
    created_at: now
  }).run();
  return id;
}
function listMemoryVersions(storeId, opts) {
  const db = getDrizzle();
  const limit = opts?.limit ?? 100;
  const conditions = [eq(schema_exports.memoryVersions.store_id, storeId)];
  if (opts?.memoryId) {
    conditions.push(eq(schema_exports.memoryVersions.memory_id, opts.memoryId));
  }
  if (opts?.cursor) {
    conditions.push(lt(schema_exports.memoryVersions.id, opts.cursor));
  }
  const rows = db.select().from(schema_exports.memoryVersions).where(and(...conditions)).orderBy(desc(schema_exports.memoryVersions.created_at), desc(schema_exports.memoryVersions.id)).limit(limit).all();
  return rows.map(hydrateVersion);
}
function getMemoryVersion(storeId, versionId) {
  const db = getDrizzle();
  const row = db.select().from(schema_exports.memoryVersions).where(
    and(
      eq(schema_exports.memoryVersions.store_id, storeId),
      eq(schema_exports.memoryVersions.id, versionId)
    )
  ).get();
  return row ? hydrateVersion(row) : void 0;
}
function updateMemoryStore(id, fields) {
  const db = getDrizzle();
  const now = nowMs();
  const parts = { updated_at: now };
  if (fields.name !== void 0) parts.name = fields.name;
  if (fields.description !== void 0) parts.description = fields.description;
  if (fields.metadata !== void 0) parts.metadata_json = JSON.stringify(fields.metadata);
  const res = db.update(schema_exports.memoryStores).set(parts).where(eq(schema_exports.memoryStores.id, id)).run();
  if (res.changes === 0) return void 0;
  return getMemoryStore(id) ?? void 0;
}
function redactMemoryVersion(storeId, versionId) {
  const db = getDrizzle();
  const version = db.select().from(schema_exports.memoryVersions).where(
    and(
      eq(schema_exports.memoryVersions.store_id, storeId),
      eq(schema_exports.memoryVersions.id, versionId)
    )
  ).get();
  if (!version) return false;
  if (version.memory_id && version.content_sha256) {
    const memory = getMemory(version.memory_id);
    if (memory && memory.content_sha256 === version.content_sha256) {
      return false;
    }
  }
  const now = nowMs();
  db.run(
    sql`UPDATE memory_versions SET content = NULL, content_sha256 = NULL, redacted_at = ${now} WHERE id = ${versionId} AND store_id = ${storeId}`
  );
  return true;
}
function archiveMemoryStore(id) {
  const db = getDrizzle();
  const now = nowMs();
  const res = db.update(schema_exports.memoryStores).set({ archived_at: now, updated_at: now }).where(eq(schema_exports.memoryStores.id, id)).run();
  return res.changes > 0;
}

export {
  createMemoryStore,
  getMemoryStore,
  listMemoryStores,
  deleteMemoryStore,
  createOrUpsertMemory,
  getMemory,
  getMemoryByPath,
  listMemories,
  searchMemories,
  updateMemory,
  deleteMemory,
  createMemoryVersion,
  listMemoryVersions,
  getMemoryVersion,
  updateMemoryStore,
  redactMemoryVersion,
  archiveMemoryStore
};
