/**
 * public/queue.ts — W2: client helper for the server-side PTY-inject queue.
 *
 * Enqueue a follow-up prompt that the server fires into a session's PTY the next
 * time Claude goes idle (so "run tests → open a PR" advances itself while you're
 * away). Enqueue is a same-origin HTTP POST (Origin-guarded server-side), NOT a
 * WS frame — it must work with zero tabs open and target any session (e.g. from
 * the manage page), not just the WS-bound one.
 *
 * Discipline (mirrors quick-reply): every call NEVER throws — a failed fetch or
 * non-2xx response returns a falsy result the caller can ignore. Byte-shuttle:
 * `text` is sent verbatim; `appendEnter` tells the server to append \r.
 */

/** Result of an enqueue attempt. `length` = the new queue depth on success. */
export interface EnqueueResult {
  ok: boolean
  /** New queue depth (present on success). */
  length?: number
  /** HTTP status on a non-2xx response (absent on network error). */
  status?: number
}

/** POST a follow-up prompt to a session's inject queue. Never throws. */
export async function enqueueFollowup(
  sessionId: string,
  text: string,
  appendEnter: boolean,
): Promise<EnqueueResult> {
  try {
    if (typeof fetch === 'undefined') return { ok: false }
    const res = await fetch(`/live-sessions/${encodeURIComponent(sessionId)}/queue`, {
      method: 'POST',
      credentials: 'same-origin',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ text, appendEnter }),
    })
    if (!res.ok) return { ok: false, status: res.status }
    const data = (await res.json()) as { length?: unknown }
    return { ok: true, length: typeof data.length === 'number' ? data.length : undefined }
  } catch {
    return { ok: false }
  }
}

/** DELETE all pending entries for a session (cancel-all). Returns success. Never throws. */
export async function clearQueue(sessionId: string): Promise<boolean> {
  try {
    if (typeof fetch === 'undefined') return false
    const res = await fetch(`/live-sessions/${encodeURIComponent(sessionId)}/queue`, {
      method: 'DELETE',
      credentials: 'same-origin',
    })
    return res.ok
  } catch {
    return false
  }
}

/**
 * Extract the queue depth from an incoming server frame. Returns the length for a
 * `{type:'queue',length}` frame, else null (so callers can filter unrelated
 * frames). Defensive: tolerates any unknown input shape.
 */
export function queueLengthFromFrame(msg: unknown): number | null {
  if (msg === null || typeof msg !== 'object') return null
  const o = msg as Record<string, unknown>
  if (o['type'] !== 'queue') return null
  return typeof o['length'] === 'number' ? o['length'] : null
}
