/**
 * 桌面端 SSE 适配器（B）— 把 AgentCallbacks 恒等映射成 SSE event emit。
 *
 * 替换原 route.ts 的 drainQuery + MessageMapper 直用。零行为变化：
 * SSE 事件流（type/字段/顺序）与原 mapper.mapMessage 输出逐事件等价。
 * done / attachment 事件不在此处理由 route.ts 组装（需 DB messageId + fs 拷贝）。
 */

import type { AgentCallbacks, AgentContentEvent } from '../agent-types'
import type { SseEvent } from '../adapters/claude/message-mapper'

/** 创建把 AgentCallbacks 恒等 emit 成 SSE 事件的回调集。 */
export function createSseCallbacks(emit: (event: SseEvent) => void | Promise<void>): AgentCallbacks {
  return {
    onTextDelta: async (text) => { await emit({ type: 'text_delta', text }) },
    onThinkingStart: async () => { await emit({ type: 'thinking_start' }) },
    onThinkingDelta: async (text) => { await emit({ type: 'thinking_delta', text }) },
    onToolUseStart: async (id, name) => {
      console.log('[semantic] tool_use_start', { id, name })
      await emit({ type: 'tool_use_start', id, name })
    },
    onToolUse: async (id, name, input) => { await emit({ type: 'tool_use', id, name, input }) },
    onToolResult: async (toolUseId, name, result, isError) => {
      await emit({ type: 'tool_result', tool_use_id: toolUseId, name, result, is_error: isError })
    },
    onToolRawResult: async (toolUseId, toolName, rawContent) => {
      await emit({ type: 'tool_raw_result', tool_use_id: toolUseId, tool_name: toolName, raw_content: rawContent })
    },
    onToolProgress: async (toolUseId, toolName, elapsedSeconds) => {
      await emit({ type: 'tool_progress', tool_use_id: toolUseId, tool_name: toolName, elapsed_time_seconds: elapsedSeconds })
    },
    onQuestionRequest: async (req) => {
      console.log('[semantic] question_request', req)
      await emit({ type: 'question_request', tool_use_id: req.toolUseId, input: req.input, questions: req.questions })
    },
    onPlanReviewRequest: async (req) => {
      console.log('[semantic] plan_review_request', req)
      await emit({
        type: 'plan_review_request',
        tool_use_id: req.toolUseId,
        input: req.input,
        ...(req.planContent !== undefined ? { plan_content: req.planContent } : {}),
      })
    },
    onTodoUpdate: async (req) => {
      console.log('[semantic] todo_update', req)
      await emit({ type: 'todo_update', tool_use_id: req.toolUseId, input: req.input, todos: req.todos })
    },
    onSessionInit: async (event) => {
      console.log('[semantic] session_init', event)
      await emit({ type: 'session_init', session_id: event.sessionId, ...(event.model ? { model: event.model } : {}) })
    },
    onCancelled: async (event) => {
      console.log('[semantic] cancelled', event)
      await emit({ type: 'cancelled', reason: event.reason })
    },
    onApiRetry: async (event) => {
      console.log('[semantic] api_retry', event)
      await emit({
        type: 'api_retry',
        ...(event.attempt !== undefined ? { attempt: event.attempt } : {}),
        ...(event.maxRetries !== undefined ? { max_retries: event.maxRetries } : {}),
        ...(event.retryDelayMs !== undefined ? { retry_delay_ms: event.retryDelayMs } : {}),
        ...(event.errorStatus !== undefined ? { error_status: event.errorStatus } : {}),
        ...(event.error !== undefined ? { error: event.error } : {}),
      })
    },
    onWebSearchResult: async (event) => {
      console.log('[semantic] web_search_result', event)
      await emit({ type: 'web_search_result', tool_use_id: event.toolUseId, results: event.results })
    },
    onToolSummary: async (event) => {
      console.log('[semantic] tool_summary', event)
      await emit({ type: 'tool_summary', tool_use_ids: event.toolUseIds, summary: event.summary })
    },
    onAgentStart: async (event) => {
      console.log('[semantic] agent_start', event)
      await emit({
        type: 'agent_start',
        parent_tool_use_id: event.parentToolUseId,
        ...(event.description !== undefined ? { description: event.description } : {}),
        ...(event.prompt !== undefined ? { prompt: event.prompt } : {}),
      })
    },
    onAgentDone: async (event) => {
      console.log('[semantic] agent_done', event)
      await emit({
        type: 'agent_done',
        parent_tool_use_id: event.parentToolUseId,
        status: event.status,
        ...(event.inputTokens !== undefined ? { input_tokens: event.inputTokens } : {}),
        ...(event.outputTokens !== undefined ? { output_tokens: event.outputTokens } : {}),
      })
    },
    onAgentError: async (event) => {
      console.log('[semantic] agent_error', event)
      await emit({
        type: 'agent_error',
        parent_tool_use_id: event.parentToolUseId,
        error: event.error,
        ...(event.category !== undefined ? { category: event.category } : {}),
      })
    },
    onAgentContent: async (parentToolUseId, block) => {
      await emit({ type: 'agent_content', parent_tool_use_id: parentToolUseId, block_type: block.blockType, ...pickAgentFields(block) })
    },
    onError: async (error, category) => {
      console.log('[semantic] error', { error, category })
      await emit({ type: 'error', error, ...(category ? { category } : {}) })
    },
    // onUsage / onSdkSession / onBlock / onDone / onFirstEvent 不 emit —— 由 route.ts 从 AgentResult 组装 done
  }
}

/** AgentContentEvent（camelCase）→ SSE agent_content 的 snake_case 字段（往返于 dispatcher 的 mapAgentContent）。 */
function pickAgentFields(block: AgentContentEvent): Record<string, unknown> {
  const out: Record<string, unknown> = {}
  if (block.text !== undefined) out.text = block.text
  if (block.id !== undefined) out.id = block.id
  if (block.name !== undefined) out.name = block.name
  if (block.input !== undefined) out.input = block.input
  if (block.toolUseId !== undefined) out.tool_use_id = block.toolUseId
  if (block.content !== undefined) out.content = block.content
  if (block.isError !== undefined) out.is_error = block.isError
  if (block.elapsedSeconds !== undefined) out.elapsed_time_seconds = block.elapsedSeconds
  return out
}
