<template>
  <div class="app">
    <Sidebar
      :conversations="conversations"
      :current-id="currentConvId"
      :loading="loadingConvs"
      :has-more="hasMoreConvs"
      @select="selectConversation"
      @create="createConversation"
      @delete="deleteConversation"
      @load-more="loadMoreConversations"
    />

    <ChatView
      ref="chatViewRef"
      :conversation="currentConv"
      :messages="messages"
      :streaming="streaming"
      :streaming-content="streamContent"
      :streaming-thinking="streamThinking"
      :streaming-tool-calls="streamToolCalls"
      :streaming-process-steps="streamProcessSteps"
      :has-more-messages="hasMoreMessages"
      :loading-more="loadingMessages"
      :tools-enabled="toolsEnabled"
      @send-message="sendMessage"
      @delete-message="deleteMessage"
      @regenerate-message="regenerateMessage"
      @toggle-settings="showSettings = true"
      @load-more-messages="loadMoreMessages"
      @toggle-tools="updateToolsEnabled"
    />

    <SettingsPanel
      :visible="showSettings"
      :conversation="currentConv"
      @close="showSettings = false"
      @save="saveSettings"
    />
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import Sidebar from './components/Sidebar.vue'
import ChatView from './components/ChatView.vue'
import SettingsPanel from './components/SettingsPanel.vue'
import { conversationApi, messageApi } from './api'

const chatViewRef = ref(null)

// -- Conversations state --
const conversations = ref([])
const currentConvId = ref(null)
const loadingConvs = ref(false)
const hasMoreConvs = ref(false)
const nextConvCursor = ref(null)

// -- Messages state --
const messages = ref([])
const hasMoreMessages = ref(false)
const loadingMessages = ref(false)
const nextMsgCursor = ref(null)

// -- Streaming state --
const streaming = ref(false)
const streamContent = ref('')
const streamThinking = ref('')
const streamToolCalls = ref([])
const streamProcessSteps = ref([])

// 保存每个对话的流式状态
const streamStates = new Map()

// 保存当前流式请求引用
let currentStreamPromise = null

// -- UI state --
const showSettings = ref(false)
const toolsEnabled = ref(localStorage.getItem('tools_enabled') !== 'false') // 默认开启

const currentConv = computed(() =>
  conversations.value.find(c => c.id === currentConvId.value) || null
)

// -- Load conversations --
async function loadConversations(reset = true) {
  if (loadingConvs.value) return
  loadingConvs.value = true
  try {
    const res = await conversationApi.list(reset ? null : nextConvCursor.value)
    if (reset) {
      conversations.value = res.data.items
    } else {
      conversations.value.push(...res.data.items)
    }
    nextConvCursor.value = res.data.next_cursor
    hasMoreConvs.value = res.data.has_more
  } catch (e) {
    console.error('Failed to load conversations:', e)
  } finally {
    loadingConvs.value = false
  }
}

function loadMoreConversations() {
  if (hasMoreConvs.value) loadConversations(false)
}

// -- Create conversation --
async function createConversation() {
  try {
    const res = await conversationApi.create({ title: '新对话' })
    conversations.value.unshift(res.data)
    await selectConversation(res.data.id)
  } catch (e) {
    console.error('Failed to create conversation:', e)
  }
}

// -- Select conversation --
async function selectConversation(id) {
  // 保存当前对话的流式状态和消息列表（如果有）
  if (currentConvId.value && streaming.value) {
    streamStates.set(currentConvId.value, {
      streaming: true,
      streamContent: streamContent.value,
      streamThinking: streamThinking.value,
      streamToolCalls: [...streamToolCalls.value],
      streamProcessSteps: [...streamProcessSteps.value],
      messages: [...messages.value],  // 保存消息列表（包括临时用户消息）
    })
  }

  currentConvId.value = id
  nextMsgCursor.value = null
  hasMoreMessages.value = false

  // 恢复新对话的流式状态
  const savedState = streamStates.get(id)
  if (savedState && savedState.streaming) {
    streaming.value = true
    streamContent.value = savedState.streamContent
    streamThinking.value = savedState.streamThinking
    streamToolCalls.value = savedState.streamToolCalls
    streamProcessSteps.value = savedState.streamProcessSteps
    messages.value = savedState.messages || []  // 恢复消息列表
  } else {
    streaming.value = false
    streamContent.value = ''
    streamThinking.value = ''
    streamToolCalls.value = []
    streamProcessSteps.value = []
    messages.value = []
  }

  // 如果不是正在流式传输，从服务器加载消息
  if (!streaming.value) {
    await loadMessages(true)
  }
}

