import {
  archiveThread,
  getThread,
  listThreads
} from "./chunk-B4F53V4H.js";
import {
  assertResourceTenant
} from "./chunk-3F6VNSRK.js";
import {
  jsonOk,
  paginatedOk,
  routeWrap
} from "./chunk-KKJ5D3II.js";
import {
  subscribe
} from "./chunk-4NRHKTBW.js";
import {
  getSession
} from "./chunk-SEGKFEG5.js";
import {
  listEvents,
  rowToManagedEvent
} from "./chunk-LH3NEWMT.js";
import {
  getDb,
  init_client
} from "./chunk-TLEKKGH7.js";
import {
  badRequest,
  notFound
} from "./chunk-EZYKRG4W.js";

// src/handlers/anthropic-compat/threads.ts
init_client();
function loadSession(auth, sessionId) {
  const row = getDb().prepare(`SELECT tenant_id FROM sessions WHERE id = ?`).get(sessionId);
  if (!row) throw notFound(`session ${sessionId} not found`);
  assertResourceTenant(auth, row.tenant_id, `session ${sessionId} not found`);
  const session = getSession(sessionId);
  if (!session) throw notFound(`session ${sessionId} not found`);
  return session;
}
function handleListThreads(request, sessionId) {
  return routeWrap(request, async ({ auth }) => {
    loadSession(auth, sessionId);
    const url = new URL(request.url);
    const limit = url.searchParams.get("limit");
    const order = url.searchParams.get("order");
    const requestedLimit = limit ? Number(limit) : 50;
    const data = listThreads(sessionId, {
      limit: requestedLimit,
      order: order ?? void 0
    });
    return paginatedOk(data, requestedLimit);
  });
}
function handleGetThread(request, sessionId, threadId) {
  return routeWrap(request, async ({ auth }) => {
    loadSession(auth, sessionId);
    const thread = getThread(sessionId, threadId);
    if (!thread) throw notFound(`thread ${threadId} not found`);
    return jsonOk(thread);
  });
}
function handleArchiveThread(request, sessionId, threadId) {
  return routeWrap(request, async ({ auth }) => {
    loadSession(auth, sessionId);
    const existing = getThread(sessionId, threadId);
    if (!existing) throw notFound(`thread ${threadId} not found`);
    if (existing.status !== "idle") {
      throw badRequest(`cannot archive thread in status "${existing.status}" \u2014 must be idle`);
    }
    const archived = archiveThread(sessionId, threadId);
    if (!archived) throw notFound(`thread ${threadId} not found`);
    return jsonOk(archived);
  });
}
function handleListThreadEvents(request, sessionId, threadId) {
  return routeWrap(request, async ({ auth }) => {
    loadSession(auth, sessionId);
    const thread = getThread(sessionId, threadId);
    if (!thread) throw notFound(`thread ${threadId} not found`);
    const url = new URL(request.url);
    const limit = url.searchParams.get("limit");
    const order = url.searchParams.get("order");
    const afterSeq = url.searchParams.get("after_seq");
    const requestedLimit = limit ? Number(limit) : 50;
    const allEvents = listEvents(sessionId, {
      limit: 500,
      // fetch more than needed since we filter
      order: order ?? "asc",
      afterSeq: afterSeq ? Number(afterSeq) : void 0
    });
    const threadEvents = allEvents.filter((e) => {
      const payload = JSON.parse(e.payload_json);
      return payload.thread_id === threadId || e.type.startsWith("session.thread_");
    }).slice(0, requestedLimit).map(rowToManagedEvent);
    return paginatedOk(threadEvents, requestedLimit);
  });
}
function handleStreamThreadEvents(request, sessionId, threadId) {
  return routeWrap(request, async ({ auth }) => {
    loadSession(auth, sessionId);
    const thread = getThread(sessionId, threadId);
    if (!thread) throw notFound(`thread ${threadId} not found`);
    const url = new URL(request.url);
    const lastEventId = request.headers.get("last-event-id");
    const afterSeq = lastEventId ? Number(lastEventId) : Number(url.searchParams.get("after_seq") ?? "0");
    const encoder = new TextEncoder();
    let controller;
    const stream = new ReadableStream({
      start(c) {
        controller = c;
      }
    });
    const write = (payload) => {
      try {
        controller.enqueue(encoder.encode(payload));
      } catch {
      }
    };
    const sub = subscribe(
      sessionId,
      Number.isFinite(afterSeq) ? afterSeq : 0,
      (evt) => {
        if (evt.thread_id === threadId) {
          write(`id: ${evt.seq}
event: ${evt.type}
data: ${JSON.stringify(evt)}

`);
        }
      }
    );
    const keepalive = setInterval(() => {
      write(`data: {"type":"ping"}

`);
    }, 15e3);
    const abort = () => {
      clearInterval(keepalive);
      sub.unsubscribe();
      try {
        controller.close();
      } catch {
      }
    };
    request.signal.addEventListener("abort", abort);
    return new Response(stream, {
      headers: {
        "Content-Type": "text/event-stream",
        "Cache-Control": "no-cache",
        Connection: "keep-alive",
        "X-Accel-Buffering": "no"
      }
    });
  });
}

export {
  handleListThreads,
  handleGetThread,
  handleArchiveThread,
  handleListThreadEvents,
  handleStreamThreadEvents
};
