import type {
  Message,
  ToolCall,
  ToolResult,
} from '#cli/core/model'
import {
  guessLanguageFromFilePath,
  highlightCodePreviewToAnsi,
} from '../syntax-highlight'

function findToolNameForCall(
  messages: readonly Message[],
  assistantId: string,
  callId: string,
): string | null {
  const msg = messages.find((m) => m.id === assistantId)
  if (!msg || msg.role !== 'assistant') return null
  const part = msg.parts.find(
    (p) => p.type === 'tool_call' && p.call.id === callId,
  ) as any
  return part?.call?.name ? String(part.call.name) : null
}

function findToolCallForCall(
  messages: readonly Message[],
  assistantId: string,
  callId: string,
): ToolCall | null {
  const msg = messages.find((m) => m.id === assistantId)
  if (!msg || msg.role !== 'assistant') return null
  const part = msg.parts.find(
    (p) => p.type === 'tool_call' && p.call.id === callId,
  ) as any
  return part?.call ? (part.call as ToolCall) : null
}

function extractFilePathFromToolCallArgs(
  args: Record<string, unknown> | undefined,
): string | null {
  const a = args ?? {}
  const candidates = [
    (a as any).file_path,
    (a as any).filePath,
    (a as any).path,
  ]
  for (const v of candidates) {
    if (typeof v === 'string' && v.trim()) return v.trim()
  }
  return null
}

function shouldHighlightToolResult(
  toolName: string | null,
  filePath: string | null,
): boolean {
  void toolName
  void filePath
  return false
}

export function scheduleToolResultHighlight(
  opts: Readonly<{
    state: Readonly<{ messages: Message[] }>
    assistantId: string
    result: ToolResult
    updateAssistant: (
      assistantId: string,
      fn: (
        m: Extract<Message, { role: 'assistant' }>,
      ) => Extract<Message, { role: 'assistant' }>,
    ) => void
  }>,
): void {
  const callId = String(opts.result.toolCallId ?? '').trim()
  if (!callId) return
  const toolName = findToolNameForCall(
    opts.state.messages,
    opts.assistantId,
    callId,
  )
  const call = findToolCallForCall(
    opts.state.messages,
    opts.assistantId,
    callId,
  )
  const filePath = extractFilePathFromToolCallArgs(call?.arguments as any)
  if (!shouldHighlightToolResult(toolName, filePath)) return

  const lang = guessLanguageFromFilePath(filePath!)
  if (!lang) return

  void (async () => {
    const outputAnsi = await highlightCodePreviewToAnsi({
      code: opts.result.output,
      language: lang,
      maxLines: 10,
    })
    if (!outputAnsi || !outputAnsi.trim()) return
    opts.updateAssistant(opts.assistantId, (m) => {
      const parts = m.parts.slice()
      const idx = parts.findIndex(
        (p) => p.type === 'tool_result' && p.result.toolCallId === callId,
      )
      if (idx < 0) return m
      const prevPart = parts[idx] as Extract<
        (typeof parts)[number],
        { type: 'tool_result' }
      >
      if (prevPart.result.output !== opts.result.output) return m
      if (prevPart.result.outputAnsi && prevPart.result.outputAnsi.trim())
        return m
      parts[idx] = {
        type: 'tool_result',
        result: { ...prevPart.result, outputAnsi },
      } as const
      return { ...m, parts }
    })
  })()
}