// -- Load messages --
async function loadMessages(reset = true) {
  if (!currentConvId.value || loadingMessages.value) return
  loadingMessages.value = true
  try {
    const res = await messageApi.list(currentConvId.value, reset ? null : nextMsgCursor.value)
    if (reset) {
      // Filter out tool messages (they're merged into assistant messages)
      messages.value = res.data.items.filter(m => m.role !== 'tool')
    } else {
      messages.value = [...res.data.items.filter(m => m.role !== 'tool'), ...messages.value]
    }
    nextMsgCursor.value = res.data.next_cursor
    hasMoreMessages.value = res.data.has_more
  } catch (e) {
    console.error('Failed to load messages:', e)
  } finally {
    loadingMessages.value = false
  }
}

function loadMoreMessages() {
  if (hasMoreMessages.value) loadMessages(false)
}

// -- Send message (streaming) --
async function sendMessage(data) {
  if (!currentConvId.value || streaming.value) return

  const convId = currentConvId.value  // 保存当前对话ID
  const text = data.text || ''
  const attachments = data.attachments || null

  // Add user message optimistically
  const userMsg = {
    id: 'temp_' + Date.now(),
    conversation_id: convId,
    role: 'user',
    text,
    attachments: attachments ? attachments.map(a => ({ name: a.name, extension: a.extension })) : null,
    token_count: 0,
    created_at: new Date().toISOString(),
  }
  messages.value.push(userMsg)

  streaming.value = true
  streamContent.value = ''
  streamThinking.value = ''
  streamToolCalls.value = []
  streamProcessSteps.value = []

  currentStreamPromise = messageApi.send(convId, { text, attachments }, {
    stream: true,
    toolsEnabled: toolsEnabled.value,
    onThinkingStart() {
      if (currentConvId.value === convId) {
        streamThinking.value = ''
      } else {
        const saved = streamStates.get(convId) || {}
        streamStates.set(convId, { ...saved, streamThinking: '' })
      }
    },
    onThinking(text) {
      if (currentConvId.value === convId) {
        streamThinking.value += text
      } else {
        const saved = streamStates.get(convId) || { streamThinking: '' }
        streamStates.set(convId, { ...saved, streamThinking: (saved.streamThinking || '') + text })
      }
    },
    onMessage(text) {
      if (currentConvId.value === convId) {
        streamContent.value += text
      } else {
        const saved = streamStates.get(convId) || { streamContent: '' }
        streamStates.set(convId, { ...saved, streamContent: (saved.streamContent || '') + text })
      }
    },
    onToolCalls(calls) {
      console.log('🔧 Tool calls received:', calls)
      if (currentConvId.value === convId) {
        streamToolCalls.value.push(...calls.map(c => ({ ...c, result: null })))
      } else {
        const saved = streamStates.get(convId) || { streamToolCalls: [] }
        const newCalls = [...(saved.streamToolCalls || []), ...calls.map(c => ({ ...c, result: null }))]
        streamStates.set(convId, { ...saved, streamToolCalls: newCalls })
      }
    },
    onToolResult(result) {
      console.log('✅ Tool result received:', result)
      if (currentConvId.value === convId) {
        const call = streamToolCalls.value.find(c => c.id === result.id)
        if (call) call.result = result.content
      } else {
        const saved = streamStates.get(convId) || { streamToolCalls: [] }
        const call = saved.streamToolCalls?.find(c => c.id === result.id)
        if (call) call.result = result.content
        streamStates.set(convId, { ...saved })
      }
    },
    onProcessStep(step) {
      const idx = step.index
      if (currentConvId.value === convId) {
        // 创建新数组确保响应式更新
        const newSteps = [...streamProcessSteps.value]
        while (newSteps.length <= idx) {
          newSteps.push(null)
        }
        newSteps[idx] = step
        streamProcessSteps.value = newSteps
      } else {
        const saved = streamStates.get(convId) || { streamProcessSteps: [] }
        const steps = [...(saved.streamProcessSteps || [])]
        while (steps.length <= idx) steps.push(null)
        steps[idx] = step
        streamStates.set(convId, { ...saved, streamProcessSteps: steps })
      }
    },
    async onDone(data) {
      // 清除保存的状态
      streamStates.delete(convId)

      if (currentConvId.value === convId) {
        streaming.value = false
        currentStreamPromise = null
        // 添加助手消息（保留临时用户消息）
        messages.value.push({
          id: data.message_id,
          conversation_id: convId,
          role: 'assistant',
          text: streamContent.value,
          thinking: streamThinking.value || null,
          tool_calls: streamToolCalls.value.length > 0 ? streamToolCalls.value : null,
          process_steps: streamProcessSteps.value.filter(Boolean),
          token_count: data.token_count,
          created_at: new Date().toISOString(),
        })
        streamContent.value = ''
        streamThinking.value = ''
        streamToolCalls.value = []
        streamProcessSteps.value = []

        // Update conversation in list (move to top)
        const idx = conversations.value.findIndex(c => c.id === convId)
        if (idx > 0) {
          const [conv] = conversations.value.splice(idx, 1)
          conv.message_count = (conv.message_count || 0) + 2
          if (data.suggested_title) {
            conv.title = data.suggested_title
          }
          conversations.value.unshift(conv)
        } else if (idx === 0) {
          conversations.value[0].message_count = (conversations.value[0].message_count || 0) + 2
          if (data.suggested_title) {
            conversations.value[0].title = data.suggested_title
          }
        }
      } else {
        // 后台完成，重新加载该对话的消息
        try {
          const res = await messageApi.list(convId, null, 50)
          // 更新对话列表中的消息计数和标题
          const idx = conversations.value.findIndex(c => c.id === convId)
          if (idx >= 0) {
            conversations.value[idx].message_count = res.data.items.length
            // 从服务器获取最新标题
            if (res.data.items.length > 0) {
              const convRes = await conversationApi.get(convId)
              if (convRes.data.title) {
                conversations.value[idx].title = convRes.data.title
              }
            }
          }
        } catch (_) {}
      }
    },
    onError(msg) {
      streamStates.delete(convId)
      if (currentConvId.value === convId) {
        streaming.value = false
        currentStreamPromise = null
        streamContent.value = ''
        streamThinking.value = ''
        streamToolCalls.value = []
        streamProcessSteps.value = []
        console.error('Stream error:', msg)
      }
    },
  })
}

