<template>
  <div class="app-container">
    <!-- 顶部搜索和操作栏 -->
    <div class="top-toolbar">
      <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
        <el-form-item label="知识库名称" prop="collectionName">
          <el-input v-model="queryParams.collectionName" placeholder="请输入知识库名称" clearable @keyup.enter="handleQuery" />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" :icon="Search" @click="handleQuery">搜索</el-button>
          <el-button :icon="Refresh" @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>

      <div class="toolbar-actions">
        <el-button type="primary" plain :icon="Plus" @click="handleAdd" v-hasPermi="['llm:knowledge:add']">
          新增知识库
        </el-button>
        <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
      </div>
    </div>

    <!-- 主要内容区域 -->
    <div class="main-content">
      <!-- 左侧知识库列表 -->
      <div class="left-panel">
        <div class="panel-header">
          <h3>知识库列表</h3>
          <span class="knowledge-count">{{ knowledgeList.length }} 个知识库</span>
        </div>

        <div class="knowledge-cards" v-loading="loading">
          <div v-for="(item, index) in knowledgeList" :key="index" class="knowledge-card"
            :class="{ 'active': selectedKnowledge?.collectionName === item.collectionName }"
            @click="selectKnowledge(item)">
            <div class="card-header">
              <div class="card-title">
                <el-icon class="folder-icon">
                  <Folder />
                </el-icon>
                <span class="title-text">{{ item.collectionName }}</span>
              </div>
              <div class="card-actions">
                <el-dropdown trigger="click" @command="handleCardAction">
                  <el-button type="text" size="small">
                    <el-icon>
                      <MoreFilled />
                    </el-icon>
                  </el-button>
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item :command="{ action: 'edit', data: item }" :icon="Edit">编辑</el-dropdown-item>
                      <el-dropdown-item :command="{ action: 'upload', data: item }"
                        :icon="Upload">上传文件</el-dropdown-item>
                      <el-dropdown-item :command="{ action: 'delete', data: item }" :icon="Delete"
                        divided>删除</el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </div>
            </div>

            <div class="card-content">
              <p class="description">{{ item.description || '暂无描述' }}</p>
              <div class="meta-info">
                <span class="create-time">{{ parseTime(item.createdTime, '{y}-{m}-{d}') }}</span>
                <span class="file-count">{{ item.fileCount || 0 }} 个文件</span>
              </div>
            </div>
          </div>

          <!-- 空状态 -->
          <div v-if="knowledgeList.length === 0 && !loading" class="empty-state">
            <el-icon class="empty-icon">
              <FolderOpened />
            </el-icon>
            <p>暂无知识库</p>
            <el-button type="primary" @click="handleAdd">创建第一个知识库</el-button>
          </div>
        </div>
      </div>

      <!-- 右侧面板 -->
      <div class="right-panel">
        <div class="panel-header">
          <h3>{{ isChatMode ? '知识库对话' : '文件列表' }}</h3>
          <div class="header-actions">
            <el-button v-if="!isChatMode" type="primary" :icon="ChatRound" @click="handleChat(selectedKnowledge)"
              :disabled="!selectedKnowledge" v-hasPermi="['llm:knowledge:chat']">
              开始对话
            </el-button>
            <el-button v-if="!isChatMode" type="primary" :icon="Upload" @click="handleUpload(selectedKnowledge)"
              :disabled="!selectedKnowledge" v-hasPermi="['llm:knowledge:upload']">
              上传文件
            </el-button>
            <el-button v-if="isChatMode" type="default" :icon="Document" @click="switchToFileMode">
              返回文件列表
            </el-button>
          </div>
        </div>

        <!-- 文件列表模式 -->
        <div v-if="!isChatMode" class="file-content" v-loading="fileLoading">
          <div v-if="selectedKnowledge" class="selected-knowledge">
            <el-icon class="folder-icon">
              <Folder />
            </el-icon>
            <span class="knowledge-name">{{ selectedKnowledge.collectionName }}</span>
          </div>

          <div v-if="!selectedKnowledge" class="empty-state">
            <el-icon class="empty-icon">
              <Document />
            </el-icon>
            <p>请选择一个知识库查看文件</p>
          </div>

          <div v-else-if="fileList.length === 0" class="empty-state">
            <el-icon class="empty-icon">
              <Document />
            </el-icon>
            <p>该知识库暂无文件</p>
            <el-button type="primary" @click="handleUpload(selectedKnowledge)">上传文件</el-button>
          </div>

          <div v-else class="file-list">
            <div v-for="(file, index) in pagedFileList" :key="index" class="file-item">
              <div class="file-info">
                <el-icon class="file-icon">
                  <Document />
                </el-icon>
                <div class="file-details">
                  <div class="file-name">{{ file }}</div>
                  <div class="file-meta">
                    <span class="file-type">{{ getFileType(file) }}</span>
                  </div>
                </div>
              </div>
              <div class="file-actions">
                <el-button type="danger" size="small" :icon="Delete" @click="handleDeleteFile(file)">
                  删除
                </el-button>
              </div>
            </div>
          </div>

          <!-- 文件列表分页 -->
          <pagination v-show="fileTotal > 0" :total="fileTotal" v-model:page="filePageNum" v-model:limit="filePageSize" :autoScroll="false"
            @pagination="handleFilePagination" />
        </div>

        <!-- 聊天模式 -->
        <div v-else class="chat-content">
          <div v-if="selectedKnowledge" class="selected-knowledge">
            <el-icon class="folder-icon">
              <Folder />
            </el-icon>
            <span class="knowledge-name">{{ selectedKnowledge.collectionName }}</span>
            <span class="chat-mode-badge">对话模式</span>
          </div>

          <!-- 聊天消息区域 -->
          <div class="chat-messages" ref="chatMessagesRef">
            <div v-if="chatMessages.length === 0" class="welcome-message">
              <div class="welcome-content">
                <div class="welcome-icon">🤖</div>
                <h3>知识库助手</h3>
                <p>我是基于「{{ selectedKnowledge?.collectionName }}」知识库的AI助手</p>
                <p>您可以询问关于该知识库内容的问题，我会为您提供准确的答案</p>
              </div>
            </div>

            <div v-else class="message-list">
              <div v-for="(message, index) in chatMessages" :key="index" class="message-item"
                :class="[message.type, { 'typing': message.type === 'ai' && isSending && index === chatMessages.length - 1 }]">
                <div class="message-avatar">
                  <div v-if="message.type === 'user'" class="user-avatar">
                    <el-icon>
                      <User />
                    </el-icon>
                  </div>
                  <div v-else class="ai-avatar">
                    🤖
                  </div>
                </div>
                <div class="message-content">
                  <div class="message-bubble" :class="message.type">
                    <div class="message-text" v-html="formatMessage(message.content)"></div>
                    
                    <!-- AI回答的引用文件信息 -->
                    <div v-if="message.type === 'ai' && message.references && message.references.length > 0" class="message-references">
                      <div class="references-header">
                        <el-icon class="reference-icon"><Document /></el-icon>
                        <span>参考文件 ({{ message.references.length }})</span>
                        <el-button 
                          v-if="message.references.length > 3"
                          type="text" 
                          size="small" 
                          class="toggle-references"
                          @click="toggleReferences(index)"
                        >
                          {{ message.showAllReferences ? '收起' : '展开全部' }}
                        </el-button>
                      </div>
                      <div class="references-list">
                        <div 
                          v-for="(ref, refIndex) in getDisplayedReferences(message)" 
                          :key="refIndex" 
                          class="reference-item"
                        >
                          <div class="reference-info">
                            <span class="reference-filename" :title="ref.fileName">{{ ref.fileName }}</span>
                            <span class="reference-similarity" :class="getSimilarityClass(ref.similarity)">
                              相似度: {{ formatSimilarity(ref.similarity) }}%
                            </span>
                          </div>
                        </div>
                      </div>
                    </div>
                    
                    <div class="message-time">{{ message.time }}</div>
                  </div>
                </div>
              </div>

              <!-- AI回答loading状态 -->
              <div
                v-if="isSending && chatMessages.length > 0 && chatMessages[chatMessages.length - 1].type === 'ai' && chatMessages[chatMessages.length - 1].content === ''"
                class="message-item ai">
                <div class="message-avatar">
                  <div class="ai-avatar">
                    <el-icon>
                      <ChatDotRound />
                    </el-icon>
                  </div>
                </div>
                <div class="message-content">
                  <div class="message-bubble ai">
                    <div class="loading-dots">
                      <span></span>
                      <span></span>
                      <span></span>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>

          <!-- 输入区域 -->
          <div class="chat-input-area">
            <div class="input-container">
              <el-input v-model="chatInput" type="textarea" :rows="3"
                :placeholder="isSending ? 'AI正在思考中...' : '请输入您的问题...'" @keydown.enter="handleEnter"
                @keydown.ctrl.enter="handleCtrlEnter" :disabled="isSending" resize="none" />
              <div class="input-actions">
                <el-button v-if="!isSending" type="primary" :icon="Promotion" @click="sendMessage"
                  :disabled="!chatInput.trim() || chatInput.length > 2000">
                  发送
                </el-button>
                <el-button v-else type="danger" :icon="Delete" @click="stopGenerating">
                  停止生成
                </el-button>
              </div>
            </div>
            <div class="input-tips">
              <span>按 Enter 发送，Ctrl + Enter 换行</span>
              <span v-if="chatInput" class="char-count" :class="{ 'warning': chatInput.length > 1500 }">
                {{ chatInput.length }} 字符
                <span v-if="chatInput.length > 2000" class="error-text">(超出限制)</span>
              </span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 添加或修改知识库对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="knowledgeFormRef" :model="form" :rules="rules" label-width="120px">
        <el-form-item label="知识库名称" prop="collectionName">
          <el-input v-model="form.collectionName" placeholder="请输入知识库名称" :disabled="isModify" />
        </el-form-item>
        <el-form-item label="新知识库名称" prop="newCollectionName" v-if="isModify">
          <el-input v-model="form.newCollectionName" placeholder="请输入新知识库名称" />
        </el-form-item>
        <el-form-item label="描述" prop="description" v-if="!isModify">
          <el-input type="textarea" v-model="form.description" placeholder="请输入描述" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 上传文件对话框 -->
    <el-dialog title="上传文件到知识库" v-model="uploadOpen" width="500px" append-to-body>
      <el-form ref="uploadFormRef" :model="uploadForm" :rules="uploadRules" label-width="80px">
        <el-form-item label="知识库" prop="collectionName">
          <el-input v-model="uploadForm.collectionName" disabled />
        </el-form-item>
        <el-form-item label="选择文件" prop="file">
          <el-upload ref="knowledgeUpload" multiple accept=".docx,.pdf" :headers="upload.headers" :action="''"
            :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess"
            :auto-upload="false" drag :on-change="handleFileChange">
            <el-icon class="el-icon--upload"><upload-filled /></el-icon>
            <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
            <template #tip>
              <div class="el-upload__tip text-center">
                <div class="el-upload__tip">
                  <el-checkbox v-model="upload.updateSupport" />
                  是否更新已经存在的文件数据
                </div>
                <span>支持 .docx、.pdf 格式文件</span>
              </div>
            </template>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitUpload">确 定</el-button>
          <el-button @click="cancelUpload">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, getCurrentInstance, onMounted, onUnmounted, nextTick, watch, computed } from 'vue'
