import { ref, computed } from 'vue'
import { useMessage } from 'naive-ui'
import {
  listSessions,
  createSession,
  getSession,
  updateSession as apiUpdateSession,
  startRun,
  submitClarify as apiSubmitClarify,
  deleteSession as apiDeleteSession,
  exportSession as apiExportSession,
  resetSession as apiResetSession,
  regenerateMessage as apiRegenerate,
  editMessage as apiEditMessage,
  activateMessageVersion as apiActivateVersion
} from '../api/chat'
import { useGlobalRuns } from './useGlobalRuns'

/**
 * 单会话对话状态机。
 *
 * <p>对应设计文档 {@code docs/design/agent-chat-page-design.md} §5.4。
 * 职责：</p>
 * <ul>
 *   <li>加载会话列表 / 切换会话 / 加载会话历史</li>
 *   <li>发送消息 → 调 {@link startRun} → 注册到 {@link useGlobalRuns}</li>
 *   <li>把全局 Run 池推送的事件流追加到对应 assistant 消息的 logs</li>
 *   <li>暴露 pendingAsk（当前等待用户回答的 clarify）给视图</li>
 *   <li>提交 clarify 答案</li>
 * </ul>
 *
 * <p>注：版本管理（重新生成/编辑）在阶段 4 加；这里先留接口。</p>
 */
