<template>
  <el-container class="chat-container">
    <el-aside width="300px" class="chat-sidebar" :class="{ 'mobile-hidden': isMobile && !showSidebar }">
      <div class="sidebar-header">
        <el-input
          v-model="searchQuery"
          placeholder="搜索历史对话..."
          prefix-icon="Search"
          class="search-input"
          @input="handleSearch"
        />
        <el-button type="primary" class="new-chat-btn" @click="createNewChat" circle>
          <el-icon><Plus /></el-icon>
        </el-button>
      </div>
      <el-scrollbar class="conversation-list">
        <div
          v-for="conv in conversations"
          :key="conv.id"
          class="conversation-item"
          :class="{ active: currentConversationId === conv.id, 'active-edit': editingConversationId === conv.id }"
          @click="selectConversation(conv)"
        >
          <div class="conv-content">
            <el-input
              v-if="editingConversationId === conv.id"
              v-model="editingTitle"
              size="small"
              @click.stop
              @keydown.enter="saveEdit(conv)"
              @blur="saveEdit(conv)"
              class="edit-input"
            />
            <span v-else class="conv-title">{{ conv.title }}</span>
            <span class="conv-time">{{ formatTime(conv.updatedAt) }}</span>
          </div>
          <div class="conv-actions">
            <el-button
              v-if="editingConversationId !== conv.id"
              type="primary"
              link
              icon="Edit"
              class="action-btn"
              @click.stop="startEdit(conv)"
            />
            <el-button
              v-if="editingConversationId !== conv.id"
              type="danger"
              link
              icon="Delete"
              class="action-btn"
              @click.stop="deleteConversation(conv.id)"
            />
          </div>
        </div>
      </el-scrollbar>
    </el-aside>

    <el-main class="chat-main" :class="{ 'mobile-full': isMobile && !showSidebar }">
      
      <!-- New Chat / Empty State View -->
      <div v-if="isNewChat" class="empty-chat-container">
        <div class="welcome-text">{{ welcomeMessage }}</div>
        <div class="chat-input-wrapper center-input">
          <el-input
            ref="chatInputRef"
            v-model="inputMessage"
            type="textarea"
            :autosize="{ minRows: 1, maxRows: 4 }"
            placeholder="有问题，尽管问"
            class="custom-input"
            resize="none"
            @keydown.enter.prevent="sendMessage"
            :disabled="isStreaming"
          />
          <div class="input-actions">
            <!-- <el-button circle text>
              <el-icon><Microphone /></el-icon>
            </el-button> -->
            <el-button type="primary" circle class="send-btn-inner" @click="sendMessage" :loading="isStreaming" :disabled="!inputMessage.trim()">
              <el-icon><Top /></el-icon>
            </el-button>
          </div>
        </div>
      </div>

      <!-- Active Chat View -->
      <template v-else>
        <div class="chat-header">
          <div style="display: flex; align-items: center; gap: 12px; flex: 1;">
            <el-button v-if="isMobile" icon="Menu" text @click="toggleSidebar" />
            <span class="chat-title">{{ currentConversationTitle }}</span>
          </div>
          
          <el-select 
            v-model="selectedKbId" 
            placeholder="选择知识库 (RAG)" 
            clearable 
            style="width: 180px;"
            size="small"
          >
            <template #prefix>
              <el-icon><Notebook /></el-icon>
            </template>
            <el-option
              v-for="kb in knowledgeBases"
              :key="kb.id"
              :label="kb.name"
              :value="kb.id"
            />
          </el-select>
        </div>
        
        <el-scrollbar ref="messageScroll" class="message-area">
          <div v-for="(msg, index) in messages" :key="index" class="message-wrapper" :class="msg.role">
            <div class="message-avatar">
              <el-avatar :icon="msg.role === 'user' ? 'User' : 'Service'" :src="msg.role === 'user' ? userAvatar : assistantAvatar" />
            </div>
            <div class="message-content">
               <div class="bubble markdown-body" v-html="renderMessage(msg.content)"></div>
            </div>
          </div>
        </el-scrollbar>
  
        <div class="input-area">
          <div class="chat-input-wrapper full-width">
            <el-input
              ref="chatInputRef"
              v-model="inputMessage"
              type="textarea"
              :autosize="{ minRows: 1, maxRows: 4 }"
              class="custom-input"
              resize="none"
              @keydown.enter.prevent="sendMessage"
              :disabled="isStreaming"
            />
            <div class="input-actions">
              <el-button type="primary" circle class="send-btn-inner" @click="sendMessage" :loading="isStreaming" :disabled="!inputMessage.trim()">
                <el-icon><Top /></el-icon>
              </el-button>
            </div>
          </div>
        </div>
      </template>
    </el-main>
  </el-container>