// -- Delete message --
async function deleteMessage(msgId) {
  if (!currentConvId.value) return
  try {
    await messageApi.delete(currentConvId.value, msgId)
    messages.value = messages.value.filter(m => m.id !== msgId)
  } catch (e) {
    console.error('Failed to delete message:', e)
  }
}

// -- Regenerate message --
async function regenerateMessage(msgId) {
  if (!currentConvId.value || streaming.value) return

  const convId = currentConvId.value

  // 找到要重新生成的消息索引
  const msgIndex = messages.value.findIndex(m => m.id === msgId)
  if (msgIndex === -1) return

  // 移除该消息及其后面的所有消息
  messages.value = messages.value.slice(0, msgIndex)

  streaming.value = true
  streamContent.value = ''
  streamThinking.value = ''
  streamToolCalls.value = []
  streamProcessSteps.value = []

  currentStreamPromise = messageApi.regenerate(convId, msgId, {
    toolsEnabled: toolsEnabled.value,
    onThinkingStart() {
      if (currentConvId.value === convId) {
        streamThinking.value = ''
      }
    },
    onThinking(text) {
      if (currentConvId.value === convId) {
        streamThinking.value += text
      }
    },
    onMessage(text) {
      if (currentConvId.value === convId) {
        streamContent.value += text
      }
    },
    onToolCalls(calls) {
      if (currentConvId.value === convId) {
        streamToolCalls.value.push(...calls.map(c => ({ ...c, result: null })))
      }
    },
    onToolResult(result) {
      if (currentConvId.value === convId) {
        const call = streamToolCalls.value.find(c => c.id === result.id)
        if (call) call.result = result.content
      }
    },
    onProcessStep(step) {
      const idx = step.index
      if (currentConvId.value === convId) {
        const newSteps = [...streamProcessSteps.value]
        while (newSteps.length <= idx) {
          newSteps.push(null)
        }
        newSteps[idx] = step
        streamProcessSteps.value = newSteps
      }
    },
    async onDone(data) {
      if (currentConvId.value === convId) {
        streaming.value = false
        currentStreamPromise = null
        messages.value.push({
          id: data.message_id,
          conversation_id: convId,
          role: 'assistant',
          text: streamContent.value,
          thinking: streamThinking.value || null,
          tool_calls: streamToolCalls.value.length > 0 ? streamToolCalls.value : null,
          process_steps: streamProcessSteps.value.filter(Boolean),
          token_count: data.token_count,
          created_at: new Date().toISOString(),
        })
        streamContent.value = ''
        streamThinking.value = ''
        streamToolCalls.value = []
        streamProcessSteps.value = []
      }
    },
    onError(msg) {
      if (currentConvId.value === convId) {
        streaming.value = false
        currentStreamPromise = null
        streamContent.value = ''
        streamThinking.value = ''
        streamToolCalls.value = []
        streamProcessSteps.value = []
        console.error('Regenerate error:', msg)
      }
    },
  })
}