export function useChat() {
  const message = useMessage()
  const globalRuns = useGlobalRuns()

  // 会话列表 + 当前会话 + 当前消息
  const sessions = ref([])
  const currentSessionId = ref(null)
  const session = ref(null)
  const messages = ref([])

  // 当前会话对应的 runId（用于从 globalRuns 拉事件流）
  const currentRunId = computed(() => {
    if (!currentSessionId.value) return null
    // 找该 session 下最后一个 RUNNING run
    for (const runId of globalRuns.listRunIds()) {
      const r = globalRuns.getRun(runId)
      if (r && r.sessionId === currentSessionId.value && r.status === 'RUNNING') {
        return runId
      }
    }
    return null
  })

  // 当前会话的 pendingAsk（来自 globalRuns 中所有该 session 的 run）
  const pendingAsk = computed(() => {
    if (!currentSessionId.value) return null
    for (const runId of globalRuns.listRunIds()) {
      const r = globalRuns.getRun(runId)
      if (r && r.sessionId === currentSessionId.value && r.pendingAsk) {
        return r.pendingAsk
      }
    }
    return null
  })

  const sending = ref(false)

  /* ============== 会话管理 ============== */

  async function loadSessions() {
    try {
      const res = await listSessions()
      sessions.value = res.data || []
    } catch (e) {
      message.error('加载会话列表失败：' + e.message)
    }
  }

  async function selectSession(sessionId) {
    currentSessionId.value = sessionId
    session.value = null
    messages.value = []
    try {
      const res = await getSession(sessionId)
      if (res.data) {
        session.value = res.data.session
        messages.value = (res.data.messages || []).map(normalizeMessage)
        // 关键修复：会话内若有 RUNNING 中的 assistant 消息（如刷新页面/路由切换后回来），
        // 必须把它们重新绑定到 globalRuns 的事件流，否则 UI 永远停在"思考中..."
        reattachRunningRuns(sessionId)
      }
    } catch (e) {
      message.error('加载会话失败：' + e.message)
    }
  }

  /**
   * 把会话内所有 RUNNING 状态的 assistant 消息重新挂到 globalRuns 的事件流。
   *
   * <p>覆盖两个场景：
   * <ul>
   *   <li>页面刷新：globalRuns 模块单例重置，pool 为空 → register 触发新的 SSE 订阅</li>
   *   <li>路由切换回来：globalRuns pool 还在 → register 幂等返回，attachView 重放历史事件</li>
   * </ul>
   * 注意：attachView 的回调用 messageId 动态查找消息，避免 reloadCurrentSession
   * 后引用孤立导致新事件落不到 UI。</p>
   */
  function reattachRunningRuns(sessionId) {
    for (const m of messages.value) {
      if (m.role === 'ASSISTANT' && m.status === 'RUNNING' && m.runId) {
        const runId = m.runId
        const assistantMsgId = m.id
        globalRuns.register(runId, sessionId, assistantMsgId)
        globalRuns.attachView(runId, (evt, entry) => {
          const cur = messages.value.find(x => x.id === assistantMsgId)
          if (cur) onRunEvent(cur, evt, entry)
        })
      }
    }
  }

  async function newSession(payload = {}) {
    try {
      const res = await createSession(payload)
      if (res.data) {
        await loadSessions()
        await selectSession(res.data.sessionId)
      }
    } catch (e) {
      message.error('创建会话失败：' + e.message)
    }
  }

  /* ============== 发送消息 ============== */

  /**
   * 发送一条用户消息并启动 run。
   * @param {string} text
   * @param {Object} opts {modelId?, skillFolder?, maxIterations?, parentMessageId?}
   */
  async function send(text, opts = {}) {
    if (!currentSessionId.value) {
      message.warning('请先选择或创建会话')
      return
    }
    if (!text || !text.trim() || sending.value) return

    sending.value = true

    // 乐观插入 user 消息
    const parentId = opts.parentMessageId != null
      ? opts.parentMessageId
      : (messages.value.length > 0 ? messages.value[messages.value.length - 1].id : null)
    const tempUserMsg = {
      id: `tmp-user-${Date.now()}`,
      parentId,
      role: 'USER',
      content: text,
      status: 'SENT',
      logs: [],
      isActive: true
    }
    messages.value.push(tempUserMsg)

    // 占位 assistant 消息（runId 后填）
    const tempAssistantMsg = {
      id: `tmp-assistant-${Date.now()}`,
      parentId: tempUserMsg.id,
      role: 'ASSISTANT',
      content: '',
      status: 'RUNNING',
      logs: [],
      isActive: true,
      _runId: null
    }
    messages.value.push(tempAssistantMsg)
    const assistantIdx = messages.value.length - 1

    try {
      const res = await startRun(currentSessionId.value, {
        message: text,
        modelId: opts.modelId ?? null,
        skillFolder: opts.skillFolder ?? null,
        maxIterations: opts.maxIterations ?? null,
        parentMessageId: opts.parentMessageId ?? null
      })
      if (!res.data) {
        throw new Error('启动 run 失败')
      }
      const { runId, messageId } = res.data
      // 用 splice 替换占位消息，让 Vue 通过新引用正确 diff（key 变化会触发 DOM 重建）
      messages.value.splice(assistantIdx, 1, {
        ...tempAssistantMsg,
        id: messageId,
        _runId: runId
      })
      // 注册到全局 run 池，附加视图回调
      // 注意：回调里用 messageId 动态查找消息，避免 reloadCurrentSession 后引用孤立
      globalRuns.register(runId, currentSessionId.value, messageId)
      globalRuns.attachView(runId, (evt, entry) => {
        const cur = messages.value.find(m => m.id === messageId)
        if (cur) onRunEvent(cur, evt, entry)
      })
    } catch (e) {
      // 失败回滚：移除乐观插入的 user + assistant 占位消息，避免重发时累积重复条目
      messages.value = messages.value.filter(
        m => m.id !== tempUserMsg.id && m.id !== tempAssistantMsg.id
      )
      sending.value = false
      message.error('发送失败：' + e.message)
    }
  }

  /**
   * 全局 Run 池推送的事件 → 追加到对应 assistant 消息的 logs。
   */
  function onRunEvent(assistantMsg, evt, entry) {
    if (evt.event === 'node_stream') {
      const { kind, content, toolName } = evt.data || {}
      assistantMsg.logs.push({ kind, content, toolName, at: evt.at })
    } else if (evt.event === 'workflow_complete') {
      assistantMsg.status = 'SUCCESS'
      const reply = evt.data && evt.data.output && evt.data.output.reply
      if (reply) {
        assistantMsg.content = reply
      }
      // 重新加载会话以拿到后端持久化的最终 content
      reloadCurrentSession()
      sending.value = false
    } else if (evt.event === 'workflow_error') {
      assistantMsg.status = 'FAILED'
      assistantMsg.error = (evt.data && evt.data.error) || '运行失败'
      sending.value = false
    }
  }

  async function reloadCurrentSession() {
    if (!currentSessionId.value) return
    try {
      const res = await getSession(currentSessionId.value)
      if (res.data) {
        session.value = res.data.session
        // 保留正在运行中的临时消息，仅替换已完成/历史的
        const runningSet = new Set(
          messages.value.filter(m => m.status === 'RUNNING').map(m => m.id)
        )
        messages.value = (res.data.messages || [])
          .map(normalizeMessage)
          // 若某条消息本地仍标记为 RUNNING，则保留本地版本（避免被后端 RUNNING 覆盖）
          .map(m => runningSet.has(m.id) ? messages.value.find(x => x.id === m.id) || m : m)
      }
    } catch (e) {
      console.warn('[useChat] reloadCurrentSession 失败', e?.message || e)
    }
  }

  /* ============== Clarify ============== */

  async function answerClarify(clarifyId, answer) {
    if (!currentRunId.value || !pendingAsk.value) return
    try {
      await apiSubmitClarify(currentRunId.value, clarifyId, answer)
      // 立即清除本地 pendingAsk，避免用户重复点击提交按钮
      globalRuns.clearPendingAsk(currentRunId.value)
    } catch (e) {
      message.error('提交答案失败：' + e.message)
    }
  }

  /* ============== 会话级操作（删除 / 导出 / 重置） ============== */

  /** 删除（归档）当前会话；删除后回到空状态。 */
  async function deleteCurrentSession() {
    if (!currentSessionId.value) return
    const targetId = currentSessionId.value
    try {
      await apiDeleteSession(targetId)
      sessions.value = sessions.value.filter(s => s.id !== targetId)
      if (currentSessionId.value === targetId) {
        currentSessionId.value = null
        session.value = null
        messages.value = []
      }
    } catch (e) {
      message.error('删除会话失败：' + e.message)
    }
  }

  /** 删除指定 id 的会话（侧栏操作）。 */
  async function deleteSessionById(sessionId) {
    try {
      await apiDeleteSession(sessionId)
      sessions.value = sessions.value.filter(s => s.id !== sessionId)
      if (currentSessionId.value === sessionId) {
        currentSessionId.value = null
        session.value = null
        messages.value = []
      }
    } catch (e) {
      message.error('删除会话失败：' + e.message)
    }
  }

  /** 重命名会话。 */
  async function renameSession(sessionId, title) {
    try {
      const res = await apiUpdateSession(sessionId, { title })
      if (res.data) {
        // 局部更新列表项 + 当前 session
        const idx = sessions.value.findIndex(s => s.id === sessionId)
        if (idx !== -1) sessions.value[idx] = { ...sessions.value[idx], ...res.data }
        if (currentSessionId.value === sessionId && session.value) {
          session.value = { ...session.value, ...res.data }
        }
      }
    } catch (e) {
      message.error('重命名失败：' + e.message)
      throw e
    }
  }

  /** 切换置顶。pinned 为当前状态，传 true 时切换为 false，反之亦然。 */
  async function togglePinSession(sessionId, currentPinned) {
    try {
      const res = await apiUpdateSession(sessionId, { pinned: !currentPinned })
      if (res.data) {
        const idx = sessions.value.findIndex(s => s.id === sessionId)
        if (idx !== -1) sessions.value[idx] = { ...sessions.value[idx], ...res.data }
        if (currentSessionId.value === sessionId && session.value) {
          session.value = { ...session.value, ...res.data }
        }
      }
    } catch (e) {
      message.error('置顶失败：' + e.message)
      throw e
    }
  }

  /** 导出当前会话为 Markdown（浏览器自动下载）。 */
  async function exportCurrentSession() {
    if (!currentSessionId.value) return
    try {
      await apiExportSession(currentSessionId.value)
      message.success('已开始下载对话记录')
    } catch (e) {
      message.error('导出失败：' + e.message)
    }
  }

  /** 重置当前会话：清空对话历史（软清空，不删数据）。 */
  async function resetCurrentSession() {
    if (!currentSessionId.value) return
    try {
      await apiResetSession(currentSessionId.value)
      messages.value = []
      await loadSessions()
      message.success('已重置会话')
    } catch (e) {
      message.error('重置失败：' + e.message)
    }
  }

  /* ============== 版本管理（重新生成 / 编辑 / 切换） ============== */

  /**
   * 重新生成指定的 assistant 消息。
   * 后端会创建同 parent 的新 assistant 占位 + 触发 run。
   * 前端：把旧 assistant 标 inactive（移除），插入新的占位消息。
   */
  async function regenerateMessage(msgId) {
    try {
      const res = await apiRegenerate(msgId)
      if (!res.data) return
      const { runId, messageId } = res.data
      // 找旧消息位置，替换为新占位
      const idx = messages.value.findIndex(m => m.id === msgId)
      if (idx === -1) return
      const old = messages.value[idx]
      const placeholder = {
        id: messageId,
        parentId: old.parentId,
        role: 'ASSISTANT',
        content: '',
        status: 'RUNNING',
        logs: [],
        isActive: true,
        _runId: runId
      }
      messages.value.splice(idx, 1, placeholder)
      // 注册到全局 run 池
      globalRuns.register(runId, currentSessionId.value, messageId)
      globalRuns.attachView(runId, (evt, entry) => {
        const cur = messages.value.find(m => m.id === messageId)
        if (cur) onRunEvent(cur, evt, entry)
      })
    } catch (e) {
      message.error('重新生成失败：' + e.message)
    }
  }

  /**
   * 编辑 user 消息：后端创建新 user 版本 + 新 assistant 占位 + 触发 run。
   * 前端：移除旧 user 与其下所有 assistant，追加新 user + 占位 assistant。
   */
  async function editUserMessage(msgId, newContent) {
    try {
      const res = await apiEditMessage(msgId, newContent)
      if (!res.data) return
      const { runId, messageId } = res.data
      const idx = messages.value.findIndex(m => m.id === msgId)
      if (idx === -1) return
      const oldUser = messages.value[idx]
      // 把旧 user 及其后所有消息移除（让重载后只看到新版本链）
      messages.value = messages.value.slice(0, idx)
      const newUser = {
        id: `tmp-user-${Date.now()}`,
        parentId: oldUser.parentId,
        role: 'USER',
        content: newContent,
        status: 'SENT',
        logs: [],
        isActive: true
      }
      messages.value.push(newUser)
      const placeholder = {
        id: messageId,
        parentId: newUser.id,
        role: 'ASSISTANT',
        content: '',
        status: 'RUNNING',
        logs: [],
        isActive: true,
        _runId: runId
      }
      messages.value.push(placeholder)
      globalRuns.register(runId, currentSessionId.value, messageId)
      globalRuns.attachView(runId, (evt, entry) => {
        const cur = messages.value.find(m => m.id === messageId)
        if (cur) onRunEvent(cur, evt, entry)
      })
    } catch (e) {
      message.error('编辑失败：' + e.message)
    }
  }

  /**
   * 切换激活版本。后端切完后，前端 reload 当前会话以拿到新 active 分支。
   */
  async function activateVersion(msgId) {
    if (!currentSessionId.value) return
    try {
      await apiActivateVersion(msgId)
      await reloadCurrentSession()
    } catch (e) {
      message.error('切换版本失败：' + e.message)
    }
  }

  /* ============== 工具 ============== */

  /** 把后端返回的消息标准化为前端使用的对象 */
  function normalizeMessage(m) {
    return {
      id: m.id,
      parentId: m.parentId,
      role: m.role,
      content: m.content || '',
      status: m.status,
      runId: m.runId,
      branchOrder: m.branchOrder,
      isActive: m.isActive,
      modelId: m.modelId,
      skillFolder: m.skillFolder,
      error: m.error,
      createdAt: m.createdAt,
      completedAt: m.completedAt,
      logs: Array.isArray(m.logs) ? m.logs.map(normalizeLog) : []
    }
  }

  function normalizeLog(l) {
    return {
      kind: l.kind,
      content: l.content,
      toolName: l.toolName,
      metaJson: l.metaJson,
      seq: l.seq,
      createdAt: l.createdAt
    }
  }

  return {
    // state
    sessions,
    currentSessionId,
    session,
    messages,
    sending,
    pendingAsk,
    currentRunId,
    // actions - 会话/消息基础
    loadSessions,
    selectSession,
    newSession,
    send,
    answerClarify,
    // actions - 会话级（删除/导出/重置/重命名/置顶）
    deleteCurrentSession,
    deleteSessionById,
    renameSession,
    togglePinSession,
    exportCurrentSession,
    resetCurrentSession,
    // actions - 版本管理
    regenerateMessage,
    editUserMessage,
    activateVersion
  }
}