import { Search, Refresh, Plus, Edit, Delete, Upload, UploadFilled, Folder, MoreFilled, FolderOpened, Document, ChatRound, User, ChatDotRound, Promotion } from '@element-plus/icons-vue'
import { listKnowledge, addKnowledge, updateKnowledge, delKnowledge, insertKnowledgeFile, listKnowledgeDocument, deleteKnowledgeFile } from "@/api/llm/knowLedge";
import { getAnswer, getAnswerStream,getContextFile } from '@/api/llm/rag';
import { getToken } from "@/utils/auth";

const { proxy } = getCurrentInstance();

const knowledgeList = ref([]);
const open = ref(false);
const uploadOpen = ref(false);
const loading = ref(true);
const fileLoading = ref(false);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const isModify = ref(false);
const selectedKnowledge = ref(null);
const fileList = ref([]);

// 文件分页相关状态
const fileTotal = ref(0);
const filePageNum = ref(1);
const filePageSize = ref(10);
const pagedFileList = computed(() => {
  const start = (filePageNum.value - 1) * filePageSize.value;
  const end = start + filePageSize.value;
  return fileList.value.slice(start, end);
});

// 聊天相关状态
const isChatMode = ref(false);
const chatMessages = ref([]);
const chatInput = ref('');
const isSending = ref(false);
const chatMessagesRef = ref(null);

