// 注入器 · 渲染层
//
// 把检索/采集到的结构化数据渲染成可注入系统提示词的字符串块。
// 纯函数，不依赖 DB / 网络 / state——从 injector.js 拆出，便于单独维护与测试。
// 历史上这些 format* 函数都挤在 injector.js 里，跟检索逻辑耦合不强，是最自然的切口。

function summarizeUISignals(signals = []) {
  if (!signals.length) return ''
  const now = Date.now()
  const lines = signals.map(s => {
    const age = Math.max(0, Math.round((now - s.ts) / 1000))
    let payload = {}
    try { payload = JSON.parse(s.payload || '{}') } catch {}
    const target = s.target ? ` (${s.target})` : ''
    let desc = s.type
    if (s.type === 'card.mounted')        desc = `Card finished mounting${target}`
    else if (s.type === 'card.dismissed') desc = `User dismissed the card${target} (${payload.by || 'unknown'}, dwell ${Math.round((payload.dwell_ms||0)/1000)}s)`
    else if (s.type === 'card.dwell')     desc = `Card dwell ${Math.round((payload.dwell_ms||0)/1000)}s${target}`
    else if (s.type === 'card.action')    desc = `User acted on card: ${payload.action || ''}${target}`
    else if (s.type === 'card.error')     desc = `Card error: ${payload.message || ''}${target}`
    return `- ${age}s ago: ${desc}`
  })
  return `UI behavior from the past minute. This is context only; do not speak proactively just because of it:\n${lines.join('\n')}`
}
export { summarizeUISignals }

// 渲染成 <temporal-recall> 块的字符串（多个区间各自一段）。
// 给 prompt.js / system-prompt-preview.js 用，injector 只负责出 buckets 数据。
export function formatTemporalRecall(buckets) {
  if (!buckets || buckets.length === 0) return ''
  return buckets.map(b => {
    const lines = b.memories.map(m => {
      const timePart = (m.timestamp || '').slice(11, 16) // HH:MM
      const star = (m.salience ?? 3) >= 4 ? '★ ' : ''
      const title = m.title ? m.title.replace(/^专注结论：/, '').trim() : ''
      const topicHint = title ? `[${title}] ` : ''
      const body = (m.content || '').replace(/\s+/g, ' ').trim()
      return `- ${timePart} ${star}${topicHint}${body}`
    }).join('\n')
    return `<temporal-recall date="${b.date}" label="${b.label}">\n${lines}\n</temporal-recall>`
  }).join('\n\n')
}

// 从 memory.tags（JSON 字符串）中解出 body_path 标签
function extractBodyPath(memory) {
  try {
    const tags = JSON.parse(memory.tags || '[]')
    if (!Array.isArray(tags)) return null
    const tag = tags.find(t => typeof t === 'string' && t.startsWith('body_path:'))
    return tag ? tag.replace('body_path:', '') : null
  } catch {
    return null
  }
}

// 普通记忆：摘要行，带类型标签和 title（如有）。article 类型附正文路径提示。
// RECALL 记忆：带完整 detail
export function formatMemoriesForPrompt(memories, recallMemories = []) {
  const parts = []

  if (memories?.length > 0) {
    parts.push(memories.map(memory => {
      const typeLabel = memory.event_type ? `[${memory.event_type}] ` : ''
      const titlePart = memory.title ? `《${memory.title}》 ` : ''
      const bodyPath = extractBodyPath(memory)
      const bodyHint = bodyPath ? `\n  ↳ Full text: read_file("${bodyPath}")` : ''
      const salienceMark = memory.salience >= 4 ? ` ★${memory.salience}` : ''
      return `- [${memory.timestamp.slice(0, 10)}${salienceMark}] ${typeLabel}${titlePart}${memory.content}${bodyHint}`
    }).join('\n'))
  }

  if (recallMemories?.length > 0) {
    parts.push('[Recall details]\n' + recallMemories.map(memory => {
      const titlePart = memory.title ? `《${memory.title}》 ` : ''
      const bodyPath = extractBodyPath(memory)
      const bodyHint = bodyPath ? `\n  ↳ Full text: read_file("${bodyPath}")` : ''
      return `- [${memory.timestamp.slice(0, 10)}] ${titlePart}${memory.content}\n  ${memory.detail}${bodyHint}`
    }).join('\n'))
  }

  return parts.join('\n\n')
}

// 预热缓存：格式化注入文本
export function formatPrefetchedItems(prefetchedItems = []) {
  if (!prefetchedItems?.length) return ''
  const body = prefetchedItems.map(item => {
    const fetchedTime = item.fetched_at?.slice(11, 16) || ''
    return `[${item.source}] (${fetchedTime} already fetched)\n${item.content}`
  }).join('\n\n')
  return body + '\n\nThe data above has already been prefetched. Use it directly and phrase the response naturally; do not reuse the same sentence pattern every time.'
}

// 当前屏幕上的存活 ACUI 卡片列表
export function formatActiveUICards(cards = []) {
  if (!cards?.length) return ''
  const lines = cards.map(c => `  - id="${c.id}"  component=${c.component}`)
  return `[Active UI cards on screen]\n${lines.join('\n')}\nUse ui_hide with the id to close a card; use ui_update to update its content.`
}

// AI 视频生成面板「感知」：把面板开关状态 + 用户正在编辑的提示词草稿贴进上下文。
// state 来自 media.js 的 getAIVideoPanelState()。面板关闭且无草稿时不渲染（零噪声）。
export function formatAIVideoPanel(state) {
  if (!state || (!state.open && !state.prompt)) return ''
  const lines = ['<aivideo-panel>']
  lines.push(state.open ? 'AI 视频生成面板：当前已打开。' : 'AI 视频生成面板：当前已关闭。')
  const draft = String(state.prompt || '').trim()
  if (draft) {
    lines.push(`用户在提示词输入框里的当前草稿："${draft}"`)
    lines.push('如果用户让你"优化/改写提示词"，直接基于上面这段草稿改——你已经看得到它，不要再追问用户写了什么。')
    lines.push('默认只在对话里给出改写后的版本让用户过目；不要自动覆盖输入框。只有用户明确表示"采用/就用这个"之后，才调用 generate_video(action="set_prompt", prompt="…") 把它写回输入框。用户也可以自己从你的回复里复制粘贴。')
  } else if (state.open) {
    lines.push('提示词输入框当前为空。')
  }
  lines.push('</aivideo-panel>')
  return lines.join('\n')
}

// 任务知识库：显示完整 content + detail
export function formatTaskKnowledge(taskKnowledge = []) {
  if (!taskKnowledge?.length) return ''
  return taskKnowledge.map(memory => {
    const tags = JSON.parse(memory.tags || '[]')
    const kindTag = tags.find(tag => tag.startsWith('kind:'))
    const kind = kindTag ? kindTag.replace('kind:', '') : ''
    const prefix = kind ? `[${kind}] ` : ''
    return `${prefix}${memory.content}\n  ${memory.detail}`
  }).join('\n')
}
