/**
 * Codex Item Handlers
 *
 * Pure functions for processing item/started and item/completed events.
 * Extracts tool_use input computation and result text building from
 * the main adapter class.
 */

import type {
  CodexItem,
  CodexCommandExecutionItem,
  CodexFileChangeItem,
  CodexMcpToolCallItem,
  CodexWebSearchItem,
  CodexReasoningItem,
} from "./codex-types.js";
import { safeKind } from "./codex-types.js";

// ─── Types ────────────────────────────────────────────────────────────────────

export interface ToolUseDescriptor {
  toolUseId: string;
  toolName: string;
  input: Record<string, unknown>;
}

export interface CommandResult {
  text: string;
  isError: boolean;
}

export interface FileChangeResult {
  toolName: string;
  toolInput: Record<string, unknown>;
  summary: string;
  isError: boolean;
}

// ─── Item Started Helpers ─────────────────────────────────────────────────────

/** Extract tool_use descriptor for an item/started event. Returns null for non-tool items. */
export function getStartedItemToolUse(item: CodexItem): ToolUseDescriptor | null {
  switch (item.type) {
    case "commandExecution": {
      const cmd = item as CodexCommandExecutionItem;
      const commandStr = Array.isArray(cmd.command) ? cmd.command.join(" ") : (cmd.command || "");
      return { toolUseId: item.id, toolName: "Bash", input: { command: commandStr } };
    }

    case "fileChange": {
      const fc = item as CodexFileChangeItem;
      const changes = fc.changes || [];
      const firstChange = changes[0];
      const toolName = safeKind(firstChange?.kind) === "create" ? "Write" : "Edit";
      return {
        toolUseId: item.id,
        toolName,
        input: {
          file_path: firstChange?.path || "",
          changes: changes.map((c) => ({ path: c.path, kind: safeKind(c.kind) })),
        },
      };
    }

    case "mcpToolCall": {
      const mcp = item as CodexMcpToolCallItem;
      return {
        toolUseId: item.id,
        toolName: `mcp:${mcp.server}:${mcp.tool}`,
        input: mcp.arguments || {},
      };
    }

    case "webSearch": {
      const ws = item as CodexWebSearchItem;
      return { toolUseId: item.id, toolName: "WebSearch", input: { query: ws.query || "" } };
    }

    default:
      return null;
  }
}

/** Extract initial reasoning text from a reasoning item. */
export function getReasoningStartText(item: CodexReasoningItem): string {
  return item.summary || item.content || "";
}

// ─── Item Completed Helpers ───────────────────────────────────────────────────

/**
 * Build the result text and error flag for a completed command execution.
 * Returns null when a successful command produces no output (should be silent).
 */
export function buildCommandCompletionResult(item: CodexCommandExecutionItem): CommandResult | null {
  const output = (item as Record<string, unknown>).stdout as string || "";
  const stderr = (item as Record<string, unknown>).stderr as string || "";
  const combinedOutput = [output, stderr].filter(Boolean).join("\n").trim();
  const exitCode = typeof item.exitCode === "number" ? item.exitCode : 0;
  const durationMs = typeof item.durationMs === "number" ? item.durationMs : undefined;
  const failed = item.status === "failed" || item.status === "declined" || exitCode !== 0;

  // Keep successful no-output commands silent in the chat feed.
  if (!combinedOutput && !failed) return null;

  let resultText = combinedOutput;
  if (!resultText) {
    resultText = `Exit code: ${exitCode}`;
  } else if (exitCode !== 0) {
    resultText = `${resultText}\nExit code: ${exitCode}`;
  }

  // Append duration if available and significant (>100ms)
  if (durationMs !== undefined && durationMs >= 100) {
    const durationStr = durationMs >= 1000
      ? `${(durationMs / 1000).toFixed(1)}s`
      : `${durationMs}ms`;
    resultText = `${resultText}\n(${durationStr})`;
  }

  return { text: resultText, isError: failed };
}

/** Build tool_use descriptor and result for a completed file change. */
export function buildFileChangeCompletionResult(item: CodexFileChangeItem): FileChangeResult {
  const changes = item.changes || [];
  const firstChange = changes[0];
  const toolName = safeKind(firstChange?.kind) === "create" ? "Write" : "Edit";
  const toolInput = {
    file_path: firstChange?.path || "",
    changes: changes.map((c) => ({ path: c.path, kind: safeKind(c.kind) })),
  };
  const summary = changes.map((c) => `${safeKind(c.kind)}: ${c.path}`).join("\n");

  return {
    toolName,
    toolInput,
    summary: summary || "File changes applied",
    isError: item.status === "failed",
  };
}

/** Build tool_use descriptor and result text for a completed MCP tool call. */
export function getMcpToolCallToolUse(item: CodexMcpToolCallItem): ToolUseDescriptor {
  return {
    toolUseId: item.id,
    toolName: `mcp:${item.server}:${item.tool}`,
    input: item.arguments || {},
  };
}

/** Build tool_use descriptor and result text for a completed web search. */
export function getWebSearchToolUse(item: CodexWebSearchItem): ToolUseDescriptor {
  return {
    toolUseId: item.id,
    toolName: "WebSearch",
    input: { query: item.query || "" },
  };
}

/** Extract the command string from a command execution item. */
export function getCommandString(item: CodexCommandExecutionItem): string {
  return Array.isArray(item.command) ? item.command.join(" ") : (item.command || "");
}