// 表单数据
const form = reactive({
  collectionName: '',
  description: '',
  newCollectionName: ''
});

// 查询参数
const queryParams = reactive({
  collectionName: ''
});

// 表单验证规则
const rules = reactive({
  collectionName: [
    { required: true, message: "知识库名称不能为空", trigger: "blur" }
  ]
});

// 上传配置
const upload = reactive({
  file: null,
  fileList: [],
  // 是否禁用上传
  isUploading: false,
  // 是否更新已经存在的文件数据
  updateSupport: false,
  // 设置上传的请求头部
  headers: { Authorization: "Bearer " + getToken() }
});

// 上传表单
const uploadForm = reactive({
  collectionName: '',
  file: null
});

// 上传验证规则
const uploadRules = reactive({
  file: [
    { required: true, message: "请选择要上传的文件", trigger: "blur" }
  ]
});

/** 查询知识库列表 */
function getList() {
  loading.value = true;
  listKnowledge().then(response => {
    // 确保返回的数据是数组格式
    if (Array.isArray(response.data)) {
      knowledgeList.value = response.data;
      knowledgeList.value.map(item => {
        listKnowledgeDocument(item.collectionName).then(response => {
          item.fileCount = response.data.length;
        })
      })
    } else {
      knowledgeList.value = [];
    }
    loading.value = false;
  }).catch(error => {
    loading.value = false;
    proxy.$modal.msgError("获取知识库列表失败：" + error.message);
  });
}

/** 选择知识库 */
function selectKnowledge(knowledge) {
  // 如果正在生成回答，先停止
  if (isSending.value) {
    stopGenerating();
  }

  selectedKnowledge.value = knowledge;
  // 重置聊天模式
  isChatMode.value = false;
  chatMessages.value = [];
  chatInput.value = '';

  // 重置文件分页状态
  filePageNum.value = 1;
  filePageSize.value = 10;

  fileLoading.value = true;
  listKnowledgeDocument(knowledge.collectionName).then(response => {
    fileList.value = response.data;
    fileTotal.value = response.data.length;
    fileLoading.value = false;
  }).catch(error => {
    fileLoading.value = false;
    proxy.$modal.msgError("获取文件列表失败：" + error.message);
  });
}

