/**
 * Codex Message Utilities
 *
 * Pure functions for constructing BrowserIncomingMessage objects
 * that represent tool use, tool results, assistant messages, and
 * streaming events in the format expected by the browser.
 */

import { randomUUID } from "node:crypto";
import type { BrowserIncomingMessage } from "./session-types.js";

// ─── Message ID ───────────────────────────────────────────────────────────────

/** Create a deterministic message ID from a kind and optional source item ID. */
export function makeMessageId(kind: string, sourceId?: string): string {
  if (sourceId) return `codex-${kind}-${sourceId}`;
  return `codex-${kind}-${randomUUID()}`;
}

// ─── Tool Use Messages ────────────────────────────────────────────────────────

/** Build an assistant message with a tool_use content block. */
export function buildToolUseMessage(
  toolUseId: string,
  toolName: string,
  input: Record<string, unknown>,
  model: string,
): BrowserIncomingMessage {
  return {
    type: "assistant",
    message: {
      id: makeMessageId("tool_use", toolUseId),
      type: "message",
      role: "assistant",
      model,
      content: [
        {
          type: "tool_use",
          id: toolUseId,
          name: toolName,
          input,
        },
      ],
      stop_reason: null,
      usage: { input_tokens: 0, output_tokens: 0, cache_creation_input_tokens: 0, cache_read_input_tokens: 0 },
    },
    parent_tool_use_id: null,
    timestamp: Date.now(),
  };
}

/** Build a stream_event for tool_use content_block_start. */
export function buildToolUseStartEvent(
  toolUseId: string,
  toolName: string,
): BrowserIncomingMessage {
  return {
    type: "stream_event",
    event: {
      type: "content_block_start",
      index: 0,
      content_block: { type: "tool_use", id: toolUseId, name: toolName, input: {} },
    },
    parent_tool_use_id: null,
  };
}

// ─── Tool Result Messages ─────────────────────────────────────────────────────

/** Build an assistant message with a tool_result content block. */
export function buildToolResultMessage(
  toolUseId: string,
  content: unknown,
  isError: boolean,
  model: string,
): BrowserIncomingMessage {
  const safeContent = typeof content === "string" ? content : JSON.stringify(content);
  return {
    type: "assistant",
    message: {
      id: makeMessageId("tool_result", toolUseId),
      type: "message",
      role: "assistant",
      model,
      content: [
        {
          type: "tool_result",
          tool_use_id: toolUseId,
          content: safeContent,
          is_error: isError,
        },
      ],
      stop_reason: null,
      usage: { input_tokens: 0, output_tokens: 0, cache_creation_input_tokens: 0, cache_read_input_tokens: 0 },
    },
    parent_tool_use_id: null,
    timestamp: Date.now(),
  };
}

// ─── Streaming Events ─────────────────────────────────────────────────────────

/** Build message_start stream event for agent message streaming. */
export function buildMessageStartEvent(itemId: string, model: string): BrowserIncomingMessage {
  return {
    type: "stream_event",
    event: {
      type: "message_start",
      message: {
        id: makeMessageId("agent", itemId),
        type: "message",
        role: "assistant",
        model,
        content: [],
        stop_reason: null,
        usage: { input_tokens: 0, output_tokens: 0, cache_creation_input_tokens: 0, cache_read_input_tokens: 0 },
      },
    },
    parent_tool_use_id: null,
  };
}

/** Build content_block_start stream event for text streaming. */
export function buildTextBlockStartEvent(): BrowserIncomingMessage {
  return {
    type: "stream_event",
    event: {
      type: "content_block_start",
      index: 0,
      content_block: { type: "text", text: "" },
    },
    parent_tool_use_id: null,
  };
}

/** Build content_block_delta stream event for text delta. */
export function buildTextDeltaEvent(delta: string): BrowserIncomingMessage {
  return {
    type: "stream_event",
    event: {
      type: "content_block_delta",
      index: 0,
      delta: { type: "text_delta", text: delta },
    },
    parent_tool_use_id: null,
  };
}

/** Build content_block_stop stream event. */
export function buildContentBlockStopEvent(): BrowserIncomingMessage {
  return {
    type: "stream_event",
    event: {
      type: "content_block_stop",
      index: 0,
    },
    parent_tool_use_id: null,
  };
}

/** Build message_delta stream event (stop reason). */
export function buildMessageDeltaEvent(): BrowserIncomingMessage {
  return {
    type: "stream_event",
    event: {
      type: "message_delta",
      delta: { stop_reason: null },
      usage: { output_tokens: 0 },
    },
    parent_tool_use_id: null,
  };
}

/** Build content_block_start stream event for thinking content. */
export function buildThinkingBlockStartEvent(text: string): BrowserIncomingMessage {
  return {
    type: "stream_event",
    event: {
      type: "content_block_start",
      index: 0,
      content_block: { type: "thinking", thinking: text },
    },
    parent_tool_use_id: null,
  };
}

// ─── Full Assistant Messages ──────────────────────────────────────────────────

/** Build a full assistant text message (used when agent message streaming completes). */
export function buildAssistantTextMessage(
  itemId: string,
  text: string,
  model: string,
): BrowserIncomingMessage {
  return {
    type: "assistant",
    message: {
      id: makeMessageId("agent", itemId),
      type: "message",
      role: "assistant",
      model,
      content: [{ type: "text", text }],
      stop_reason: "end_turn",
      usage: { input_tokens: 0, output_tokens: 0, cache_creation_input_tokens: 0, cache_read_input_tokens: 0 },
    },
    parent_tool_use_id: null,
    timestamp: Date.now(),
  };
}

/** Build a full assistant thinking message (used when reasoning completes). */
export function buildThinkingMessage(
  itemId: string,
  thinkingText: string,
  model: string,
): BrowserIncomingMessage {
  return {
    type: "assistant",
    message: {
      id: makeMessageId("reasoning", itemId),
      type: "message",
      role: "assistant",
      model,
      content: [{ type: "thinking", thinking: thinkingText }],
      stop_reason: null,
      usage: { input_tokens: 0, output_tokens: 0, cache_creation_input_tokens: 0, cache_read_input_tokens: 0 },
    },
    parent_tool_use_id: null,
    timestamp: Date.now(),
  };
}
