export const MessageRoles = ['user', 'assistant', 'tool'] as const
export type MessageRole = (typeof MessageRoles)[number]

export type ToolName = string

export const ToolPermissions = ['pass', 'require_action'] as const
export type ToolPermission = (typeof ToolPermissions)[number]

export type ToolCall = Readonly<{
  id: string
  name: ToolName
  subagentId?: string
  /**
   * Optional timestamp (ms since epoch) for when the tool call first appeared.
   * Used for UI effects like staggered status blinking.
   */
  startedAtMs?: number
  arguments: Record<string, unknown>
  thoughtSignature?: string
  /**
   * Optional raw (streaming) arguments text, used to represent `tool_call_delta`.
   * When present, UI should prefer this for preview rendering.
   */
  argumentsText?: string
  /**
   * Optional precomputed diff preview metadata for tools that emit old/new strings (e.g. Edit).
   * This is populated asynchronously (optional dependency: shiki).
   */
  diffPreview?: DiffPreview
  /**
   * Optional precomputed preview metadata for Read tool output (file content).
   * This is populated asynchronously (optional dependency: shiki).
   */
  readPreview?: ReadPreview
  /**
   * Optional line count hint for Write tool content (streamed from SDK).
   */
  linesWritten?: number
}>

export type ShikiToken = Readonly<{
  content: string
  color?: string
  fontStyle?: number
}>

export type DiffPreviewLine = Readonly<{
  type: 'context' | 'added' | 'removed'
  content: string
  tokens: readonly ShikiToken[] | null
}>

export type DiffPreview = Readonly<{
  kind: 'shiki'
  language: string
  theme: string
  oldString: string
  newString: string
  lines: readonly DiffPreviewLine[]
}>

export type ReadPreviewLine = Readonly<{
  gutter: string
  content: string
  tokens: readonly ShikiToken[] | null
}>

export type MarkdownCodeBlockPreviewLine = Readonly<{
  content: string
  tokens: readonly ShikiToken[] | null
}>

export type MarkdownCodeBlockPreview
  = | Readonly<{
    kind: 'shiki'
    language: string
    theme: string
    /**
     * Hash of the normalized code content (language-aware).
     */
    hash: string
    totalLines: number
    lines: readonly MarkdownCodeBlockPreviewLine[]
  }>
  | Readonly<{
    kind: 'skipped'
    hash: string
    totalLines: number
    reason: 'too_large' | 'shiki_unavailable'
  }>

export type ReadPreview
  = | Readonly<{
    kind: 'shiki'
    mode: 'collapsed' | 'expanded'
    language: string
    theme: string
    /**
     * Hash of the normalized (gutter-preserving) output; used for stale checks.
     */
    hash: string
    /**
     * Total number of normalized output lines.
     */
    totalLines: number
    lines: readonly ReadPreviewLine[]
  }>
  | Readonly<{
    kind: 'skipped'
    mode: 'collapsed' | 'expanded'
    hash: string
    totalLines: number
    reason: 'too_large' | 'shiki_unavailable'
  }>

/**
 * Tool approval behavior for the TUI.
 *
 * - `auto`: auto-approve all tools (no prompts).
 * - `normal`: auto-approve read-only tools; prompt for write/execute.
 * - `strict`: prompt for every tool call.
 */
export type ToolApprovalsMode = 'auto' | 'normal' | 'strict'

export type ApprovalRequest = Readonly<{
  id: string
  subagentId?: string
  toolCallId: string
  tool: ToolName
  permission: ToolPermission
  reason: string
  args?: Record<string, unknown>
  source?: 'local' | 'goatchain'
  riskLevel?: 'safe' | 'low' | 'medium' | 'high' | 'critical' | (string & {})
  status: 'pending' | 'approved' | 'denied'
}>

export type ToolResult = Readonly<{
  toolCallId: string
  output: string
  subagentId?: string
  /**
   * Optional ANSI-colored preview of `output` for UI rendering.
   * Should contain only SGR sequences (no cursor movement).
   */
  outputAnsi?: string
  status: 'success' | 'error'
  /**
   * Optional structured content from the tool (e.g. WebSearch results/context payload).
   */
  structuredContent?: Record<string, unknown>
}>

export type ChecklistItem = Readonly<{
  id: string
  text: string
  done: boolean
  /**
   * Status as reported by tool outputs (e.g. TodoWrite/TodoPlan).
   * Older persisted sessions may omit this field; renderers should fall back to `done`.
   */
  status?: 'completed' | 'in_progress' | 'pending' | (string & {})
}>

export const AssistantContentPartTypes = [
  'status',
  'thinking',
  'markdown',
  'tool_call',
  'tool_output',
  'tool_result',
  'approve',
  'todo',
  'plan',
  'llm_meta',
  'info',
] as const
export type AssistantContentPartType
  = (typeof AssistantContentPartTypes)[number]

export type LlmMetaChangedFile = Readonly<{
  path: string
  added?: number
  removed?: number
}>

export type AssistantContentPart
  = | Readonly<{ type: 'status', text: string }>
    | Readonly<{
      type: 'thinking'
      partId: string
      title: string
      collapsed: boolean
      content: string
    }>
    | Readonly<{
      type: 'markdown'
      markdown: string
      codeBlocks?: readonly MarkdownCodeBlockPreview[]
    }>
    | Readonly<{ type: 'tool_call', call: ToolCall }>
    | Readonly<{
      type: 'tool_output'
      toolCallId: string
      toolName: ToolName
      output: string
      subagentId?: string
    }>
    | Readonly<{ type: 'tool_result', result: ToolResult }>
    | Readonly<{ type: 'approve', request: ApprovalRequest }>
    | Readonly<{
      type: 'todo'
      partId: string
      title: string
      collapsed: boolean
      items: ChecklistItem[]
      toolCallId?: string
    }>
    | Readonly<{
      type: 'plan'
      partId: string
      title: string
      collapsed: boolean
      items: ChecklistItem[]
      toolCallId?: string
    }>
    | Readonly<{
      type: 'llm_meta'
      durationMs: number
      modelId?: string
      toolCalls?: number
      tokensUsed?: number
      changedFiles?: readonly string[]
      changedFileDetails?: readonly LlmMetaChangedFile[]
    }>
    | Readonly<{ type: 'info', text: string }>

export type Message
  = | Readonly<{
    id: string
    role: 'user'
    content: string
    focusFiles?: readonly string[]
    createdAtMs?: number
    modelId?: string
    metadata?: Record<string, unknown>
  }>
  | Readonly<{
    id: string
    role: 'assistant'
    parts: AssistantContentPart[]
    createdAtMs?: number
    modelId?: string
  }>
  | Readonly<{
    id: string
    role: 'tool'
    result: ToolResult
    createdAtMs?: number
  }>

export type RunConfig = Readonly<{
  model: string
  context_window: number
  temperature?: number
  interleaved_thinking?: boolean
}>

export type TokenUsage = Readonly<{
  prompt_tokens: number
  completion_tokens: number
  total_tokens: number
  budget: number
}>

export type GoatChainContext = Readonly<{
  system: string
  cwd: string
  env: Readonly<Record<string, string | undefined>>
  focusFiles?: readonly string[]
}>