/** 开始对话 */
function handleChat(knowledge) {
  if (!knowledge) {
    proxy.$modal.msgWarning("请先选择要对话的知识库");
    return;
  }
  // 如果正在生成回答，先停止
  if (isSending.value) {
    stopGenerating();
  }

  isChatMode.value = true;
  chatMessages.value = [];
  chatInput.value = '';
  // 滚动到底部
  nextTick(() => {
    scrollToBottom();
  });
}

/** 切换到文件模式 */
function switchToFileMode() {
  // 如果正在生成回答，先停止
  if (isSending.value) {
    stopGenerating();
  }

  isChatMode.value = false;
}

/** 发送消息 */
function sendMessage() {
  if (!chatInput.value.trim()) return;

  // 如果正在发送，先停止当前请求
  if (isSending.value) {
    stopGenerating();
  }

  const userMessage = {
    type: 'user',
    content: chatInput.value.trim(),
    time: proxy.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}')
  };

  chatMessages.value.push(userMessage);
  const currentInput = chatInput.value;
  chatInput.value = '';
  isSending.value = true;

  // 滚动到底部
  nextTick(() => {
    scrollToBottom();
  });

  // 创建AI消息占位符
  const aiMessage = reactive({
    type: 'ai',
    content: '',
    time: proxy.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
    references: [], // 引用的文件信息
    showAllReferences: false // 是否显示所有引用文件
  });
  chatMessages.value.push(aiMessage);

  // 使用流式API获取回答
  const eventSource = getAnswerStream(
    currentInput,
    selectedKnowledge.value.collectionName,
    // onMessage: 接收到每个字符时的回调
    (content) => {
      // 处理接收到的内容
      console.log('=== 前端接收到内容 ===', content)

      // 清理内容中的</think>标签
      let cleanContent = content.replace(/<\/?think>/g, '');

      // 如果内容为空或只包含空白字符，跳过
      if (!cleanContent.trim()) {
        return;
      }

      // 直接替换内容，避免重复叠加
      aiMessage.content = cleanContent;
      aiMessage.time = proxy.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}');
      console.log('=== 清理后的内容 ===', cleanContent)
      console.log('=== 当前AI消息完整内容 ===', aiMessage.content)

      // 每次接收到消息都重置超时定时器
      if (window.responseTimeout) {
        clearTimeout(window.responseTimeout);
      }
      
      // 重新设置超时定时器（30秒无新消息才超时）
      window.responseTimeout = setTimeout(() => {
        if (isSending.value) {
          console.log('=== 响应超时强制结束 ===')
          isSending.value = false;
          if (window.currentController) {
            window.currentController.abort();
            window.currentController = null;
          }
          window.responseTimeout = null;
        }
      }, 30000); // 30秒无响应超时

      // 滚动到底部
      nextTick(() => {
        scrollToBottom();
      });
    },
    // onError: 发生错误时的回调
    (error) => {
      console.error('=== 流式回答错误 ===', error);
      
      // 清除超时定时器
      if (window.responseTimeout) {
        clearTimeout(window.responseTimeout);
        window.responseTimeout = null;
      }
      
      if (aiMessage.content === '') {
        aiMessage.content = '抱歉，我暂时无法回答您的问题，请稍后再试。';
      } else {
        aiMessage.content += '\n\n[回答生成中断]';
      }
      isSending.value = false;
      console.log('=== 错误时isSending设置为false ===')
      
      // 清理控制器
      if (window.currentController) {
        window.currentController = null;
      }
      
      // 滚动到底部
      nextTick(() => {
        scrollToBottom();
      });
    },
    // onComplete: 回答完成时的回调
    () => {
      console.log('=== 回答完成，正确进入onComplete ===')
      
      // 清除超时定时器
      if (window.responseTimeout) {
        clearTimeout(window.responseTimeout);
        window.responseTimeout = null;
      }
      
      isSending.value = false;
      console.log('=== onComplete中isSending设置为false ===')

      // 清理控制器
      if (window.currentController) {
        window.currentController = null;
      }

      // 确保状态更新
      nextTick(() => {
        console.log('=== 最终isSending状态 ===', isSending.value)
        scrollToBottom();
      });
    }
  );
  // 获取上下文引用文件
  getContextFile(currentInput, selectedKnowledge.value.collectionName).then(response => {
    console.log('=== 上下文文件 ===', response)
    if (response && Array.isArray(response)) {
      aiMessage.references = response.map(item => ({
        fileName: item.file_name,
        similarity: item.distance,
        content: item.content
      }));
    }
  }).catch(error => {
    console.error('获取上下文文件失败:', error);
  });
  // 如果用户快速发送多条消息，取消之前的请求
  if (window.currentController) {
    window.currentController.abort();
  }
  if (window.responseTimeout) {
    clearTimeout(window.responseTimeout);
  }
  
  window.currentController = eventSource;

  // 设置初始超时定时器（30秒无任何响应才超时）
  window.responseTimeout = setTimeout(() => {
    if (isSending.value) {
      console.log('=== 初始连接超时强制结束 ===')
      isSending.value = false;
      if (window.currentController) {
        window.currentController.abort();
        window.currentController = null;
      }
      window.responseTimeout = null;
    }
  }, 30000); // 30秒超时
}

