import { eq, and, gt, asc, desc, lt } from 'drizzle-orm';
import { db } from '../db';
import { chatSessionEvents } from './schema';

/** Append one outbound event to a session's durable log; returns its global cursor id. */
export async function appendChatEvent(sessionId: string, event: unknown): Promise<number> {
  const [row] = await db.insert(chatSessionEvents).values({ sessionId, event }).returning({ id: chatSessionEvents.id });
  return row!.id;
}

/** Replay everything a (re)connecting client missed: events for this session with id > cursor. */
export async function getChatEventsSince(
  sessionId: string,
  cursor: number,
): Promise<Array<{ id: number; event: unknown }>> {
  return db
    .select({ id: chatSessionEvents.id, event: chatSessionEvents.event })
    .from(chatSessionEvents)
    .where(and(eq(chatSessionEvents.sessionId, sessionId), gt(chatSessionEvents.id, cursor)))
    .orderBy(asc(chatSessionEvents.id));
}

/**
 * The newest cursor id for one session, or undefined if it has no events yet. The writer uses this to
 * pick its `prevSeq` chain back up after its own restart, so a client can still tell a contiguous
 * replay from one with a hole in it.
 */
export async function getLastChatEventSeq(sessionId: string): Promise<number | undefined> {
  const [row] = await db
    .select({ id: chatSessionEvents.id })
    .from(chatSessionEvents)
    .where(eq(chatSessionEvents.sessionId, sessionId))
    .orderBy(desc(chatSessionEvents.id))
    .limit(1);
  return row?.id;
}

/** Retention: drop events older than the cutoff (called periodically). */
export async function pruneChatEventsOlderThan(cutoff: Date): Promise<void> {
  await db.delete(chatSessionEvents).where(lt(chatSessionEvents.createdAt, cutoff));
}
