import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
import { useConversationStore } from '@/stores/conversation'
import { useAuthStore } from '@/stores/auth'
import {
  conversationApi,
  type ChatProgressEvent,
  type Message,
} from '@/api/conversation'
import { documentApi } from '@/api/document'
import { settingsApi, type LLMModelConfig } from '@/api/settings'
import { systemApi } from '@/api/system'

export interface SelectedFile {
  id: string
  name: string
  type: string
  size: number
}

interface MessageWithAttachments extends Message {
  attachments?: SelectedFile[]
}

interface ThinkingState {
  stage: ChatProgressEvent['stage']
  label: string
  agent?: string | null
  toolName?: string | null
  step?: string | null
  steps: string[]
}

interface OrchestrationEventItem {
  id: string
  label: string
  kind: 'info' | 'tool' | 'success' | 'error'
}

interface OrchestrationInsight {
  statusTitle: string
  systemSummary: string
  jarvisNote: string
}

interface TelemetryMetricState {
  current: number | null
  series: number[]
  online: boolean
}

interface SystemTelemetryState {
  cpu: TelemetryMetricState
  memory: TelemetryMetricState
  disk: TelemetryMetricState
}

interface SessionTelemetryState {
  activitySeries: number[]
  eventsCount: number
  toolCount: number
  agentCount: number
}

type OrchestrationStatus = 'idle' | 'active' | 'complete' | 'error'