/** 停止生成回答 */
function stopGenerating() {
  // 清除超时定时器
  if (window.responseTimeout) {
    clearTimeout(window.responseTimeout);
    window.responseTimeout = null;
  }
  
  if (window.currentController) {
    window.currentController.abort();
    window.currentController = null;
  }
  isSending.value = false;
}

/** 滚动到底部 */
function scrollToBottom() {
  if (chatMessagesRef.value) {
    const container = chatMessagesRef.value;
    container.scrollTop = container.scrollHeight;
  }
}

/** 处理Enter键 */
function handleEnter(event) {
  if (!event.shiftKey) {
    event.preventDefault();
    sendMessage();
  }
}

/** 处理Ctrl+Enter键 */
function handleCtrlEnter() {
  chatInput.value += '\n';
}

/** 格式化消息内容 */
function formatMessage(content) {
  // 简单的换行处理
  return content.replace(/\n/g, '<br>');
}

/** 格式化相似度 */
function formatSimilarity(similarity) {
  // 如果相似度已经是百分比形式(>1)，直接返回
  if (similarity > 1) {
    return similarity.toFixed(1);
  }
  // 如果是0-1之间的值，转换为百分比
  return (similarity * 100).toFixed(1);
}

/** 获取相似度的CSS类 */
function getSimilarityClass(similarity) {
  const percentage = similarity > 1 ? similarity : similarity * 100;
  if (percentage >= 80) return 'high-similarity';
  if (percentage >= 60) return 'medium-similarity';
  return 'low-similarity';
}

/** 切换引用文件的展开/收起状态 */
function toggleReferences(messageIndex) {
  const message = chatMessages.value[messageIndex];
  message.showAllReferences = !message.showAllReferences;
}

/** 获取要显示的引用文件列表 */
function getDisplayedReferences(message) {
  if (!message.references || message.references.length === 0) {
    return [];
  }
  
  // 如果引用文件数量 <= 3 或者设置为显示全部，则显示所有
  if (message.references.length <= 3 || message.showAllReferences) {
    return message.references;
  }
  
  // 否则只显示前3个
  return message.references.slice(0, 3);
}

/** 处理卡片操作 */
function handleCardAction(command) {
  const { action, data } = command;
  switch (action) {
    case 'edit':
      handleUpdate(data);
      break;
    case 'upload':
      handleUpload(data);
      break;
    case 'delete':
      handleDelete(data);
      break;
  }
}

/** 删除文件 */
function handleDeleteFile(file) {
  proxy.$modal.confirm(`是否确认删除文件"${file}"？`).then(() => {
    deleteKnowledgeFile(file, selectedKnowledge.value.collectionName).then(response => {
      proxy.$modal.msgSuccess("删除成功");
      // 刷新文件列表
      if (selectedKnowledge.value) {
        fileLoading.value = true;
        listKnowledgeDocument(selectedKnowledge.value.collectionName).then(response => {
          fileList.value = response.data;
          fileTotal.value = response.data.length;

          // 如果当前页没有数据了，回到上一页
          const maxPage = Math.ceil(fileTotal.value / filePageSize.value);
          if (filePageNum.value > maxPage && maxPage > 0) {
            filePageNum.value = maxPage;
          }

          fileLoading.value = false;
        }).catch(error => {
          fileLoading.value = false;
          proxy.$modal.msgError("刷新文件列表失败：" + error.message);
        });
      }
    }).catch(error => {
      proxy.$modal.msgError("删除失败：" + error.message);
    });
  }).catch(() => { });
}

/** 获取文件类型 */
function getFileType(fileName) {
  if (!fileName) return '未知';
  const extension = fileName.split('.').pop()?.toLowerCase();
  switch (extension) {
    case 'pdf':
      return 'PDF文档';
    case 'docx':
      return 'Word文档';
    default:
      return '文档';
  }
}

/** 文件分页处理 */
function handleFilePagination(pagination) {
  filePageNum.value = pagination.page;
  filePageSize.value = pagination.limit;
}

// 取消按钮
function cancel() {
  open.value = false;
  reset();
}

// 表单重置
function reset() {
  form.collectionName = '';
  form.description = '';
  form.newCollectionName = '';
  // 强制更新DOM
  nextTick(() => {
    proxy.resetForm("form");
  });
}

/** 搜索按钮操作 */
function handleQuery() {
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryForm");
  handleQuery();
}

/** 新增按钮操作 */
function handleAdd() {
  reset();
  open.value = true;
  title.value = "添加知识库";
  isModify.value = false;
}