</template>

<script setup>
import { ref, reactive, onMounted, computed, nextTick } from 'vue'
import { chatApi } from '@/api/chat'
import { knowledgeApi } from '@/api/knowledge'
import { useAuthStore } from '@/stores/auth'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Search, Delete, User, Service, Menu, Edit, Top, Microphone, Notebook } from '@element-plus/icons-vue'
import { marked } from 'marked'

const authStore = useAuthStore()
const conversations = ref([])
const messages = ref([])
const currentConversationId = ref(null)
const currentConversationTitle = ref('新对话')
const inputMessage = ref('')
const searchQuery = ref('')
const isStreaming = ref(false)
const showSidebar = ref(true)
const messageScroll = ref(null)
const isMobile = ref(window.innerWidth < 768)
const editingConversationId = ref(null)
const editingTitle = ref('')
const editInputRef = ref(null)
const chatInputRef = ref(null)
const knowledgeBases = ref([])
const selectedKbId = ref(null)

const isNewChat = computed(() => messages.value.length === 0)

const welcomeMessages = [
  "有什么可以帮忙的？",
  "今天想聊点什么？",
  "无论您遇到什么问题，我都在这里。",
  "准备好开始新的探索了吗？",
  "嗨！有什么我能为您做的吗？",
  "期待与您的交流，请随时提问。"
]
const welcomeMessage = ref(welcomeMessages[Math.floor(Math.random() * welcomeMessages.length)])

const userAvatar = computed(() => authStore.avatarPath ? (import.meta.env.VITE_API_BASE || 'http://localhost:8080') + authStore.avatarPath : '')
const assistantAvatar = '/favicon.png'