export function useChatView() {
  const store = useConversationStore()
  const auth = useAuthStore()
  const inputMessage = ref('')
  const isSending = ref(false)
  const chatContainer = ref<HTMLElement>()
  const inputRef = ref<HTMLTextAreaElement>()
  const isTyping = ref(false)
  const fileInputRef = ref<HTMLInputElement>()
  const showEmojiPicker = ref(false)
  const selectedFiles = ref<SelectedFile[]>([])
  const chatModels = ref<LLMModelConfig[]>([])
  const selectedModelName = ref('')
  const isLoadingModels = ref(false)
  const conversationsError = ref('')
  const currentSelectionRequestId = ref(0)
  const thinkingState = ref<ThinkingState | null>(null)
  const orchestrationPanelVisible = ref(true)
  const orchestrationStatus = ref<OrchestrationStatus>('idle')
  const orchestrationInsight = ref<OrchestrationInsight>({
    statusTitle: 'STANDBY',
    systemSummary: '等待请求接入',
    jarvisNote: '系统在线。希望下一项任务别太无聊。',
  })
  const activeAgent = ref<string | null>(null)
  const visitedAgents = ref<string[]>([])
  const orchestrationEventFeed = ref<OrchestrationEventItem[]>([])
  const systemTelemetry = ref<SystemTelemetryState>({
    cpu: { current: null, series: [], online: false },
    memory: { current: null, series: [], online: false },
    disk: { current: null, series: [], online: false },
  })
  const sessionTelemetry = ref<SessionTelemetryState>({
    activitySeries: [],
    eventsCount: 0,
    toolCount: 0,
    agentCount: 0,
  })
  const selectedModel = computed(() => chatModels.value.find((model) => model.name === selectedModelName.value) ?? null)
  let systemTelemetryTimer: ReturnType<typeof setInterval> | null = null
  let sessionTelemetryTimer: ReturnType<typeof setInterval> | null = null

  function resetOrchestrationState() {
    orchestrationPanelVisible.value = true
    orchestrationStatus.value = 'idle'
    orchestrationInsight.value = {
      statusTitle: 'STANDBY',
      systemSummary: '等待请求接入',
      jarvisNote: '系统在线。希望下一项任务别太无聊。',
    }
    activeAgent.value = null
    visitedAgents.value = []
    orchestrationEventFeed.value = []
    sessionTelemetry.value = {
      activitySeries: [],
      eventsCount: 0,
      toolCount: 0,
      agentCount: 0,
    }
  }

  function appendTelemetryPoint(series: number[], value: number, limit = 24) {
    return [...series, value].slice(-limit)
  }

  function markSessionActivity(value: number, options?: { tool?: boolean; agent?: string | null }) {
    sessionTelemetry.value = {
      activitySeries: appendTelemetryPoint(sessionTelemetry.value.activitySeries, value),
      eventsCount: sessionTelemetry.value.eventsCount + 1,
      toolCount: sessionTelemetry.value.toolCount + (options?.tool ? 1 : 0),
      agentCount: options?.agent && !visitedAgents.value.includes(options.agent)
        ? sessionTelemetry.value.agentCount + 1
        : sessionTelemetry.value.agentCount,
    }
  }

  function updateSystemTelemetry(metric: keyof SystemTelemetryState, value: number | null, online: boolean) {
    const current = systemTelemetry.value[metric]
    systemTelemetry.value = {
      ...systemTelemetry.value,
      [metric]: {
        current: value,
        online,
        series: value === null ? current.series : appendTelemetryPoint(current.series, value),
      },
    }
  }

  async function loadSystemStatus() {
    try {
      const response = await systemApi.getStatus()
      updateSystemTelemetry('cpu', response.data.cpu_percent, true)
      updateSystemTelemetry('memory', response.data.memory_percent, true)
      updateSystemTelemetry('disk', response.data.disk_percent, true)
    } catch (error) {
      console.error('加载系统状态失败:', error)
      updateSystemTelemetry('cpu', systemTelemetry.value.cpu.current, false)
      updateSystemTelemetry('memory', systemTelemetry.value.memory.current, false)
      updateSystemTelemetry('disk', systemTelemetry.value.disk.current, false)
    }
  }

  function startSystemTelemetryPolling() {
    if (systemTelemetryTimer) clearInterval(systemTelemetryTimer)
    systemTelemetryTimer = setInterval(() => {
      void loadSystemStatus()
    }, 2000)
  }

  function startSessionTelemetryDecay() {
    if (sessionTelemetryTimer) clearInterval(sessionTelemetryTimer)
    sessionTelemetryTimer = setInterval(() => {
      const lastValue = sessionTelemetry.value.activitySeries.at(-1) ?? 0
      const nextValue = Math.max(0, Math.round(lastValue * 0.72) - 2)
      sessionTelemetry.value = {
        ...sessionTelemetry.value,
        activitySeries: appendTelemetryPoint(sessionTelemetry.value.activitySeries, nextValue),
      }
    }, 1200)
  }

  function pushOrchestrationEvent(label: string, kind: OrchestrationEventItem['kind']) {
    const normalized = label.trim()
    if (!normalized) return
    if (orchestrationEventFeed.value.at(-1)?.label === normalized) return
    orchestrationEventFeed.value = [
      ...orchestrationEventFeed.value,
      {
        id: `${Date.now()}-${orchestrationEventFeed.value.length}`,
        label: normalized,
        kind,
      },
    ].slice(-5)
  }

  function buildOrchestrationInsight(payload: ChatProgressEvent): OrchestrationInsight {
    if (payload.stage === 'thinking') {
      return {
        statusTitle: 'ANALYSIS',
        systemSummary: payload.agent ? '正在解析请求并评估处理路径' : '正在解析请求意图',
        jarvisNote: payload.steps?.length
          ? '这件事比表面复杂一点，我宁可先把结构看清。'
          : '这个请求不算棘手，先让我确认范围。',
      }
    }

    if (payload.stage === 'planning') {
      return {
        statusTitle: 'ROUTING',
        systemSummary: payload.agent === 'planner' ? '已路由至 planner，正在拆解任务' : '正在规划执行链路',
        jarvisNote: payload.steps?.length
          ? '问题有几层关系，按顺序拆开会体面很多。'
          : '这一步需要一点秩序感。',
      }
    }

    if (payload.stage === 'tool') {
      return {
        statusTitle: 'EXECUTION',
        systemSummary: payload.tool_name ? `正在调用工具 · ${payload.tool_name}` : '正在执行操作',
        jarvisNote: payload.tool_name
          ? '工具链已接通。希望它今天愿意配合。'
          : '执行阶段开始了，接下来看看链路表现。',
      }
    }

    return {
      statusTitle: 'SYNTHESIS',
      systemSummary: payload.agent === 'analyst' ? 'analyst 正在整理结果' : '结果已收集，正在整理回答',
      jarvisNote: '信息已经够用了，我来把它变得清晰一点。',
    }
  }

  function applyProgressToOrchestration(payload: ChatProgressEvent) {
    orchestrationPanelVisible.value = true
    orchestrationStatus.value = 'active'
    orchestrationInsight.value = buildOrchestrationInsight(payload)
    const isNewAgent = Boolean(payload.agent && !visitedAgents.value.includes(payload.agent))
    activeAgent.value = payload.agent || null
    markSessionActivity(payload.tool_name ? 92 : 68, {
      tool: Boolean(payload.tool_name),
      agent: isNewAgent ? payload.agent || null : null,
    })
    if (payload.agent && isNewAgent) {
      visitedAgents.value = [...visitedAgents.value, payload.agent]
    }

    if (payload.step) {
      pushOrchestrationEvent(payload.step, payload.tool_name ? 'tool' : 'info')
    } else if (payload.tool_name) {
      pushOrchestrationEvent(`调用工具 · ${payload.tool_name}`, 'tool')
    } else {
      pushOrchestrationEvent(payload.label, 'info')
    }
  }

  function finalizeOrchestration(status: Exclude<OrchestrationStatus, 'idle' | 'active'>, finalLabel: string) {
    orchestrationPanelVisible.value = true
    orchestrationStatus.value = status
    orchestrationInsight.value = status === 'error'
      ? {
          statusTitle: 'ERROR',
          systemSummary: '执行中断，等待进一步处理',
          jarvisNote: '结果不理想，不过问题已经开始显形。',
        }
      : {
          statusTitle: 'COMPLETE',
          systemSummary: '执行完成，结果已生成',
          jarvisNote: '很好，问题已经收束。',
        }
    pushOrchestrationEvent(finalLabel, status === 'error' ? 'error' : 'success')
  }

  async function sendMessage() {
    if (!inputMessage.value.trim() || isSending.value) return

    resetOrchestrationState()
    isSending.value = true
    isTyping.value = true
    const text = inputMessage.value.trim()
    const attachments = [...selectedFiles.value]
    const tempMessageId = `temp-${Date.now()}`
    const previousConversationId = store.currentConversationId
    inputMessage.value = ''

    store.addMessage({
      id: tempMessageId,
      role: 'user',
      content: text,
      created_at: new Date().toISOString(),
      attachments,
    } as MessageWithAttachments)

    await nextTick()
    scrollToBottom()

    let finalConversationId = previousConversationId
    let finalMessageId = ''
    let finalContent = ''
    let streamError = ''

    try {
      await conversationApi.chatStream(
        text,
        previousConversationId ?? undefined,
        attachments.map((file) => file.id),
        selectedModelName.value || undefined,
        {
          onMetadata(payload) {
            finalConversationId = payload.conversation_id
            finalMessageId = payload.message_id
            if (previousConversationId === null) {
              store.setCurrentConversation(payload.conversation_id)
            }
          },
          onProgress(payload) {
            thinkingState.value = {
              stage: payload.stage,
              label: payload.label,
              agent: payload.agent,
              toolName: payload.tool_name,
              step: payload.step,
              steps: payload.steps || [],
            }
            applyProgressToOrchestration(payload)
          },
          onChunk(payload) {
            finalContent += payload.content
            markSessionActivity(54)
          },
          onError(message) {
            streamError = message
          },
        },
      )

      if (streamError) {
        throw new Error(streamError)
      }

      selectedFiles.value = []
      isTyping.value = false
      store.addMessage({
        id: finalMessageId || `assistant-${Date.now()}`,
        role: 'assistant',
        content: finalContent || '抱歉，我暂时没有生成可用回复。',
        model: selectedModelName.value || selectedModel.value?.name || 'jarvis',
        created_at: new Date().toISOString(),
      })
      if (finalConversationId && previousConversationId === null) {
        store.setCurrentConversation(finalConversationId)
      }
      finalizeOrchestration('complete', '响应已生成')
      await loadConversations()
    } catch (error: any) {
      isTyping.value = false
      console.error('发送失败:', error)
      const content = error?.message || '抱歉，连接失败。请检查服务状态。'
      finalizeOrchestration('error', content)
      store.removeMessage(tempMessageId)
      store.addMessage({
        id: `err-${Date.now()}`,
        role: 'assistant',
        content,
        created_at: new Date().toISOString(),
      })
    }

    isSending.value = false
    await nextTick()
    scrollToBottom()
  }

  async function loadConversations() {
    conversationsError.value = ''
    try {
      const response = await conversationApi.list()
      store.setConversations(response.data)
    } catch (error) {
      conversationsError.value = '加载会话失败，请稍后重试'
      console.error('加载对话列表失败:', error)
    }
  }

  async function loadChatModels() {
    isLoadingModels.value = true
    try {
      const response = await settingsApi.get()
      const chatModelsList = (response.data.llm_config?.chat || []).filter((model) => model.enabled)
      const vlmModels = (response.data.llm_config?.vlm || []).filter((model) => model.enabled)
      // 合并 chat 和 vlm 模型
      chatModels.value = [...chatModelsList, ...vlmModels]
      if (!selectedModelName.value || !chatModels.value.some((model) => model.name === selectedModelName.value)) {
        selectedModelName.value = chatModels.value[0]?.name || ''
      }
    } catch (error) {
      console.error('加载聊天模型失败:', error)
      chatModels.value = []
      selectedModelName.value = ''
    } finally {
      isLoadingModels.value = false
    }
  }

  async function selectConversation(id: string) {
    resetOrchestrationState()
    thinkingState.value = null
    isTyping.value = false
    const requestId = currentSelectionRequestId.value + 1
    currentSelectionRequestId.value = requestId
    store.setCurrentConversation(id)
    store.setMessages([])
    try {
      const response = await conversationApi.getMessages(id)
      if (currentSelectionRequestId.value !== requestId || store.currentConversationId !== id) {
        return
      }
      store.setMessages(response.data)
      await nextTick()
      scrollToBottom()
    } catch (error) {
      if (currentSelectionRequestId.value === requestId) {
        store.setMessages([])
      }
      console.error('加载消息失败:', error)
    }
  }

  function newConversation() {
    resetOrchestrationState()
    thinkingState.value = null
    isTyping.value = false
    store.setCurrentConversation(null)
    store.setMessages([])
    inputRef.value?.focus()
  }

  async function deleteConversation(id: string, event: Event) {
    event.stopPropagation()
    try {
      await conversationApi.delete(id)
      store.removeConversation(id)
      if (store.currentConversationId === id) {
        store.setCurrentConversation(null)
        store.setMessages([])
      }
    } catch (error) {
      console.error('删除失败:', error)
    }
  }

  function scrollToBottom() {
    if (chatContainer.value) {
      chatContainer.value.scrollTop = chatContainer.value.scrollHeight
    }
  }

  function formatTime(dateStr: string) {
    const date = new Date(dateStr)
    return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })
  }

  function formatConvDate(dateStr: string) {
    const date = new Date(dateStr)
    const now = new Date()
    const diff = now.getTime() - date.getTime()
    if (diff < 60000) return '刚刚'
    if (diff < 3600000) return `${Math.floor(diff / 60000)}分钟前`
    if (diff < 86400000) return '今天'
    return date.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric' })
  }

  function autoResize(event: Event) {
    const element = event.target as HTMLTextAreaElement
    element.style.height = 'auto'
    element.style.height = `${Math.min(element.scrollHeight, 120)}px`
  }

  async function handleFileSelect(event: Event) {
    const input = event.target as HTMLInputElement
    if (!input.files?.length) return

    for (const file of input.files) {
      if (file.size > 10 * 1024 * 1024) {
        alert(`文件 ${file.name} 超过10MB限制`)
        continue
      }
      try {
        const response = await documentApi.upload(file)
        selectedFiles.value.push({
          id: response.data.id,
          name: file.name,
          type: file.type,
          size: file.size,
        })
      } catch (error) {
        console.error('上传失败:', error)
        alert(`文件 ${file.name} 上传失败`)
      }
    }
    if (fileInputRef.value) {
      fileInputRef.value.value = ''
    }
  }

  function insertEmoji(emoji: string) {
    inputMessage.value += emoji
    showEmojiPicker.value = false
  }

  function openFilePicker() {
    fileInputRef.value?.click()
  }

  void loadSystemStatus()
  startSystemTelemetryPolling()
  startSessionTelemetryDecay()

  onMounted(async () => {
    await auth.ensureAuthReady()
    if (auth.isAuthenticated && auth.user) {
      await Promise.all([loadConversations(), loadChatModels(), loadSystemStatus()])
    }
    inputRef.value?.focus()
  })

  onUnmounted(() => {
    if (systemTelemetryTimer) clearInterval(systemTelemetryTimer)
    if (sessionTelemetryTimer) clearInterval(sessionTelemetryTimer)
  })

  return {
    store,
    inputMessage,
    isSending,
    chatContainer,
    inputRef,
    isTyping,
    fileInputRef,
    showEmojiPicker,
    selectedFiles,
    chatModels,
    selectedModelName,
    selectedModel,
    isLoadingModels,
    conversationsError,
    thinkingState,
    orchestrationPanelVisible,
    orchestrationStatus,
    orchestrationInsight,
    activeAgent,
    visitedAgents,
    orchestrationEventFeed,
    systemTelemetry,
    sessionTelemetry,
    sendMessage,
    selectConversation,
    newConversation,
    deleteConversation,
    formatTime,
    formatConvDate,
    autoResize,
    handleFileSelect,
    insertEmoji,
    openFilePicker,
  }
}