/** 修改按钮操作 */
function handleUpdate(row) {
  reset();
  const collectionName = row?.collectionName || ids.value[0];
  if (!collectionName) {
    proxy.$modal.msgWarning("请先选择要修改的知识库");
    return;
  }
  form.collectionName = collectionName;
  form.newCollectionName = '';
  isModify.value = true;
  open.value = true;
  title.value = "修改知识库";
}

/** 提交按钮 */
function submitForm() {
  proxy.$refs["knowledgeFormRef"].validate(valid => {
    if (valid) {
      if (form.newCollectionName) {
        // 修改操作
        updateKnowledge(form.collectionName, form.newCollectionName).then(response => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        }).catch(error => {
          proxy.$modal.msgError("修改失败：" + error.message);
        });
      } else {
        // 新增操作
        addKnowledge(form.collectionName, form.description).then(response => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        }).catch(error => {
          proxy.$modal.msgError("新增失败：" + error.message);
        });
      }
    }
  });
}

/** 删除按钮操作 */
function handleDelete(row) {
  const collectionNames = row?.collectionName || ids.value;
  if (!collectionNames) {
    proxy.$modal.msgWarning("请先选择要删除的知识库");
    return;
  }
  proxy.$modal.confirm('是否确认删除知识库名称为"' + collectionNames + '"的数据项？').then(function () {
    return delKnowledge(collectionNames);
  }).then(() => {
    getList();
    // 如果删除的是当前选中的知识库，清空选择
    if (selectedKnowledge.value?.collectionName === collectionNames) {
      // 如果正在生成回答，先停止
      if (isSending.value) {
        stopGenerating();
      }
      selectedKnowledge.value = null;
      fileList.value = [];
      isChatMode.value = false;
      chatMessages.value = [];
    }
    proxy.$modal.msgSuccess("删除成功");
  }).catch((error) => {
    if (error !== 'cancel') {
      proxy.$modal.msgError("删除失败：" + error.message);
    }
  });
}

/** 上传文件按钮操作 */
function handleUpload(row) {
  const collectionName = row?.collectionName;
  if (!collectionName) {
    proxy.$modal.msgWarning("请先选择要上传文件的知识库");
    return;
  }
  uploadForm.collectionName = collectionName;
  uploadOpen.value = true;
}

// 文件上传中处理
function handleFileUploadProgress(event, file, fileList) {
  upload.isUploading = true;
}

function handleFileChange(file, fileList) {
  upload.fileList = fileList.map(f => f.raw)
  console.log(upload.fileList)
}

// 文件上传成功处理
function handleFileSuccess(response, file, fileList) {
  upload.isUploading = false;
  proxy.$refs.upload.clearFiles();
  proxy.$alert(response.msg, "导入结果", { dangerouslyUseHTMLString: true });
  uploadOpen.value = false;
  getList();
  // 如果当前有选中的知识库，刷新文件列表
  if (selectedKnowledge.value) {
    fileLoading.value = true;
    listKnowledgeDocument(selectedKnowledge.value.collectionName).then(response => {
      fileList.value = response.data;
      fileTotal.value = response.data.length;
      fileLoading.value = false;
    }).catch(error => {
      fileLoading.value = false;
      proxy.$modal.msgError("刷新文件列表失败：" + error.message);
    });
  }
}

// 提交上传
function submitUpload() {
  insertKnowledgeFile(upload.fileList, uploadForm.collectionName).then(response => {
    proxy.$modal.msgSuccess("上传成功");
    uploadOpen.value = false;
    proxy.$refs.knowledgeUpload.clearFiles();
    getList();
  }).catch(error => {
    proxy.$modal.msgError("上传失败：" + error.message);
  });
}

// 取消上传
function cancelUpload() {
  uploadOpen.value = false;
  proxy.$refs.knowledgeUpload.clearFiles();
}

onMounted(() => {
  getList();
});

// 组件卸载时清理请求控制器和超时定时器
onUnmounted(() => {
  if (window.currentController) {
    window.currentController.abort();
    window.currentController = null;
  }
  if (window.responseTimeout) {
    clearTimeout(window.responseTimeout);
    window.responseTimeout = null;
  }
});
</script>

<style lang="scss" scoped>
.app-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: #f5f7fa;
}

.top-toolbar {
  background: white;
  padding: 16px 24px;
  border-bottom: 1px solid #e4e7ed;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);

  .toolbar-actions {
    margin-top: 12px;
    display: flex;
    gap: 8px;
    align-items: center;
  }
}

.main-content {
  flex: 1;
  display: flex;
  gap: 16px;
  padding: 16px;
  overflow: hidden;
}

