import {
  init_session_resources,
  session_resources_exports
} from "./chunk-UU3ECGO5.js";
import {
  getAgent
} from "./chunk-LGPJPAHU.js";
import {
  DEFAULT_TENANT_ID
} from "./chunk-X27B5TCC.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";
import {
  __toCommonJS
} from "./chunk-2ESYSVXG.js";

// src/db/sessions.ts
init_drizzle();
import { eq, and, isNull, lt, gt, gte, lte, inArray, sql } from "drizzle-orm";
init_ids();
init_clock();
function hydrateSession(row) {
  let resources;
  try {
    const { listResources } = (init_session_resources(), __toCommonJS(session_resources_exports));
    const tableResources = listResources(row.id);
    if (tableResources.length > 0) {
      resources = tableResources.map((r) => {
        const base = { type: r.type };
        if (r.file_id) base.file_id = r.file_id;
        if (r.mount_path) base.mount_path = r.mount_path;
        if (r.url) {
          if (r.type === "github_repository") base.repository_url = r.url;
          else base.uri = r.url;
        }
        if (r.checkout_json) {
          try {
            const checkout = JSON.parse(r.checkout_json);
            if (checkout.type === "branch") base.branch = checkout.name;
            else if (checkout.type === "commit") base.commit = checkout.name;
          } catch {
          }
        }
        return base;
      });
    } else {
      resources = row.resources_json ? JSON.parse(row.resources_json) : [];
    }
  } catch {
    resources = row.resources_json ? JSON.parse(row.resources_json) : [];
  }
  const agentObj = getAgent(row.agent_id, row.agent_version);
  const agentEmbed = agentObj ? {
    type: "agent",
    id: agentObj.id,
    version: agentObj.version,
    name: agentObj.name,
    description: agentObj.description,
    model: agentObj.model,
    system: agentObj.system,
    tools: agentObj.tools,
    mcp_servers: agentObj.mcp_servers,
    skills: agentObj.skills
  } : {
    type: "agent",
    id: row.agent_id,
    version: row.agent_version,
    name: "",
    description: "",
    model: { id: "" },
    system: null,
    tools: [],
    mcp_servers: [],
    skills: []
  };
  return {
    id: row.id,
    type: "session",
    agent: agentEmbed,
    environment_id: row.environment_id,
    status: row.status,
    stop_reason: row.stop_reason,
    title: row.title,
    metadata: JSON.parse(row.metadata_json),
    max_budget_usd: row.max_budget_usd ?? null,
    max_tokens: row.max_tokens ?? null,
    max_wall_duration_ms: row.max_wall_duration_ms ?? null,
    outcome: row.outcome_criteria_json ? JSON.parse(row.outcome_criteria_json) : null,
    outcome_evaluations: row.outcome_criteria_json ? [JSON.parse(row.outcome_criteria_json)].filter((o) => o.outcome_id).map((o) => ({
      type: "outcome_evaluation",
      outcome_id: o.outcome_id,
      description: o.description ?? "",
      result: o.status === "running" ? "running" : o.status,
      iteration: o.grader_iteration ?? 0,
      completed_at: o.completed_at ?? null,
      explanation: o.explanation ?? ""
    })) : [],
    resources,
    vault_ids: row.vault_ids_json ? JSON.parse(row.vault_ids_json) : [],
    user_profile_id: row.user_profile_id ?? null,
    parent_session_id: row.parent_session_id ?? null,
    thread_depth: row.thread_depth ?? 0,
    stats: {
      turn_count: row.turn_count,
      tool_calls_count: row.tool_calls_count,
      active_seconds: row.active_seconds,
      duration_seconds: row.duration_seconds
    },
    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
      },
      cost_usd: row.usage_cost_usd
    },
    created_at: toIso(row.created_at),
    updated_at: toIso(row.updated_at),
    archived_at: row.archived_at ? toIso(row.archived_at) : null
  };
}
function createSession(input) {
  const db = getDrizzle();
  const id = newId("sesn");
  const now = nowMs();
  db.insert(schema_exports.sessions).values({
    id,
    agent_id: input.agent_id,
    agent_version: input.agent_version,
    environment_id: input.environment_id,
    status: "idle",
    title: input.title ?? null,
    metadata_json: JSON.stringify(input.metadata ?? {}),
    max_budget_usd: input.max_budget_usd ?? null,
    max_tokens: input.max_tokens ?? null,
    max_wall_duration_ms: input.max_wall_duration_ms ?? null,
    resources_json: input.resources ? JSON.stringify(input.resources) : null,
    vault_ids_json: input.vault_ids ? JSON.stringify(input.vault_ids) : null,
    user_profile_id: input.user_profile_id ?? null,
    parent_session_id: input.parent_session_id ?? null,
    thread_depth: input.thread_depth ?? 0,
    api_key_id: input.api_key_id ?? null,
    tenant_id: input.tenant_id ?? DEFAULT_TENANT_ID,
    debug_prompt_json: input.debug_capture ? '{"pending":true}' : null,
    created_at: now,
    updated_at: now
  }).run();
  return getSession(id);
}
function listSessionsByApiKey(keyId, opts = {}) {
  const db = getDrizzle();
  const limit = Math.min(opts.limit ?? 50, 200);
  const offset = opts.offset ?? 0;
  const rows = db.select().from(schema_exports.sessions).where(eq(schema_exports.sessions.api_key_id, keyId)).orderBy(sql`${schema_exports.sessions.created_at} DESC`).limit(limit).offset(offset).all();
  return rows.map(hydrateSession);
}
function getSession(id) {
  const row = getSessionRow(id);
  return row ? hydrateSession(row) : null;
}
function getSessionRow(id) {
  const db = getDrizzle();
  return db.select().from(schema_exports.sessions).where(eq(schema_exports.sessions.id, id)).get() ?? null;
}
function updateSessionStatus(id, status, stopReason) {
  const db = getDrizzle();
  db.update(schema_exports.sessions).set({ status, stop_reason: stopReason ?? null, updated_at: nowMs() }).where(eq(schema_exports.sessions.id, id)).run();
}
function setSessionSandbox(id, sandboxName) {
  const db = getDrizzle();
  db.update(schema_exports.sessions).set({ sandbox_name: sandboxName, updated_at: nowMs() }).where(eq(schema_exports.sessions.id, id)).run();
}
function setBackendSessionId(id, backendSessionId) {
  const db = getDrizzle();
  db.update(schema_exports.sessions).set({ claude_session_id: backendSessionId, updated_at: nowMs() }).where(eq(schema_exports.sessions.id, id)).run();
}
function setSessionProvider(id, providerName) {
  const db = getDrizzle();
  db.update(schema_exports.sessions).set({ provider_name: providerName, updated_at: nowMs() }).where(eq(schema_exports.sessions.id, id)).run();
}
function setIdleSince(id, idleSince) {
  const db = getDrizzle();
  db.update(schema_exports.sessions).set({ idle_since: idleSince }).where(eq(schema_exports.sessions.id, id)).run();
}
function updateSessionMutable(id, input) {
  const db = getDrizzle();
  const existing = getSession(id);
  if (!existing) return null;
  db.update(schema_exports.sessions).set({
    title: input.title ?? existing.title,
    metadata_json: JSON.stringify(input.metadata ?? existing.metadata),
    updated_at: nowMs()
  }).where(eq(schema_exports.sessions.id, id)).run();
  return getSession(id);
}
function bumpSessionStats(id, delta, usage) {
  const db = getDrizzle();
  db.transaction((tx) => {
    tx.update(schema_exports.sessions).set({
      turn_count: sql`${schema_exports.sessions.turn_count} + ${delta.turn_count ?? 0}`,
      tool_calls_count: sql`${schema_exports.sessions.tool_calls_count} + ${delta.tool_calls_count ?? 0}`,
      active_seconds: sql`${schema_exports.sessions.active_seconds} + ${delta.active_seconds ?? 0}`,
      duration_seconds: sql`${schema_exports.sessions.duration_seconds} + ${delta.duration_seconds ?? 0}`,
      usage_input_tokens: sql`${schema_exports.sessions.usage_input_tokens} + ${usage?.input_tokens ?? 0}`,
      usage_output_tokens: sql`${schema_exports.sessions.usage_output_tokens} + ${usage?.output_tokens ?? 0}`,
      usage_cache_read_input_tokens: sql`${schema_exports.sessions.usage_cache_read_input_tokens} + ${usage?.cache_read_input_tokens ?? 0}`,
      usage_cache_creation_input_tokens: sql`${schema_exports.sessions.usage_cache_creation_input_tokens} + ${usage?.cache_creation_input_tokens ?? 0}`,
      usage_cost_usd: sql`${schema_exports.sessions.usage_cost_usd} + ${usage?.cost_usd ?? 0}`,
      updated_at: nowMs()
    }).where(eq(schema_exports.sessions.id, id)).run();
    const costDelta = usage?.cost_usd ?? 0;
    if (costDelta !== 0) {
      tx.run(
        sql`UPDATE api_keys
            SET spent_usd = spent_usd + ${costDelta}
          WHERE id = (SELECT api_key_id FROM sessions WHERE id = ${id} AND api_key_id IS NOT NULL)`
      );
    }
  });
}
function archiveSession(id) {
  const db = getDrizzle();
  const now = nowMs();
  const res = db.update(schema_exports.sessions).set({ archived_at: now, updated_at: now }).where(and(eq(schema_exports.sessions.id, id), isNull(schema_exports.sessions.archived_at))).run();
  return res.changes > 0;
}
function listSessions(opts) {
  const db = getDrizzle();
  const limit = Math.min(Math.max(opts.limit ?? 20, 1), 100);
  const orderDir = opts.order === "asc" ? "asc" : "desc";
  const includeArchived = opts.includeArchived ?? false;
  const conditions = [];
  if (opts.tenantFilter != null) conditions.push(eq(schema_exports.sessions.tenant_id, opts.tenantFilter));
  if (opts.agent_id) conditions.push(eq(schema_exports.sessions.agent_id, opts.agent_id));
  if (opts.agent_version != null) conditions.push(eq(schema_exports.sessions.agent_version, opts.agent_version));
  if (opts.environmentId) conditions.push(eq(schema_exports.sessions.environment_id, opts.environmentId));
  if (opts.parent_session_id) conditions.push(eq(schema_exports.sessions.parent_session_id, opts.parent_session_id));
  if (opts.statuses?.length) {
    conditions.push(inArray(schema_exports.sessions.status, opts.statuses));
  } else if (opts.status) {
    conditions.push(eq(schema_exports.sessions.status, opts.status));
  }
  if (!includeArchived) conditions.push(isNull(schema_exports.sessions.archived_at));
  if (opts.createdGt != null) conditions.push(gt(schema_exports.sessions.created_at, opts.createdGt));
  if (opts.createdGte != null) conditions.push(gte(schema_exports.sessions.created_at, opts.createdGte));
  if (opts.createdLt != null) conditions.push(lt(schema_exports.sessions.created_at, opts.createdLt));
  if (opts.createdLte != null) conditions.push(lte(schema_exports.sessions.created_at, opts.createdLte));
  if (opts.cursor) {
    const cursorRow = db.select({ created_at: schema_exports.sessions.created_at }).from(schema_exports.sessions).where(eq(schema_exports.sessions.id, opts.cursor)).get();
    if (cursorRow) {
      conditions.push(
        orderDir === "desc" ? lt(schema_exports.sessions.created_at, cursorRow.created_at) : gt(schema_exports.sessions.created_at, cursorRow.created_at)
      );
    } else {
      conditions.push(
        orderDir === "desc" ? lt(schema_exports.sessions.id, opts.cursor) : gt(schema_exports.sessions.id, opts.cursor)
      );
    }
  }
  const where = conditions.length ? and(...conditions) : void 0;
  const orderClause = orderDir === "desc" ? sql`${schema_exports.sessions.created_at} DESC, ${schema_exports.sessions.id} DESC` : sql`${schema_exports.sessions.created_at} ASC, ${schema_exports.sessions.id} ASC`;
  const rows = where ? db.select().from(schema_exports.sessions).where(where).orderBy(orderClause).limit(limit).all() : db.select().from(schema_exports.sessions).orderBy(orderClause).limit(limit).all();
  return rows.map(hydrateSession);
}
function updateSessionResources(id, resourcesJson) {
  const db = getDrizzle();
  db.update(schema_exports.sessions).set({ resources_json: resourcesJson, updated_at: nowMs() }).where(eq(schema_exports.sessions.id, id)).run();
}
function listIdleSessions(sessionMaxAgeMs, now, limit) {
  const db = getDrizzle();
  return db.select().from(schema_exports.sessions).where(
    and(
      eq(schema_exports.sessions.status, "idle"),
      isNull(schema_exports.sessions.archived_at),
      sql`COALESCE(${schema_exports.sessions.idle_since}, ${schema_exports.sessions.created_at}) + ${sessionMaxAgeMs} < ${now}`
    )
  ).limit(limit).all();
}
function setOutcomeCriteria(id, criteria) {
  const db = getDrizzle();
  db.update(schema_exports.sessions).set({ outcome_criteria_json: JSON.stringify(criteria), updated_at: nowMs() }).where(eq(schema_exports.sessions.id, id)).run();
}
function getOutcomeCriteria(id) {
  const row = getSessionRow(id);
  return row?.outcome_criteria_json ? JSON.parse(row.outcome_criteria_json) : null;
}

export {
  hydrateSession,
  createSession,
  listSessionsByApiKey,
  getSession,
  getSessionRow,
  updateSessionStatus,
  setSessionSandbox,
  setBackendSessionId,
  setSessionProvider,
  setIdleSince,
  updateSessionMutable,
  bumpSessionStats,
  archiveSession,
  listSessions,
  updateSessionResources,
  listIdleSessions,
  setOutcomeCriteria,
  getOutcomeCriteria
};
