import type { Message } from '#cli/core/model'
import type { DimSdkStore } from '#cli/core/store'
import type { DimSdkSessionsApi } from '../../../keys'

/**
 * Build a copy-friendly text representation of a message.
 *
 * This is used by the "Message Actions" menu.
 */
export function messageToPlainText(msg: Message): string {
  if (msg.role === 'user') return String(msg.content ?? '')
  if (msg.role === 'tool') return String(msg.result.output ?? '')

  // assistant
  return msg.parts
    .map((p) => {
      if (p.type === 'markdown') return String(p.markdown ?? '')
      if (p.type === 'thinking') return String(p.content ?? '')
      if (p.type === 'status') return String(p.text ?? '')
      return ''
    })
    .filter(Boolean)
    .join('\n')
}

/**
 * Remove transient assistant UI parts when creating a forked transcript seed.
 *
 * The forked session should preserve the real content (markdown + tool calls/results),
 * but drop ephemeral status text that is only meaningful during streaming.
 */
export function sanitizeForkMessage(m: Message): Message {
  if (m.role !== 'assistant') return m
  const parts = m.parts.filter(
    (p) =>
      p.type !== 'status' && p.type !== 'thinking' && p.type !== 'tool_output',
  )
  return { ...m, parts }
}

export function buildForkSeed(
  messages: readonly Message[],
  targetMessageId: string,
): Message[] | null {
  const idx = messages.findIndex((m) => m.id === targetMessageId)
  if (idx < 0) return null
  return messages.slice(0, idx).map(sanitizeForkMessage)
}

export function findTurnStartMessageId(
  messages: readonly Message[],
  targetMessageId: string,
): string | null {
  const idx = messages.findIndex((m) => m.id === targetMessageId)
  if (idx < 0) return null
  for (let i = idx; i >= 0; i--) {
    const message = messages[i]
    if (message?.role === 'user') return message.id
  }
  const target = messages[idx]
  return target ? target.id : null
}

/**
 * Fork the current session using the most capable available API.
 *
 * Fallback order:
 * - `sessionsApi.fork({ messages })` (preferred, persists server-side)
 * - `sessionsApi.createNew()` then replace in-memory transcript
 * - no sessions API: clear session id and replace in-memory transcript
 */
export async function forkSession(
  opts: Readonly<{
    sessionsApi: DimSdkSessionsApi | undefined
    store: DimSdkStore
    seed: readonly Message[]
  }>,
): Promise<void> {
  const api: any = opts.sessionsApi as any
  if (api && typeof api.fork === 'function') {
    await api.fork({ messages: opts.seed })
    return
  }

  if (opts.sessionsApi) {
    await opts.sessionsApi.createNew()
    opts.store.replaceMessages(opts.seed)
    opts.store.clearRevertedMessages()
    opts.store.state.selectedToolCallId = null
    return
  }

  // Non-persistent runtime: clear UI state and let the agent create a new session id on the next send.
  opts.store.state.sessionId = ''
  opts.store.replaceMessages(opts.seed)
  opts.store.clearRevertedMessages()
  opts.store.state.selectedToolCallId = null
  opts.store.state.usage.prompt_tokens = 0
  opts.store.state.usage.completion_tokens = 0
  opts.store.state.usage.total_tokens = 0
  opts.store.state.lastRequestBudget = null
}