.left-panel {
  width: 400px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.right-panel {
  flex: 1;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.panel-header {
  padding: 20px 24px;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: #fafbfc;

  h3 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    color: #303133;
  }

  .knowledge-count {
    font-size: 12px;
    color: #909399;
    background: #f0f2f5;
    padding: 4px 8px;
    border-radius: 4px;
  }

  .header-actions {
    display: flex;
    gap: 8px;
  }
}

.knowledge-cards {
  flex: 1;
  padding: 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.knowledge-card {
  background: white;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  padding: 16px;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;

  &:hover {
    border-color: #409eff;
    box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
    transform: translateY(-2px);
  }

  &.active {
    border-color: #409eff;
    background: #f0f9ff;
    box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
  }

  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    margin-bottom: 12px;

    .card-title {
      display: flex;
      align-items: center;
      gap: 8px;
      flex: 1;

      .folder-icon {
        color: #409eff;
        font-size: 18px;
      }

      .title-text {
        font-weight: 600;
        color: #303133;
        font-size: 14px;
        line-height: 1.4;
      }
    }

    .card-actions {
      opacity: 0;
      transition: opacity 0.3s ease;
    }
  }

  &:hover .card-actions {
    opacity: 1;
  }

  .card-content {
    .description {
      color: #606266;
      font-size: 13px;
      line-height: 1.5;
      margin: 0 0 12px 0;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
      overflow: hidden;
    }

    .meta-info {
      display: flex;
      justify-content: space-between;
      align-items: center;
      font-size: 12px;
      color: #909399;

      .create-time {
        background: #f0f2f5;
        padding: 2px 6px;
        border-radius: 3px;
      }

      .file-count {
        background: #e1f3d8;
        color: #67c23a;
        padding: 2px 6px;
        border-radius: 3px;
      }
    }
  }
}

.file-content {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
}

// 聊天模式样式
.chat-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.selected-knowledge {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  background: #f0f9ff;
  border-radius: 6px;
  margin-bottom: 20px;

  .folder-icon {
    color: #409eff;
    font-size: 16px;
  }

  .knowledge-name {
    font-weight: 600;
    color: #303133;
  }

  .chat-mode-badge {
    background: #409eff;
    color: white;
    padding: 2px 8px;
    border-radius: 12px;
    font-size: 12px;
    margin-left: auto;
  }
}

.chat-messages {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
  background: #fafbfc;
}

.welcome-message {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;

  .welcome-content {
    max-width: 400px;

    .welcome-icon {
      font-size: 48px;
      margin-bottom: 16px;
    }

    h3 {
      margin: 0 0 12px 0;
      color: #303133;
      font-size: 18px;
    }

    p {
      margin: 0 0 8px 0;
      color: #606266;
      font-size: 14px;
      line-height: 1.6;
    }
  }
}

.message-list {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.message-item {
  display: flex;
  gap: 12px;

  &.user {
    flex-direction: row-reverse;

    .message-content {
      align-items: flex-end;
    }

    .message-bubble {
      background: #409eff;
      color: white;
      border-radius: 18px 18px 4px 18px;
    }
  }

  &.ai {
    .message-bubble {
      background: white;
      color: #303133;
      border: 1px solid #e4e7ed;
      border-radius: 18px 18px 18px 4px;
    }
  }
}

.message-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;

  .user-avatar {
    // background: #409eff;
    color: #409eff;
    font-size: 18px;
  }

  .ai-avatar {
    // background: #67c23a;
    color: white;
    font-size: 18px;
  }
}

.message-content {
  display: flex;
  flex-direction: column;
  max-width: 70%;
}

.message-bubble {
  padding: 12px 16px;
  line-height: 1.5;
  word-wrap: break-word;

  .message-text {
    margin-bottom: 8px;
    white-space: pre-wrap;
  }

  .message-references {
    margin: 12px 0;
    padding: 12px;
    background: rgba(0, 0, 0, 0.05);
    border-radius: 6px;
    border-left: 3px solid #409eff;

    .references-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 6px;
      margin-bottom: 8px;
      font-size: 13px;
      font-weight: 600;
      color: #409eff;

      .reference-icon {
        font-size: 14px;
      }

      .toggle-references {
        font-size: 11px;
        color: #909399;
        padding: 0;
        height: auto;
        
        &:hover {
          color: #409eff;
        }
      }
    }

    .references-list {
      display: flex;
      flex-direction: column;
      gap: 6px;
    }

    .reference-item {
      padding: 6px 8px;
      background: rgba(255, 255, 255, 0.8);
      border-radius: 4px;
      border: 1px solid rgba(0, 0, 0, 0.1);

      .reference-info {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 8px;

        .reference-filename {
          font-size: 12px;
          color: #303133;
          font-weight: 500;
          flex: 1;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }

                 .reference-similarity {
           font-size: 11px;
           padding: 2px 6px;
           border-radius: 10px;
           white-space: nowrap;
           font-weight: 500;
           transition: all 0.3s ease;

           &.high-similarity {
             color: #67c23a;
             background: #e1f3d8;
           }

           &.medium-similarity {
             color: #e6a23c;
             background: #fdf5e6;
           }

           &.low-similarity {
             color: #f56c6c;
             background: #fef0f0;
           }
         }
      }
    }
  }

  .message-time {
    font-size: 12px;
    opacity: 0.7;
  }
}

// 打字机效果的光标 - 只在正在生成时显示
.message-bubble.ai.typing .message-text:after {
  content: '|';
  animation: blink 1s infinite;
  color: #409eff;
}