// -- Delete conversation --
async function deleteConversation(id) {
  try {
    await conversationApi.delete(id)
    conversations.value = conversations.value.filter(c => c.id !== id)
    if (currentConvId.value === id) {
      currentConvId.value = conversations.value.length > 0 ? conversations.value[0].id : null
      if (currentConvId.value) {
        await selectConversation(currentConvId.value)
      } else {
        messages.value = []
      }
    }
  } catch (e) {
    console.error('Failed to delete conversation:', e)
  }
}

// -- Save settings --
async function saveSettings(data) {
  if (!currentConvId.value) return
  try {
    const res = await conversationApi.update(currentConvId.value, data)
    const idx = conversations.value.findIndex(c => c.id === currentConvId.value)
    if (idx !== -1) {
      conversations.value[idx] = { ...conversations.value[idx], ...res.data }
    }
  } catch (e) {
    console.error('Failed to save settings:', e)
  }
}

// -- Update tools enabled --
function updateToolsEnabled(val) {
  toolsEnabled.value = val
  localStorage.setItem('tools_enabled', String(val))
}

// -- Init --
onMounted(() => {
  loadConversations()
})
</script>

<style>
:root {
  /* Light theme */
  --bg-primary: #ffffff;
  --bg-secondary: #f8fafc;
  --bg-tertiary: #f0f4f8;
  --bg-hover: rgba(37, 99, 235, 0.06);
  --bg-active: rgba(37, 99, 235, 0.12);
  --bg-input: #f8fafc;
  --bg-code: #f1f5f9;
  --bg-thinking: #f1f5f9;

  --text-primary: #1e293b;
  --text-secondary: #64748b;
  --text-tertiary: #94a3b8;

  --border-light: rgba(0, 0, 0, 0.06);
  --border-medium: rgba(0, 0, 0, 0.08);
  --border-input: rgba(0, 0, 0, 0.08);

  --accent-primary: #2563eb;
  --accent-primary-hover: #3b82f6;
  --accent-primary-light: rgba(37, 99, 235, 0.08);
  --accent-primary-medium: rgba(37, 99, 235, 0.15);

  --success-color: #059669;
  --success-bg: rgba(16, 185, 129, 0.1);
  --danger-color: #ef4444;
  --danger-bg: rgba(239, 68, 68, 0.08);

  --scrollbar-thumb: rgba(0, 0, 0, 0.08);
  --scrollbar-thumb-sidebar: rgba(0, 0, 0, 0.1);

  --overlay-bg: rgba(0, 0, 0, 0.3);

  --avatar-gradient: linear-gradient(135deg, #3b82f6, #60a5fa);
}

[data-theme="dark"] {
  /* Dark theme - 保持与浅色模式相同的相对色差 */
  --bg-primary: #1a1a1a;    /* 聊天框，最浅（对应浅色 #ffffff） */
  --bg-secondary: #141414;  /* 侧边栏，中等（对应浅色 #f8fafc） */
  --bg-tertiary: #0a0a0a;   /* 整体背景，最深（对应浅色 #f0f4f8） */
  --bg-hover: rgba(255, 255, 255, 0.08);
  --bg-active: rgba(255, 255, 255, 0.12);
  --bg-input: #141414;
  --bg-code: #141414;
  --bg-thinking: #141414;

  --text-primary: #f0f0f0;
  --text-secondary: #a0a0a0;
  --text-tertiary: #606060;

  --border-light: rgba(255, 255, 255, 0.08);
  --border-medium: rgba(255, 255, 255, 0.12);
  --border-input: rgba(255, 255, 255, 0.1);

  --accent-primary: #3b82f6;
  --accent-primary-hover: #60a5fa;
  --accent-primary-light: rgba(59, 130, 246, 0.15);
  --accent-primary-medium: rgba(59, 130, 246, 0.25);

  --success-color: #34d399;
  --success-bg: rgba(52, 211, 153, 0.15);
  --danger-color: #f87171;
  --danger-bg: rgba(248, 113, 113, 0.15);

  --scrollbar-thumb: rgba(255, 255, 255, 0.1);
  --scrollbar-thumb-sidebar: rgba(255, 255, 255, 0.15);

  --overlay-bg: rgba(0, 0, 0, 0.6);

  --avatar-gradient: linear-gradient(135deg, #3b82f6, #60a5fa);
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html, body {
  height: 100%;
  overflow: hidden;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans SC', sans-serif;
  background: var(--bg-tertiary);
  color: var(--text-primary);
  -webkit-font-smoothing: antialiased;
  transition: background 0.2s, color 0.2s;
}

#app {
  height: 100%;
}

.app {
  display: flex;
  height: 100%;
}
</style>