const renderMessage = (content) => {
  if (!content) return ''
  try {
    // Pre-process content to fix common LLM formatting issues
    
    // 1. Fix bold text followed immediately by a list item (e.g. **Title**1. Item)
    let processed = content.replace(/(\*\*[^*]+\*\*)(\s*)(\d+\.)/g, "$1\n\n$3")
    
    // 2. Fix headers not having a newline before them
    processed = processed.replace(/([^\n])\s*(#{1,6}\s)/g, "$1\n\n$2")
    
    // 3. Fix horizontal rules not having a newline before them
    processed = processed.replace(/([^\n])\s*(---+\s*$)/gm, "$1\n\n$2")

    return marked.parse(processed, { breaks: true })
  } catch (e) {
    console.error('Markdown parsing error:', e)
    return content
  }
}

window.addEventListener('resize', () => {
  isMobile.value = window.innerWidth < 768
  if (!isMobile.value) showSidebar.value = true
})

const toggleSidebar = () => {
  showSidebar.value = !showSidebar.value
}

const loadConversations = async () => {
  try {
    const res = await chatApi.getConversations()
    conversations.value = res || []
  } catch (error) {
    console.error(error)
  }
}

const loadKnowledgeBases = async () => {
  try {
    const res = await knowledgeApi.getKnowledgeBases({ size: 100 })
    knowledgeBases.value = res.records || []
  } catch (error) {
    console.error(error)
  }
}

const selectConversation = async (conv) => {
  currentConversationId.value = conv.id
  currentConversationTitle.value = conv.title
  if (isMobile.value) showSidebar.value = false
  
  try {
    const res = await chatApi.getMessages(conv.id)
    messages.value = res || []
    scrollToBottom()
  } catch (error) {
    console.error(error)
  }
}

const createNewChat = () => {
  currentConversationId.value = null
  currentConversationTitle.value = '新对话'
  messages.value = []
  if (isMobile.value) showSidebar.value = false
  welcomeMessage.value = welcomeMessages[Math.floor(Math.random() * welcomeMessages.length)]
  nextTick(() => {
    chatInputRef.value?.focus()
  })
}

const deleteConversation = (id) => {
  ElMessageBox.confirm('确定要删除这个对话吗?', '提示', {
    type: 'warning'
  }).then(async () => {
    try {
      await chatApi.deleteConversation(id)
      ElMessage.success('删除成功')
      if (currentConversationId.value === id) {
        currentConversationId.value = null
        messages.value = []
        currentConversationTitle.value = ''
      }
      loadConversations()
    } catch (error) {
      console.error(error)
    }
  })
}

const handleSearch = async () => {
  if (!searchQuery.value) {
    loadConversations()
    return
  }
  try {
    const res = await chatApi.searchConversations(searchQuery.value)
    conversations.value = res || []
  } catch (error) {
    console.error(error)
  }
}

const startEdit = (conv) => {
  editingConversationId.value = conv.id
  editingTitle.value = conv.title
  nextTick(() => {
    // Try to focus the input
    const input = document.querySelector('.conversation-item.active-edit input')
    if (input) input.focus()
  })
}

const saveEdit = async (conv) => {
  if (!editingConversationId.value) return
  
  const newTitle = editingTitle.value
  
  // If title is empty or unchanged, just cancel edit
  if (!newTitle.trim() || newTitle === conv.title) {
     if (editingConversationId.value === conv.id) {
         editingConversationId.value = null
         editingTitle.value = ''
     }
     return
  }

  try {
    await chatApi.updateConversation(conv.id, newTitle)
    conv.title = newTitle
    if (currentConversationId.value === conv.id) {
      currentConversationTitle.value = newTitle
    }
    ElMessage.success('标题已更新')
  } catch (error) {
    console.error(error)
    ElMessage.error('更新失败')
  } finally {
    if (editingConversationId.value === conv.id) {
      editingConversationId.value = null
      editingTitle.value = ''
    }
  }
}

const sendMessage = async () => {
  if (!inputMessage.value.trim() || isStreaming.value) return
  
  const content = inputMessage.value
  inputMessage.value = ''
  
  if (!currentConversationId.value) {
     try {
        const res = await chatApi.createConversation(content.substring(0, 20))
        await loadConversations()
        currentConversationId.value = res.id
        currentConversationTitle.value = res.title
     } catch(e) {
        ElMessage.error('创建对话失败')
        return
     }
  }

  messages.value.push({ role: 'user', content })
  scrollToBottom()
  
  try {
    await chatApi.saveMessage(currentConversationId.value, 'user', content)
  } catch (e) {
    console.error('Failed to save user message')
  }

  isStreaming.value = true
  const assistantMsg = reactive({ role: 'assistant', content: '' })
  messages.value.push(assistantMsg)
  
  try {
    const baseUrl = import.meta.env.VITE_API_BASE || 'http://localhost:8080'
    const response = await fetch(`${baseUrl}/api/ai/stream`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${authStore.token}`
        },
        body: JSON.stringify({ 
            message: content, 
            temperature: 0.7,
            conversationId: currentConversationId.value,
            knowledgeBaseId: selectedKbId.value
        })
    })

    if (!response.ok) throw new Error(response.statusText)

    const reader = response.body.getReader()
    const decoder = new TextDecoder()
    let buffer = ''

    while (true) {
        const { done, value } = await reader.read()
        if (done) break
        
        const chunk = decoder.decode(value, { stream: true })
        buffer += chunk
        const lines = buffer.split('\n')
        buffer = lines.pop()
        
        for (const line of lines) {
            if (line.startsWith('data:')) {
                const data = line.slice(5)
                assistantMsg.content += data
                scrollToBottom()
            }
        }
    }
    
    await chatApi.saveMessage(currentConversationId.value, 'assistant', assistantMsg.content)
    
  } catch (e) {
    if (e.name === 'AbortError') {
        assistantMsg.content += " [已停止]"
    } else {
        console.error(e)
        // Only show error in chat bubble if we haven't received any content yet
        if (!assistantMsg.content) {
             ElMessage.error('AI 响应失败: ' + e.message)
             assistantMsg.content += " [连接失败]"
        } else {
             // If we have content, it means stream worked but maybe save failed
             ElMessage.warning('消息已接收，但保存失败: ' + e.message)
             console.error('Failed to save assistant message or stream error', e)
        }
    }
  } finally {
    isStreaming.value = false
    nextTick(() => {
      chatInputRef.value?.focus()
    })
  }
}

const scrollToBottom = () => {
  nextTick(() => {
    if (messageScroll.value) {
       const wrap = messageScroll.value.wrapRef
       wrap.scrollTop = wrap.scrollHeight
    }
  })
}

const formatTime = (timeStr) => {
  if (!timeStr) return ''
  return new Date(timeStr).toLocaleString()
}

onMounted(() => {
  loadConversations()
  loadKnowledgeBases()
})
</script>

<style scoped>
.chat-container {
  height: calc(85vh - 60px);
  background-color: #fff;
  overflow: hidden;
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}

.chat-sidebar {
  background-color: #f9fafc;
  border-right: 1px solid #eaeaea;
  display: flex;
  flex-direction: column;
}

.sidebar-header {
  height: auto;
  padding: 20px 15px;

  display: flex;
  align-items: center;
  gap: 12px;
  background-color: #f9fafc;
}

.new-chat-btn {
  flex-shrink: 0;
  box-shadow: 0 2px 6px rgba(64, 158, 255, 0.3);
}

.search-input :deep(.el-input__wrapper) {
  border-radius: 20px;
  box-shadow: 0 0 0 1px #dcdfe6 inset;
}

.conversation-list {
  flex: 1;
  padding: 10px;
}

.conversation-item {
  padding: 12px 15px;
  cursor: pointer;
  border-radius: 10px;
  margin-bottom: 8px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: all 0.25s ease;
  border: 1px solid transparent;
}

.conversation-item:hover {
  background-color: #d6d2d296;
  box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}

.conversation-item.active {
  background-color: #fff;
  border-color: var(--ios-primary);
  box-shadow: 0 2px 12px rgba(64, 158, 255, 0.15);
}

.conversation-item:hover .conv-actions {
  display: flex;
}

.conv-content {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  max-width: 190px;
  flex: 1;
}

.conv-title {
  font-weight: 600;
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: #303133;
}

.conv-actions {
  display: none;
  align-items: center;
  gap: 8px;
}

.action-btn {
  padding: 0 !important;
  margin-left: 0 !important;
  font-size: 16px;
  color: #909399;
}

.action-btn:hover {
  color: var(--ios-primary);
}

.edit-input {
  margin-bottom: 2px;
}

.conv-time {
  font-size: 11px;
  color: #999;
  margin-top: 4px;
}

.chat-main {
  display: flex;
  flex-direction: column;
  padding: 0;
  position: relative;
  overflow: hidden;
  background-color: #fff;
}

.chat-header {
  height: 60px;
  /* border-bottom: 1px solid #eaeaea; */
  display: flex;
  align-items: center;
  padding: 0 24px;
  background: #fff;
  font-weight: 600;
  font-size: 16px;
  color: #303133;
}

.message-area {
  flex: 1;
  padding: 0px 30px;
  /* margin-top: -20px; */
  background-color: #fff;
}

.message-wrapper {
  display: flex;
  margin-bottom: 24px;
  align-items: flex-start;
}

.message-wrapper.user {
  flex-direction: row-reverse;
}

.message-avatar {
  margin: 0 12px;
  flex-shrink: 0;
}

.message-content {
  max-width: 75%;
}

.bubble {
  padding: 12px 18px;
  border-radius: 12px;
  line-height: 1.6;
  font-size: 15px;
  word-wrap: break-word;
}

/* Markdown Styles */
.bubble :deep(p) {
  margin: 0 0 10px 0;
}

.bubble :deep(p:last-child) {
  margin-bottom: 0;
}

.bubble :deep(h1), .bubble :deep(h2), .bubble :deep(h3), .bubble :deep(h4), .bubble :deep(h5), .bubble :deep(h6) {
  margin: 10px 0 8px 0;
  font-weight: 600;
  line-height: 1.4;
}

.bubble :deep(h1) { font-size: 1.5em; border-bottom: 1px solid #eaeaea; padding-bottom: 5px; }
.bubble :deep(h2) { font-size: 1.4em; border-bottom: 1px solid #eaeaea; padding-bottom: 4px; }
.bubble :deep(h3) { font-size: 1.3em; }
.bubble :deep(h4) { font-size: 1.2em; }
.bubble :deep(h5) { font-size: 1.1em; }
.bubble :deep(h6) { font-size: 1.0em; color: #606266; }

.bubble :deep(ul) {
  margin: 5px 0 10px 20px;
  padding-left: 20px;
  list-style-type: disc;
}

.bubble :deep(ol) {
  margin: 5px 0 10px 20px;
  padding-left: 20px;
  list-style-type: decimal;
}

.bubble :deep(li) {
  margin-bottom: 4px;
}

.bubble :deep(pre) {
  background-color: rgba(0, 0, 0, 0.05);
  padding: 10px;
  border-radius: 6px;
  overflow-x: auto;
  font-family: monospace;
  margin: 10px 0;
}

.bubble :deep(code) {
  background-color: rgba(0, 0, 0, 0.05);
  padding: 2px 4px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 0.9em;
}

.bubble :deep(pre code) {
  background-color: transparent;
  padding: 0;
}

.bubble :deep(blockquote) {
  border-left: 3px solid rgba(0, 0, 0, 0.2);
  margin: 10px 0;
  padding-left: 10px;
  color: inherit;
  opacity: 0.8;
}

.bubble :deep(hr) {
  height: 1px;
  background-color: #e0e0e0;
  border: none;
  margin: 15px 0;
}

.bubble :deep(table) {
  width: 100%;
  border-collapse: collapse;
  margin: 10px 0;
  font-size: 0.9em;
}

.bubble :deep(th), .bubble :deep(td) {
  padding: 8px 12px;
  border: 1px solid #ddd;
  text-align: left;
}

.bubble :deep(th) {
  background-color: rgba(0, 0, 0, 0.05);
  font-weight: 600;
}

/* Adjust colors for user bubble (dark background) */
.message-wrapper.user .bubble :deep(pre), 
.message-wrapper.user .bubble :deep(code) {
  background-color: rgba(255, 255, 255, 0.2);
}

.message-wrapper.user .bubble :deep(blockquote) {
  border-left-color: rgba(255, 255, 255, 0.4);
}

.message-wrapper.user .bubble :deep(a) {
  color: #fff;
  text-decoration: underline;
}

/* Adjust colors for assistant bubble (light background) */
.message-wrapper.assistant .bubble :deep(a) {
  color: var(--el-color-primary);
}

.message-wrapper.user .bubble {
  background: #EBF5FF;
  color: #000;
  border-radius: 12px 12px 0 12px;
}

.message-wrapper.assistant .bubble {
  background-color: #f4f6f8;
  color: #2c3e50;
  border-radius: 12px 12px 12px 0;
  border: 1px solid #eaecf0;
  box-shadow: none;
}

.input-area {
  padding: 20px 30px;
  background: #fff;

  display: flex;
  justify-content: center;
}

.empty-chat-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding-bottom: 100px; /* Offset a bit */
}

.welcome-text {
  font-size: 28px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 40px;
}

.chat-input-wrapper {
  background-color: #f4f4f4;
  border-radius: 28px;
  padding: 8px 16px;
  display: flex;
  align-items: flex-end; /* Align bottom for textarea growth */
  gap: 10px;
  transition: all 0.3s ease;
  border: 1px solid transparent;
  box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}

.chat-input-wrapper:focus-within {
  background-color: #fff;
  border-color: #dcdfe6;
  box-shadow: 0 4px 15px rgba(0,0,0,0.08);
}

.center-input {
  width: 100%;
  max-width: 700px;
  padding: 12px 20px;
}

.full-width {
  width: 100%;
  max-width: 800px; /* limit width on wide screens */
}

.input-prefix {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 40px; /* Match button height */
  color: #909399;
  cursor: pointer;
}

.custom-input {
  flex: 1;
}

.custom-input :deep(.el-textarea__inner) {
  box-shadow: none !important;
  background: transparent !important;
  border: none !important;
  padding: 10px 0;
  resize: none;
  min-height: 24px;
  line-height: 1.5;
  font-size: 16px;
}

.input-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 4px; /* Align with text */
}

.send-btn-inner {
  width: 36px;
  height: 36px;
  min-height: 36px;
  background-color: var(--el-color-primary);
  border-color: var(--el-color-primary);
  color: #fff;
  transition: all 0.2s;
}



.send-btn-inner:disabled {
  background-color: #e4e7ed;
  border-color: #e4e7ed;
  color: #a8abb2;
}

/* Remove old styles */
/* .input-area :deep(.el-textarea__inner) ... */
/* .send-btn ... */


@media (max-width: 768px) {
  .chat-sidebar {
    position: absolute;
    z-index: 100;
    height: 100%;
    width: 80%;
    box-shadow: 2px 0 8px rgba(0,0,0,0.1);
  }
  
  .mobile-hidden {
    display: none;
  }
  
  .chat-main {
    width: 100%;
  }
}
</style>
