import {
  getAgent
} from "./chunk-LGPJPAHU.js";
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/threads.ts
init_drizzle();
import { eq, and, isNull, lt, gt, asc, desc } from "drizzle-orm";
init_ids();
init_clock();
var MAX_THREADS_PER_SESSION = 25;
function hydrate(row) {
  const agent = getAgent(row.agent_id, row.agent_version);
  const agentEmbed = agent ? {
    type: "agent",
    id: agent.id,
    version: agent.version,
    name: agent.name,
    description: agent.description,
    model: agent.model,
    system: agent.system,
    tools: agent.tools,
    mcp_servers: agent.mcp_servers,
    skills: agent.skills
  } : {
    type: "agent",
    id: row.agent_id,
    version: row.agent_version,
    name: "",
    description: "",
    model: { id: "" },
    system: null,
    tools: [],
    mcp_servers: [],
    skills: []
  };
  return {
    type: "session_thread",
    id: row.id,
    session_id: row.session_id,
    status: row.status,
    agent: agentEmbed,
    parent_thread_id: row.parent_thread_id ?? null,
    created_at: toIso(row.created_at),
    updated_at: toIso(row.updated_at),
    archived_at: row.archived_at ? toIso(row.archived_at) : null,
    usage: {
      input_tokens: row.usage_input_tokens,
      output_tokens: row.usage_output_tokens,
      cache_read_input_tokens: row.usage_cache_read_input_tokens,
      cache_creation: {
        ephemeral_5m_input_tokens: row.usage_cache_creation_input_tokens,
        ephemeral_1h_input_tokens: 0
      }
    },
    stop_reason: row.stop_reason ?? null
  };
}
function createThread(opts) {
  const db = getDrizzle();
  const existing = db.select({ id: schema_exports.sessionThreads.id }).from(schema_exports.sessionThreads).where(
    and(
      eq(schema_exports.sessionThreads.session_id, opts.sessionId),
      isNull(schema_exports.sessionThreads.archived_at)
    )
  ).all();
  if (existing.length >= MAX_THREADS_PER_SESSION) {
    throw new Error(`max threads per session reached (${MAX_THREADS_PER_SESSION})`);
  }
  const id = newId("sth");
  const now = nowMs();
  db.insert(schema_exports.sessionThreads).values({
    id,
    session_id: opts.sessionId,
    agent_id: opts.agentId,
    agent_version: opts.agentVersion,
    parent_thread_id: opts.parentThreadId ?? null,
    status: "idle",
    usage_input_tokens: 0,
    usage_output_tokens: 0,
    usage_cache_read_input_tokens: 0,
    usage_cache_creation_input_tokens: 0,
    created_at: now,
    updated_at: now
  }).run();
  return getThread(opts.sessionId, id);
}
function getThread(sessionId, threadId) {
  const db = getDrizzle();
  const row = db.select().from(schema_exports.sessionThreads).where(
    and(
      eq(schema_exports.sessionThreads.id, threadId),
      eq(schema_exports.sessionThreads.session_id, sessionId)
    )
  ).get();
  if (!row) return void 0;
  return hydrate(row);
}
function listThreads(sessionId, opts) {
  const db = getDrizzle();
  const limit = Math.min(Math.max(opts?.limit ?? 50, 1), 100);
  const orderDir = opts?.order === "asc" ? "asc" : "desc";
  const conditions = [eq(schema_exports.sessionThreads.session_id, sessionId)];
  if (opts?.cursor) {
    conditions.push(
      orderDir === "desc" ? lt(schema_exports.sessionThreads.id, opts.cursor) : gt(schema_exports.sessionThreads.id, opts.cursor)
    );
  }
  const orderClause = orderDir === "desc" ? desc(schema_exports.sessionThreads.created_at) : asc(schema_exports.sessionThreads.created_at);
  const rows = db.select().from(schema_exports.sessionThreads).where(and(...conditions)).orderBy(orderClause).limit(limit).all();
  return rows.map(hydrate);
}
function updateThreadStatus(threadId, status, stopReason) {
  const db = getDrizzle();
  const now = nowMs();
  db.update(schema_exports.sessionThreads).set({
    status,
    stop_reason: stopReason ?? null,
    updated_at: now
  }).where(eq(schema_exports.sessionThreads.id, threadId)).run();
}
function updateThreadUsage(threadId, usage) {
  const db = getDrizzle();
  const now = nowMs();
  const row = db.select().from(schema_exports.sessionThreads).where(eq(schema_exports.sessionThreads.id, threadId)).get();
  if (!row) return;
  db.update(schema_exports.sessionThreads).set({
    usage_input_tokens: row.usage_input_tokens + (usage.input_tokens ?? 0),
    usage_output_tokens: row.usage_output_tokens + (usage.output_tokens ?? 0),
    usage_cache_read_input_tokens: row.usage_cache_read_input_tokens + (usage.cache_read_input_tokens ?? 0),
    usage_cache_creation_input_tokens: row.usage_cache_creation_input_tokens + (usage.cache_creation_input_tokens ?? 0),
    updated_at: now
  }).where(eq(schema_exports.sessionThreads.id, threadId)).run();
}
function archiveThread(sessionId, threadId) {
  const db = getDrizzle();
  const row = db.select().from(schema_exports.sessionThreads).where(
    and(
      eq(schema_exports.sessionThreads.id, threadId),
      eq(schema_exports.sessionThreads.session_id, sessionId)
    )
  ).get();
  if (!row) return void 0;
  if (row.status !== "idle") {
    throw new Error(`cannot archive thread in status "${row.status}" \u2014 must be idle`);
  }
  const now = nowMs();
  db.update(schema_exports.sessionThreads).set({ archived_at: now, updated_at: now }).where(eq(schema_exports.sessionThreads.id, threadId)).run();
  return getThread(sessionId, threadId);
}
function countActiveThreads(sessionId) {
  const db = getDrizzle();
  const rows = db.select({ id: schema_exports.sessionThreads.id }).from(schema_exports.sessionThreads).where(
    and(
      eq(schema_exports.sessionThreads.session_id, sessionId),
      isNull(schema_exports.sessionThreads.archived_at)
    )
  ).all();
  return rows.length;
}

export {
  createThread,
  getThread,
  listThreads,
  updateThreadStatus,
  updateThreadUsage,
  archiveThread,
  countActiveThreads
};