@keyframes blink {

  0%,
  50% {
    opacity: 1;
  }

  51%,
  100% {
    opacity: 0;
  }
}

.chat-input-area {
  padding: 20px;
  border-top: 1px solid #e4e7ed;
  background: white;
}

.input-container {
  display: flex;
  gap: 12px;
  align-items: flex-end;

  .el-textarea {
    flex: 1;
  }

  .input-actions {
    flex-shrink: 0;
  }
}

.input-tips {
  margin-top: 8px;
  text-align: center;
  font-size: 12px;
  color: #999;
  display: flex;
  justify-content: space-between;
  align-items: center;

  .char-count {
    color: #409eff;
    font-weight: 500;

    &.warning {
      color: #e6a23c;
    }

    .error-text {
      color: #f56c6c;
      font-size: 11px;
    }
  }
}

.file-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.file-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
  background: #fafbfc;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  transition: all 0.3s ease;

  &:hover {
    border-color: #409eff;
    box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
  }

  .file-info {
    display: flex;
    align-items: center;
    gap: 12px;
    flex: 1;

    .file-icon {
      color: #409eff;
      font-size: 20px;
    }

    .file-details {
      .file-name {
        font-weight: 500;
        color: #303133;
        margin-bottom: 4px;
      }

      .file-meta {
        display: flex;
        gap: 12px;
        font-size: 12px;
        color: #909399;

        .file-type {
          background: #e1f3d8;
          color: #67c23a;
          padding: 2px 6px;
          border-radius: 3px;
        }
      }
    }
  }

  .file-actions {
    opacity: 0;
    transition: opacity 0.3s ease;
  }

  &:hover .file-actions {
    opacity: 1;
  }
}

// 文件列表分页样式
.file-content {
  :deep(.pagination-container) {
    margin-top: 20px;
    padding: 20px 0;
    text-align: center;
    background: transparent;
  }
}

.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  text-align: center;
  color: #909399;

  .empty-icon {
    font-size: 48px;
    margin-bottom: 16px;
    opacity: 0.5;
  }

  p {
    margin: 0 0 16px 0;
    font-size: 14px;
  }
}

.dialog-footer {
  text-align: right;
}

.el-upload__tip {
  font-size: 12px;
  color: #606266;
  margin-top: 7px;
}

:deep(.el-upload-dragger) {
  width: 350px;
}

:deep(.el-upload__text) {
  margin: 10px 0 16px;
  color: #606266;
  font-size: 14px;
}

:deep(.el-upload__tip) {
  font-size: 12px;
  color: #606266;
  margin-top: 7px;
}

// 修复上传文件列表中文件名过长的问题
:deep(.el-upload-list) {
  max-width: 100%;

  .el-upload-list__item {
    max-width: 100%;
    overflow: hidden;

    .el-upload-list__item-name {
      width: 350px; // 为删除按钮等留出空间
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      display: inline-block;
      vertical-align: middle;
    }
  }
}

// 修复拖拽区域内文件名显示问题
:deep(.el-upload-dragger) {
  .el-upload-list {
    .el-upload-list__item {
      margin: 0 10px 10px 10px;
      padding: 8px 12px;
      background: #f5f7fa;
      border-radius: 4px;

      .el-upload-list__item-name {
        color: #606266;
        font-size: 13px;
        max-width: calc(100% - 60px);
        word-wrap: break-word;
        word-break: break-all;
        white-space: normal;
        line-height: 1.4;
      }
    }
  }
}

// 响应式设计
@media (max-width: 1200px) {
  .main-content {
    flex-direction: column;
  }

  .left-panel {
    width: 100%;
    height: 300px;
  }
}

@media (max-width: 768px) {
  .top-toolbar {
    padding: 12px 16px;
  }

  .main-content {
    padding: 12px;
    gap: 12px;
  }

  .panel-header {
    padding: 16px 20px;
  }

  .knowledge-cards {
    padding: 12px;
  }

  .file-content {
    padding: 16px;
  }

  .chat-messages {
    padding: 16px;
  }

  .chat-input-area {
    padding: 16px;
  }

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

  .message-references {
    .references-header {
      flex-direction: column;
      align-items: flex-start;
      gap: 4px;

      .toggle-references {
        font-size: 10px;
      }
    }

    .reference-item {
      .reference-info {
        flex-direction: column;
        align-items: flex-start;
        gap: 4px;

        .reference-filename {
          font-size: 11px;
        }

        .reference-similarity {
          font-size: 10px;
          align-self: flex-end;
        }
      }
    }
  }
}

// Loading动画样式
.loading-dots {
  display: flex;
  gap: 4px;
  padding: 8px 0;

  span {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: #ccc;
    animation: loading 1.4s infinite ease-in-out;

    &:nth-child(1) {
      animation-delay: -0.32s;
    }

    &:nth-child(2) {
      animation-delay: -0.16s;
    }
  }
}

@keyframes loading {

  0%,
  80%,
  100% {
    transform: scale(0);
  }

  40% {
    transform: scale(1);
  }
}
</style>