<!-- 每个回话对应的聊天内容 -->
<script setup lang="ts">
import type { AnyObject } from 'typescript-api-pro';
import type { BubbleProps } from 'vue-element-plus-x/types/Bubble';
import type { BubbleListInstance } from 'vue-element-plus-x/types/BubbleList';
import type { FilesCardProps } from 'vue-element-plus-x/types/FilesCard';
import type { ThinkingStatus } from 'vue-element-plus-x/types/Thinking';
import type { UnifiedMessage } from '@/utils/apiFormatConverter';
import { ArrowLeftBold, ArrowRightBold, Clock, Delete, Document, DocumentCopy, Edit, Loading, Refresh } from '@element-plus/icons-vue';
import { ElIcon, ElMessage } from 'element-plus';
import { useHookFetch } from 'hook-fetch/vue';
import mammoth from 'mammoth';
import * as pdfjsLib from 'pdfjs-dist';
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import { Sender } from 'vue-element-plus-x';
import { useRoute } from 'vue-router';
import * as XLSX from 'xlsx';
import { deleteMessages, unifiedSend } from '@/api';
import MarkedMarkdown from '@/components/MarkedMarkdown/index.vue';
import ModelSelect from '@/components/ModelSelect/index.vue';

import Collapse from '@/layouts/components/Header/components/Collapse.vue';
import CreateChat from '@/layouts/components/Header/components/CreateChat.vue';
import TitleEditing from '@/layouts/components/Header/components/TitleEditing.vue';
import { useDesignStore, useGuideTourStore } from '@/stores';
import { useChatStore } from '@/stores/modules/chat';
import { useFilesStore } from '@/stores/modules/files';
import { useModelStore } from '@/stores/modules/model';
import { useSessionStore } from '@/stores/modules/session';
import { useUserStore } from '@/stores/modules/user';
import { convertToApiFormat, parseStreamChunk } from '@/utils/apiFormatConverter';
import '@/styles/github-markdown.css';
import '@/styles/yixin-markdown.scss';

// 新增的导入
const designStore = useDesignStore();
const sessionStore = useSessionStore();
const currentSession = computed(() => sessionStore.currentSession);

type MessageItem = BubbleProps & {
  key: number | string;
  id?: number | string; // 消息ID，用于删除
  role: 'ai' | 'user' | 'assistant' | string;
  avatar?: string;
  showAvatar?: boolean; // 是否显示头像
  thinkingStatus?: ThinkingStatus;
  thinlCollapse?: boolean;
  reasoning_content?: string;
  images?: Array<{ url: string; name?: string }>; // 用户消息中的图片列表
  files?: Array<{ name: string; size: number }>; // 用户消息中的文件列表
  creationTime?: string;
  tokenUsage?: { prompt: number; completion: number; total: number };
};

const route = useRoute();
const chatStore = useChatStore();
const modelStore = useModelStore();
const filesStore = useFilesStore();
const userStore = useUserStore();
const guideTourStore = useGuideTourStore();

// 用户头像
const avatar = computed(() => {
  const userInfo = userStore.userInfo;
  return userInfo?.avatar || 'https://avatars.githubusercontent.com/u/76239030?v=4';
});

const inputValue = ref('');
const senderRef = ref<InstanceType<typeof Sender> | null>(null);
const bubbleItems = ref<MessageItem[]>([]);
const bubbleListRef = ref<BubbleListInstance | null>(null);
const isSending = ref(false);

// 删除模式相关状态
const isDeleteMode = ref(false);
const selectedMessageIds = ref<(number | string)[]>([]);
const deleteTargetMessage = ref<MessageItem | null>(null); // 记录触发删除的消息

// 编辑模式相关状态
const editingMessageKey = ref<number | string | null>(null);
const editingContent = ref('');

// 临时ID计数器（用于新消息）
let tempIdCounter = -1;

// 文件处理相关常量（与 FilesSelect 保持一致）
const MAX_FILE_SIZE = 3 * 1024 * 1024;
const MAX_TOTAL_CONTENT_LENGTH = 150000;
const MAX_TEXT_FILE_LENGTH = 50000;
const MAX_WORD_LENGTH = 30000;
const MAX_EXCEL_ROWS = 100;
const MAX_PDF_PAGES = 10;

// 配置 PDF.js worker
pdfjsLib.GlobalWorkerOptions.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjsLib.version}/build/pdf.worker.min.mjs`;

// 记录当前请求使用的 API 格式类型，用于正确解析响应
const currentRequestApiType = ref<string>('');

// 创建统一发送请求的包装函数
function unifiedSendWrapper(params: any) {
  const { data, apiType, modelId, sessionId } = params;
  return unifiedSend(data, apiType, modelId, sessionId);
}

const { stream, loading: isLoading, cancel } = useHookFetch({
  request: unifiedSendWrapper,
  onError: async (error) => {
    isLoading.value = false;

    if (error.status === 403) {
      const data = await (error.response.json());
      // 弹窗提示
      ElMessage.error(data.error.message);
      return Promise.reject(data);
    }
    if (error.status === 401) {
      ElMessage.error('登录已过期，请重新登录！');
      // 弹窗提示
      userStore.logout();
      userStore.openLoginDialog();
    }
  },

});
// 记录进入思考中
let isThinking = false;

watch(
  () => route.params?.id,
  async (_id_) => {
    // 切换会话时重置状态
    exitDeleteMode();
    cancelEdit();
    tempIdCounter = -1;

    if (_id_) {
      if (_id_ !== 'not_login') {
        // 判断的当前会话id是否有聊天记录，有缓存则直接赋值展示
        if (chatStore.chatMap[`${_id_}`] && chatStore.chatMap[`${_id_}`].length) {
          bubbleItems.value = chatStore.chatMap[`${_id_}`] as MessageItem[];
          // 滚动到底部
          setTimeout(() => {
            bubbleListRef.value!.scrollToBottom();
          }, 350);
          return;
        }

        // 无缓存则请求聊天记录
        await chatStore.requestChatList(`${_id_}`);
        // 请求聊天记录后，赋值回显，并滚动到底部
        bubbleItems.value = chatStore.chatMap[`${_id_}`] as MessageItem[];
        // 滚动到底部
        setTimeout(() => {
          bubbleListRef.value!.scrollToBottom();
        }, 350);
      }

      // 如果本地有发送内容 ，则直接发送
      const v = localStorage.getItem('chatContent');
      if (v) {
        // 发送消息
        setTimeout(() => {
          startSSE(v);
        }, 350);

        localStorage.removeItem('chatContent');
      }
    }
  },
  { immediate: true, deep: true },
);

/**
 * 处理流式响应的数据块
 * 解析 AI 返回的数据，更新消息内容和思考状态
 * @param {AnyObject} chunk - 流式响应的数据块
 */
function handleDataChunk(chunk: AnyObject) {
  try {
    // 使用统一的解析器，根据当前请求的 API 格式类型解析响应
    const parsed = parseStreamChunk(chunk, currentRequestApiType.value || 'Completions');
    console.log('✅ [解析结果]:', parsed);

    const latest = bubbleItems.value[bubbleItems.value.length - 1];

    // 处理 token 使用情况
    if (parsed.usage) {
      latest.tokenUsage = {
        prompt: parsed.usage.prompt_tokens || 0,
        completion: parsed.usage.completion_tokens || 0,
        total: parsed.usage.total_tokens || 0,
      };
    }

    // 处理推理内容
    if (parsed.reasoning_content) {
      latest.thinkingStatus = 'thinking';
      latest.loading = true;
      latest.thinlCollapse = true;
      latest.reasoning_content += parsed.reasoning_content;
    }

    // 处理普通内容
    if (parsed.content) {
      const thinkStart = parsed.content.includes('<think>');
      const thinkEnd = parsed.content.includes('</think>');

      if (thinkStart)
        isThinking = true;
      if (thinkEnd)
        isThinking = false;

      if (isThinking) {
        latest.thinkingStatus = 'thinking';
        latest.loading = true;
        latest.thinlCollapse = true;
        latest.reasoning_content += parsed.content.replace('<think>', '').replace('</think>', '');
      }
      else {
        latest.thinkingStatus = 'end';
        latest.loading = false;
        latest.content += parsed.content;
      }
    }
  }
  catch (err) {
    console.error('解析数据时出错:', err);
  }
}

/**
 * 处理错误信息
 * @param {any} err - 错误对象
 */
function handleError(err: any) {
  console.error('Fetch error:', err);
}

/**
 * 发送消息并处理流式响应
 * 支持发送文本、图片和文件
 * @param {string} chatContent - 用户输入的文本内容
 * @param {boolean} skipAddUserMessage - 是否跳过添加用户消息（用于重新生成）
 */
async function startSSE(chatContent: string, skipAddUserMessage = false) {
  if (isSending.value)
    return;

  // 检查是否有未上传完成的文件
  const hasUnuploadedFiles = filesStore.filesList.some(f => !f.isUploaded);
  if (hasUnuploadedFiles && !skipAddUserMessage) {
    ElMessage.warning('文件正在上传中，请稍候...');
    return;
  }

  isSending.value = true;

  // 记录当前请求使用的 API 格式类型，用于后续正确解析响应
  currentRequestApiType.value = modelStore.currentModelInfo.modelApiType || 'Completions';
  console.log('🚀 [发送请求] 当前模型信息:', {
    modelId: modelStore.currentModelInfo.modelId,
    modelName: modelStore.currentModelInfo.modelName,
    modelApiType: modelStore.currentModelInfo.modelApiType,
    currentRequestApiType: currentRequestApiType.value,
  });

  try {
    // 清空输入框
    inputValue.value = '';

    // 获取当前上传的图片和文件（在清空之前保存）
    const imageFiles = filesStore.filesList.filter(f => f.isUploaded && f.fileType === 'image');
    const textFiles = filesStore.filesList.filter(f => f.isUploaded && f.fileType === 'text');

    const images = imageFiles.map(f => ({
      url: f.base64!, // 使用base64作为URL
      name: f.name,
    }));

    const files = textFiles.map(f => ({
      name: f.name!,
      size: f.fileSize!,
    }));

    // 如果不是跳过添加用户消息（正常发送模式），则添加用户消息
    if (!skipAddUserMessage) {
      addMessage(chatContent, true, images, files);
    }
    addMessage('', false);

    // 立即清空文件列表（不要等到响应完成）
    filesStore.clearFilesList();

    // 这里有必要调用一下 BubbleList 组件的滚动到底部 手动触发 自动滚动
    bubbleListRef.value?.scrollToBottom();

    // 组装消息内容，支持图片和文件
    const messagesContent = bubbleItems.value.slice(0, -1).slice(-6).map((item: MessageItem) => {
      const baseMessage: any = {
        role: item.role,
      };

      // 如果是用户消息且有附件（图片或文件），组装成数组格式
      if (item.role === 'user' && item.key === bubbleItems.value.length - 2) {
        // 当前发送的消息
        const contentArray: any[] = [];

        // 添加文本内容
        if (item.content) {
          contentArray.push({
            type: 'text',
            text: item.content,
          });
        }

        // 添加文本文件内容（使用XML格式）
        if (textFiles.length > 0) {
          let fileContent = '\n\n';
          textFiles.forEach((fileItem, index) => {
            fileContent += `<ATTACHMENT_FILE>\n`;
            fileContent += `<FILE_INDEX>File ${index + 1}</FILE_INDEX>\n`;
            fileContent += `<FILE_NAME>${fileItem.name}</FILE_NAME>\n`;
            fileContent += `<FILE_CONTENT>\n${fileItem.fileContent}\n</FILE_CONTENT>\n`;
            fileContent += `</ATTACHMENT_FILE>\n`;
            if (index < textFiles.length - 1) {
              fileContent += '\n';
            }
          });

          contentArray.push({
            type: 'text',
            text: fileContent,
          });
        }

        // 添加图片内容（使用之前保存的 imageFiles）
        imageFiles.forEach((fileItem) => {
          if (fileItem.base64) {
            contentArray.push({
              type: 'image_url',
              image_url: {
                url: fileItem.base64, // 使用base64
                name: fileItem.name, // 保存图片名称
              },
            });
          }
        });

        // 如果有图片或文件，使用数组格式
        if (contentArray.length > 1 || imageFiles.length > 0 || textFiles.length > 0) {
          baseMessage.content = contentArray;
        }
        else {
          baseMessage.content = item.content;
        }
      }
      else {
        // 其他消息保持原样
        baseMessage.content = (item.role === 'ai' || item.role === 'assistant') && item.content.length > 10000
          ? `${item.content.substring(0, 10000)}...（内容过长，已省略）`
          : item.content;
      }

      return baseMessage;
    });

    // 获取当前模型的 API 类型
    const apiType = modelStore.currentModelInfo.modelApiType || 'Completions';
    console.log('📤 [转换请求] API 类型:', apiType);
    console.log('📤 [转换前] 消息内容:', messagesContent);

    // 根据 API 类型转换请求格式
    const convertedRequest = convertToApiFormat(
      messagesContent as UnifiedMessage[],
      apiType,
      modelStore.currentModelInfo.modelId ?? '',
      true,
    );

    console.log('📤 [转换后] 请求体:', convertedRequest);

    // 使用新的统一接口发送请求
    const sessionId = route.params?.id !== 'not_login' ? String(route.params?.id) : 'not_login';
    const modelId = modelStore.currentModelInfo.modelId ?? '';

    for await (const chunk of stream({
      data: convertedRequest,
      apiType,
      modelId,
      sessionId,
    })) {
      console.log('📦 [接收响应] 原始数据块:', chunk.result);
      console.log('🔧 [解析响应] 使用格式:', currentRequestApiType.value);
      handleDataChunk(chunk.result as AnyObject);
    }
  }
  catch (err) {
    if (err.name === 'AbortError') {
      console.log('用户中止请求'); // 正常中止，无需提示
    }
    else {
      handleError(err); // 其他错误
      // ElMessage.error('消息发送失败，请重试');
    }
  }
  finally {
    isSending.value = false;

    // 停止打字器状态和加载状态
    if (bubbleItems.value.length) {
      const latest = bubbleItems.value[bubbleItems.value.length - 1];
      latest.typing = false;
      latest.loading = false;
      if (latest.thinkingStatus === 'thinking') {
        latest.thinkingStatus = 'end';
      }
    }

    // 保存聊天记录到 chatMap（本地缓存，刷新后可恢复）
    if (route.params?.id && route.params.id !== 'not_login') {
      chatStore.chatMap[`${route.params.id}`] = bubbleItems.value as any;
    }
  }
}

/**
 * 中断正在进行的请求
 * 停止流式响应并重置状态
 */
async function cancelSSE() {
  try {
    cancel(); // 直接调用，无需参数
    isSending.value = false;
    if (bubbleItems.value.length) {
      const latest = bubbleItems.value[bubbleItems.value.length - 1];
      latest.typing = false;
      latest.loading = false;
      if (latest.thinkingStatus === 'thinking') {
        latest.thinkingStatus = 'end';
      }
    }
  }
  catch (err) {
    handleError(err);
  }
}

/**
 * 添加消息到聊天列表
 * @param {string} message - 消息内容
 * @param {boolean} isUser - 是否为用户消息
 * @param {Array<{url: string, name?: string}>} images - 图片列表（可选）
 * @param {Array<{name: string, size: number}>} files - 文件列表（可选）
 */
function addMessage(message: string, isUser: boolean, images?: Array<{ url: string; name?: string }>, files?: Array<{ name: string; size: number }>) {
  const tempId = tempIdCounter--;
  const obj: MessageItem = {
    key: tempId,
    id: tempId,
    // 头像不显示（后续可能会显示）
    // avatar: isUser ? getUserProfilePicture() : systemProfilePicture,
    // avatarSize: '32px',
    role: isUser ? 'user' : 'assistant',
    placement: isUser ? 'end' : 'start',
    // 用户消息：气泡形状；AI消息：无气泡形状，宽度100%
    isMarkdown: !isUser,
    loading: !isUser,
    content: message || '',
    reasoning_content: '',
    thinkingStatus: 'start',
    thinlCollapse: false,
    // AI消息使用 noStyle 去除气泡样式，宽度100%
    noStyle: !isUser,
    shape: isUser ? 'corner' : undefined,
    images: images && images.length > 0 ? images : undefined,
    files: files && files.length > 0 ? files : undefined,
  };
  bubbleItems.value.push(obj);
}

/**
 * 处理思考链展开/收起状态变化
 * @param {object} payload - 状态变化的载荷
 * @param {boolean} payload.value - 展开/收起状态
 * @param {ThinkingStatus} payload.status - 思考状态
 */
function handleChange(payload: { value: boolean; status: ThinkingStatus }) {
}

/**
 * 删除文件卡片
 * @param {FilesCardProps} _item - 文件卡片项（未使用）
 * @param {number} index - 要删除的文件索引
 */
function handleDeleteCard(_item: FilesCardProps, index: number) {
  filesStore.deleteFileByIndex(index);
}

watch(
  () => filesStore.filesList.length,
  (val) => {
    if (val > 0) {
      nextTick(() => {
        senderRef.value?.openHeader();
      });
    }
    else {
      nextTick(() => {
        senderRef.value?.closeHeader();
      });
    }
  },
);

/**
 * 复制消息内容到剪贴板
 * @param {any} item - 消息项
 */
function copy(item: any) {
  navigator.clipboard.writeText(item.content || '')
    .then(() => ElMessage.success('已复制到剪贴板'))
    .catch(() => ElMessage.error('复制失败'));
}

/**
 * 进入删除模式（从指定消息开始）
 * @param item - 触发删除的消息
 */
function enterDeleteMode(item?: MessageItem) {
  isDeleteMode.value = true;
  selectedMessageIds.value = [];
  deleteTargetMessage.value = item || null;

  // 如果指定了消息，自动选中该消息及其之后的所有消息
  if (item && item.id) {
    const itemIndex = bubbleItems.value.findIndex(msg => msg.key === item.key);
    if (itemIndex !== -1) {
      const messagesToDelete = bubbleItems.value.slice(itemIndex);
      selectedMessageIds.value = messagesToDelete.filter(msg => msg.id).map(msg => msg.id!);
    }
  }
}

/**
 * 退出删除模式
 */
function exitDeleteMode() {
  isDeleteMode.value = false;
  selectedMessageIds.value = [];
  deleteTargetMessage.value = null;
}

/**
 * 切换消息选中状态
 */
function toggleMessageSelection(item: MessageItem) {
  if (!item.id)
    return;
  const index = selectedMessageIds.value.indexOf(item.id);
  if (index > -1) {
    selectedMessageIds.value.splice(index, 1);
  }
  else {
    selectedMessageIds.value.push(item.id);
  }
}

/**
 * 确认删除选中的消息
 */
async function confirmDelete() {
  if (selectedMessageIds.value.length === 0) {
    ElMessage.warning('请选择要删除的消息');
    return;
  }

  // 区分已保存消息（有有效ID）和临时消息（负数ID或undefined）
  const savedIds = selectedMessageIds.value.filter(id => typeof id === 'string' || (typeof id === 'number' && id > 0));
  const tempIds = selectedMessageIds.value.filter(id => typeof id === 'number' && id < 0);
  console.log('savedIds---', savedIds);
  try {
    // 只有已保存的消息才调用删除接口
    if (savedIds.length > 0) {
      await deleteMessages({ ids: savedIds, isDeleteSubsequent: false });
    }

    // 从本地列表中移除已删除的消息（包括临时消息）
    bubbleItems.value = bubbleItems.value.filter((item) => {
      const itemId = item.id;
      if (itemId === undefined)
        return true;
      return !savedIds.includes(itemId) && !tempIds.includes(itemId as number);
    });

    // 更新缓存
    if (route.params?.id && route.params.id !== 'not_login') {
      chatStore.chatMap[`${route.params.id}`] = bubbleItems.value as any;
    }

    ElMessage.success('删除成功');
    exitDeleteMode();
  }
  catch (error) {
    ElMessage.error('删除失败');
  }
}

/**
 * 重新生成AI消息
 * 删除对应的用户消息及之后的所有消息，然后重新发送用户消息
 * 这样可以避免后端重复保存用户消息（因为旧的用户消息已被删除）
 */
async function regenerateMessage(item: MessageItem) {
  if (isSending.value)
    return;

  const itemIndex = bubbleItems.value.findIndex(msg => msg.key === item.key);
  if (itemIndex === -1)
    return;

  // 找到该AI消息对应的用户消息（往前找最近的一条用户消息）
  let targetUserMessageIndex = -1;
  for (let i = itemIndex - 1; i >= 0; i--) {
    if (bubbleItems.value[i]?.role === 'user') {
      targetUserMessageIndex = i;
      break;
    }
  }

  if (targetUserMessageIndex === -1) {
    ElMessage.error('未找到对应的用户消息');
    return;
  }

  // 获取用户消息的ID（只传这一个ID，后端会根据 isDeleteSubsequent 删除后续消息）
  const targetUserMessage = bubbleItems.value[targetUserMessageIndex];
  const userMessageId = targetUserMessage.id;
  const userContent = targetUserMessage.content || '';

  try {
    // 调用删除接口（只传用户消息ID，后端会自动删除后续消息）
    if (userMessageId !== undefined && (typeof userMessageId === 'string' || (typeof userMessageId === 'number' && userMessageId > 0))) {
      await deleteMessages({ ids: [userMessageId], isDeleteSubsequent: true });
    }

    // 从本地列表中移除（包括临时消息）
    bubbleItems.value = bubbleItems.value.slice(0, targetUserMessageIndex);

    // 调用 startSSE 重新发送用户消息（这会添加新的用户消息和AI消息，然后发送请求）
    await startSSE(userContent);
  }
  catch (error) {
    ElMessage.error('重新生成失败');
  }
}

/**
 * 进入编辑模式
 */
function startEditMessage(item: MessageItem) {
  editingMessageKey.value = item.key;
  editingContent.value = item.content || '';
}

/**
 * 取消编辑
 */
function cancelEdit() {
  editingMessageKey.value = null;
  editingContent.value = '';
}

/**
 * 提交编辑后的消息
 * 删除当前消息及之后的消息，发送新消息
 */
async function submitEditMessage(item: MessageItem) {
  if (isSending.value || !editingContent.value.trim())
    return;

  const itemIndex = bubbleItems.value.findIndex(msg => msg.key === item.key);
  if (itemIndex === -1)
    return;

  // 获取当前编辑消息的ID（只传这一个ID，后端会根据 isDeleteSubsequent 删除后续消息）
  const messageId = item.id;
  const newContent = editingContent.value.trim();
  cancelEdit();

  try {
    // 调用删除接口（只传当前消息ID，后端会自动删除后续消息）
    if (messageId !== undefined && (typeof messageId === 'string' || (typeof messageId === 'number' && messageId > 0))) {
      await deleteMessages({ ids: [messageId], isDeleteSubsequent: true });
    }

    // 从本地列表中移除（包括临时消息）
    bubbleItems.value = bubbleItems.value.slice(0, itemIndex);

    // 发送新消息
    await startSSE(newContent);
  }
  catch (error) {
    ElMessage.error('编辑失败');
  }
}

/**
 * 图片预览
 * 在新窗口中打开图片
 * @param {string} url - 图片 URL
 */
function handleImagePreview(url: string) {
  window.open(url, '_blank');
}

/**
 * 压缩图片
 */
function compressImage(file: File, maxWidth = 1024, maxHeight = 1024, quality = 0.8): Promise<Blob> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const img = new Image();
      img.onload = () => {
        const canvas = document.createElement('canvas');
        let width = img.width;
        let height = img.height;

        if (width > maxWidth || height > maxHeight) {
          const ratio = Math.min(maxWidth / width, maxHeight / height);
          width = width * ratio;
          height = height * ratio;
        }

        canvas.width = width;
        canvas.height = height;

        const ctx = canvas.getContext('2d')!;
        ctx.drawImage(img, 0, 0, width, height);

        canvas.toBlob(
          (blob) => {
            if (blob) {
              resolve(blob);
            }
            else {
              reject(new Error('压缩失败'));
            }
          },
          file.type,
          quality,
        );
      };
      img.onerror = reject;
      img.src = e.target?.result as string;
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

/**
 * 将 Blob 转换为 base64
 */
function blobToBase64(blob: Blob): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      resolve(reader.result as string);
    };
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}

/**
 * 判断是否为文本文件
 */
function isTextFile(file: File): boolean {
  if (file.type.startsWith('text/'))
    return true;

  const textExtensions = [
    'txt',
    'log',
    'md',
    'markdown',
    'json',
    'xml',
    'yaml',
    'yml',
    'toml',
    'ini',
    'conf',
    'config',
    'js',
    'jsx',
    'ts',
    'tsx',
    'vue',
    'html',
    'htm',
    'css',
    'scss',
    'sass',
    'less',
    'java',
    'c',
    'cpp',
    'h',
    'hpp',
    'cs',
    'py',
    'rb',
    'go',
    'rs',
    'swift',
    'kt',
    'php',
    'sh',
    'bash',
    'sql',
    'csv',
    'tsv',
  ];

  const ext = file.name.split('.').pop()?.toLowerCase();
  return ext ? textExtensions.includes(ext) : false;
}

/**
 * 读取文本文件
 */
function readTextFile(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result as string);
    reader.onerror = reject;
    reader.readAsText(file, 'UTF-8');
  });
}

/**
 * 解析 Excel 文件
 */
async function parseExcel(file: File): Promise<{ content: string; totalRows: number; extractedRows: number }> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        const data = new Uint8Array(e.target?.result as ArrayBuffer);
        const workbook = XLSX.read(data, { type: 'array' });

        let result = '';
        let totalRows = 0;
        let extractedRows = 0;

        workbook.SheetNames.forEach((sheetName, index) => {
          const worksheet = workbook.Sheets[sheetName];
          const range = XLSX.utils.decode_range(worksheet['!ref'] || 'A1');
          const sheetTotalRows = range.e.r - range.s.r + 1;
          totalRows += sheetTotalRows;

          const rowsToExtract = Math.min(sheetTotalRows, MAX_EXCEL_ROWS);
          extractedRows += rowsToExtract;

          const limitedData: any[][] = [];
          for (let row = range.s.r; row < range.s.r + rowsToExtract; row++) {
            const rowData: any[] = [];
            for (let col = range.s.c; col <= range.e.c; col++) {
              const cellAddress = XLSX.utils.encode_cell({ r: row, c: col });
              const cell = worksheet[cellAddress];
              rowData.push(cell ? cell.v : '');
            }
            limitedData.push(rowData);
          }

          const csvData = limitedData.map(row => row.join(',')).join('\n');
          if (workbook.SheetNames.length > 1)
            result += `=== Sheet: ${sheetName} ===\n`;
          result += csvData;
          if (index < workbook.SheetNames.length - 1)
            result += '\n\n';
        });

        resolve({ content: result, totalRows, extractedRows });
      }
      catch (error) {
        reject(error);
      }
    };
    reader.onerror = reject;
    reader.readAsArrayBuffer(file);
  });
}

/**
 * 解析 Word 文档
 */
async function parseWord(file: File): Promise<{ content: string; totalLength: number; extracted: boolean }> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = async (e) => {
      try {
        const arrayBuffer = e.target?.result as ArrayBuffer;
        const result = await mammoth.extractRawText({ arrayBuffer });
        const fullText = result.value;
        const totalLength = fullText.length;

        if (totalLength > MAX_WORD_LENGTH) {
          const truncated = fullText.substring(0, MAX_WORD_LENGTH);
          resolve({ content: truncated, totalLength, extracted: true });
        }
        else {
          resolve({ content: fullText, totalLength, extracted: false });
        }
      }
      catch (error) {
        reject(error);
      }
    };
    reader.onerror = reject;
    reader.readAsArrayBuffer(file);
  });
}

/**
 * 解析 PDF 文件
 */
async function parsePDF(file: File): Promise<{ content: string; totalPages: number; extractedPages: number }> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = async (e) => {
      try {
        const typedArray = new Uint8Array(e.target?.result as ArrayBuffer);
        const pdf = await pdfjsLib.getDocument(typedArray).promise;
        const totalPages = pdf.numPages;
        const pagesToExtract = Math.min(totalPages, MAX_PDF_PAGES);

        let fullText = '';
        for (let i = 1; i <= pagesToExtract; i++) {
          const page = await pdf.getPage(i);
          const textContent = await page.getTextContent();
          const pageText = textContent.items.map((item: any) => item.str).join(' ');
          fullText += `${pageText}\n`;
        }

        resolve({ content: fullText, totalPages, extractedPages: pagesToExtract });
      }
      catch (error) {
        reject(error);
      }
    };
    reader.onerror = reject;
    reader.readAsArrayBuffer(file);
  });
}

/**
 * 处理粘贴事件
 */
async function handlePaste(event: ClipboardEvent) {
  const items = event.clipboardData?.items;
  if (!items)
    return;

  const files: File[] = [];
  for (let i = 0; i < items.length; i++) {
    const item = items[i];
    if (item.kind === 'file') {
      const file = item.getAsFile();
      if (file) {
        files.push(file);
      }
    }
  }

  if (files.length === 0)
    return;

  event.preventDefault();

  // 计算已有文件的总内容长度
  let totalContentLength = 0;
  filesStore.filesList.forEach((f) => {
    if (f.fileType === 'text' && f.fileContent) {
      totalContentLength += f.fileContent.length;
    }
    if (f.fileType === 'image' && f.base64) {
      totalContentLength += Math.floor(f.base64.length * 0.5);
    }
  });

  const arr: any[] = [];

  for (const file of files) {
    // 验证文件大小
    if (file.size > MAX_FILE_SIZE) {
      ElMessage.error(`文件 ${file.name} 超过 3MB 限制，已跳过`);
      continue;
    }

    const isImage = file.type.startsWith('image/');

    if (isImage) {
      try {
        const compressionLevels = [
          { maxWidth: 800, maxHeight: 800, quality: 0.6 },
          { maxWidth: 600, maxHeight: 600, quality: 0.5 },
          { maxWidth: 400, maxHeight: 400, quality: 0.4 },
        ];

        let compressedBlob: Blob | null = null;
        let base64 = '';

        for (const level of compressionLevels) {
          compressedBlob = await compressImage(file, level.maxWidth, level.maxHeight, level.quality);
          base64 = await blobToBase64(compressedBlob);

          const estimatedLength = Math.floor(base64.length * 0.5);
          if (totalContentLength + estimatedLength <= MAX_TOTAL_CONTENT_LENGTH) {
            totalContentLength += estimatedLength;
            break;
          }

          compressedBlob = null;
        }

        if (!compressedBlob) {
          ElMessage.error(`${file.name} 图片内容过大，请压缩后上传`);
          continue;
        }

        arr.push({
          uid: crypto.randomUUID(),
          name: file.name,
          fileSize: file.size,
          file,
          maxWidth: '200px',
          showDelIcon: true,
          imgPreview: true,
          imgVariant: 'square',
          url: base64,
          isUploaded: true,
          base64,
          fileType: 'image',
        });
      }
      catch (error) {
        console.error('处理图片失败:', error);
        ElMessage.error(`${file.name} 处理失败`);
      }
    }
    else {
      ElMessage.warning(`${file.name} 不支持粘贴，请使用上传按钮`);
    }
  }

  if (arr.length > 0) {
    filesStore.setFilesList([...filesStore.filesList, ...arr]);
    ElMessage.success(`已添加 ${arr.length} 个文件`);
  }
}

// 监听粘贴事件
onMounted(() => {
  document.addEventListener('paste', handlePaste);
});

onUnmounted(() => {
  document.removeEventListener('paste', handlePaste);
});
</script>

<template>
  <div class="chat-with-id-container">
    <!-- 头部导航栏 -->
    <div class="chat-header">
      <div
        class="overflow-hidden flex h-full items-center flex-row flex-1 w-fit flex-shrink-0 min-w-0"
      >
        <div class="w-full flex items-center flex-row">
          <!-- 左边 -->
          <div

            class="left-box flex h-full items-center pl-20px gap-12px flex-shrink-0 flex-row"
          >
            <Collapse />
            <CreateChat />
            <div v-if="currentSession" class="w-0.5px h-30px bg-[rgba(217,217,217)]" />
          </div>

          <!-- 中间 -->
          <div class="middle-box flex-1 min-w-0 ml-12px">
            <TitleEditing />
          </div>
        </div>
      </div>
    </div>

    <!-- 聊天内容区域 -->
    <div class="chat-warp">
      <!-- 删除模式工具栏 -->
      <div v-if="isDeleteMode" class="delete-mode-toolbar">
        <span class="selected-count">已选择 {{ selectedMessageIds.length }} 条消息</span>
        <div class="toolbar-actions">
          <el-button type="danger" size="small" @click="confirmDelete">
            确认删除
          </el-button>
          <el-button size="small" @click="exitDeleteMode">
            取消
          </el-button>
        </div>
      </div>

      <BubbleList
        ref="bubbleListRef"
        :list="bubbleItems"
        max-height="calc(100vh - 240px)"
        :class="{ 'delete-mode': isDeleteMode }"
      >
        <template #header="{ item }">
          <Thinking
            v-if="item.reasoning_content && !isDeleteMode"
            v-model="item.thinlCollapse"
            :content="item.reasoning_content"
            :status="item.thinkingStatus"
            class="thinking-chain-warp"
            @change="handleChange"
          />
        </template>

        <!-- 自定义气泡内容 -->
        <template #content="{ item }">
          <!-- 删除模式：勾选框（绝对定位在 content 左上角） -->
          <template v-if="isDeleteMode">
            <div
              v-if="item.id"
              class="delete-checkbox-inline"
              @click.stop="toggleMessageSelection(item)"
            >
              <el-checkbox
                :model-value="selectedMessageIds.includes(item.id)"
                @click.stop
                @update:model-value="toggleMessageSelection(item)"
              />
            </div>

            <!-- AI 消息内容（点击切换选中） -->
            <template v-if="item.role !== 'user'">
              <div
                class="ai-content-wrapper delete-mode-ai-content"
                @click="item.id && toggleMessageSelection(item)"
              >
                <MarkedMarkdown v-if="item.content" class="markdown-body" :content="item.content" />
              </div>
            </template>

            <!-- user 内容（气泡样式，点击切换选中） -->
            <template v-if="item.role === 'user'">
              <div
                class="user-content-wrapper delete-mode-user-content"
                @click="item.id && toggleMessageSelection(item)"
              >
                <template v-if="editingMessageKey === item.key">
                  <div class="edit-message-wrapper-full">
                    <el-input
                      v-model="editingContent"
                      type="textarea"
                      :autosize="{ minRows: 3, maxRows: 10 }"
                      placeholder="编辑消息内容"
                    />
                    <div class="edit-actions">
                      <el-button type="primary" size="small" @click.stop="submitEditMessage(item)">
                        发送
                      </el-button>
                      <el-button size="small" @click.stop="cancelEdit">
                        取消
                      </el-button>
                    </div>
                  </div>
                </template>
                <template v-else>
                  <!-- 用户消息内容（直接显示，无气泡背景） -->
                  <div v-if="item.images && item.images.length > 0" class="user-images">
                    <img
                      v-for="(image, index) in item.images"
                      :key="index"
                      :src="image.url"
                      :alt="image.name || '图片'"
                      class="user-image"
                      @click.stop="() => handleImagePreview(image.url)"
                    >
                  </div>
                  <div v-if="item.files && item.files.length > 0" class="user-files">
                    <div
                      v-for="(file, index) in item.files"
                      :key="index"
                      class="user-file-item"
                    >
                      <ElIcon class="file-icon">
                        <Document />
                      </ElIcon>
                      <span class="file-name">{{ file.name }}</span>
                    </div>
                  </div>
                  <div v-if="item.content" class="user-content">
                    {{ item.content }}
                  </div>
                </template>
              </div>
            </template>
          </template>

          <!-- 正常模式：AI 消息 -->
          <template v-if="!isDeleteMode && item.role !== 'user'">
            <div class="ai-content-wrapper">
              <MarkedMarkdown v-if="item.content" class="markdown-body" :content="item.content" />
            </div>
          </template>

          <!-- 正常模式：user 内容 -->
          <template v-if="!isDeleteMode && item.role === 'user'">
            <div class="user-content-wrapper">
              <!-- 编辑模式 - 宽度铺开 -->
              <div v-if="editingMessageKey === item.key" class="edit-message-wrapper-full">
                <el-input
                  v-model="editingContent"
                  type="textarea"
                  :autosize="{ minRows: 3, maxRows: 10 }"
                  placeholder="编辑消息内容"
                />
                <div class="edit-actions">
                  <el-button type="primary" size="small" @click="submitEditMessage(item)">
                    发送
                  </el-button>
                  <el-button size="small" @click="cancelEdit">
                    取消
                  </el-button>
                </div>
              </div>
              <!-- 正常显示模式 -->
              <template v-else>
                <!-- 图片列表 -->
                <div v-if="item.images && item.images.length > 0" class="user-images">
                  <img
                    v-for="(image, index) in item.images"
                    :key="index"
                    :src="image.url"
                    :alt="image.name || '图片'"
                    class="user-image"
                    @click="() => handleImagePreview(image.url)"
                  >
                </div>
                <!-- 文件列表 -->
                <div v-if="item.files && item.files.length > 0" class="user-files">
                  <div
                    v-for="(file, index) in item.files"
                    :key="index"
                    class="user-file-item"
                  >
                    <ElIcon class="file-icon">
                      <Document />
                    </ElIcon>
                    <span class="file-name">{{ file.name }}</span>
                  </div>
                </div>
                <!-- 文本内容 -->
                <div v-if="item.content" class="user-content">
                  {{ item.content }}
                </div>
              </template>
            </div>
          </template>
        </template>

        <!-- 自定义底部 -->
        <template #footer="{ item }">
          <div v-if="!isDeleteMode" class="footer-wrapper">
            <div class="footer-container">
              <!-- 时间和token信息 -->
              <div class="footer-info">
                <span v-if="item.creationTime" class="footer-time">
                  <ElIcon><Clock /></ElIcon>
                  {{ item.creationTime }}
                </span>
                <span v-if="item.role !== 'user' && item?.tokenUsage?.total" class="footer-token">
                  {{ item?.tokenUsage?.total }} tokens
                </span>
              </div>
              <!-- 操作按钮组 -->
              <div class="footer-actions">
                <!-- 复制按钮 -->
                <el-tooltip content="复制" placement="top">
                  <el-button text @click="copy(item)">
                    <ElIcon><DocumentCopy /></ElIcon>
                  </el-button>
                </el-tooltip>
                <!-- AI消息：重新生成按钮 (role可能是'assistant'或'ai') -->
                <el-tooltip v-if="item.role !== 'user'" content="重新生成" placement="top">
                  <el-button text :disabled="isSending" @click="regenerateMessage(item)">
                    <ElIcon><Refresh /></ElIcon>
                  </el-button>
                </el-tooltip>
                <!-- 用户消息：编辑按钮 -->
                <el-tooltip v-if="item.role === 'user'" content="编辑" placement="top">
                  <el-button text :disabled="isSending" @click="startEditMessage(item)">
                    <ElIcon><Edit /></ElIcon>
                  </el-button>
                </el-tooltip>
                <!-- 删除按钮 -->
                <el-tooltip content="删除" placement="top">
                  <el-button text @click="enterDeleteMode(item)">
                    <ElIcon><Delete /></ElIcon>
                  </el-button>
                </el-tooltip>
              </div>
            </div>
          </div>
        </template>
      </BubbleList>

      <Sender
        ref="senderRef" v-model="inputValue" class="chat-defaul-sender" data-tour="chat-sender" :auto-size="{
          maxRows: 6,
          minRows: 2,
        }" variant="updown" clearable allow-speech :loading="isLoading" @submit="startSSE" @cancel="cancelSSE"
      >
        <template #header>
          <div class="sender-header p-12px pt-6px pb-0px">
            <Attachments :items="filesStore.filesList" :hide-upload="true" @delete-card="handleDeleteCard">
              <template #prev-button="{ show, onScrollLeft }">
                <div
                  v-if="show"
                  class="prev-next-btn left-8px flex-center w-22px h-22px rounded-8px border-1px border-solid border-[rgba(0,0,0,0.08)] c-[rgba(0,0,0,.4)] hover:bg-#f3f4f6 bg-#fff font-size-10px"
                  @click="onScrollLeft"
                >
                  <ElIcon>
                    <ArrowLeftBold />
                  </ElIcon>
                </div>
              </template>

              <template #next-button="{ show, onScrollRight }">
                <div
                  v-if="show"
                  class="prev-next-btn right-8px flex-center w-22px h-22px rounded-8px border-1px border-solid border-[rgba(0,0,0,0.08)] c-[rgba(0,0,0,.4)] hover:bg-#f3f4f6 bg-#fff font-size-10px"
                  @click="onScrollRight"
                >
                  <ElIcon>
                    <ArrowRightBold />
                  </ElIcon>
                </div>
              </template>
            </Attachments>
          </div>
        </template>
        <template #prefix>
          <div class="flex-1 flex items-center gap-8px flex-none w-fit overflow-hidden">
            <FilesSelect />
            <!--            < ToolList/> -->
            <ModelSelect />
          </div>
        </template>
        <!-- 新增的 #suffix 模板 -->
        <template #suffix>
          <ElIcon v-if="isSending" class="is-loading">
            <Loading />
          </ElIcon>
        </template>
      </Sender>
    </div>
  </div>
</template>

<style scoped lang="scss">
.chat-with-id-container {
  padding: 0 20px;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  height: 100%;

  .chat-header {
    width: 100%;
    //max-width: 1000px;
    height: 60px;
    display: flex;
    align-items: center;
    flex-shrink: 0;
  }

  .chat-warp {
    max-width: 1000px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    width: 100%;
    height: calc(100vh - 120px); // 减去头部高度
    .thinking-chain-warp {
      margin-bottom: 12px;
    }
  }
  :deep() {
    .el-bubble-list {
      padding-top: 24px;

      // 删除模式
      &.delete-mode {
        .el-bubble {
          // 删除模式下：用户消息加回 flex:auto
          &[class*="end"] .el-bubble-content-wrapper {
            flex: auto;
          }

          // 删除模式下的 content 样式 - 全宽背景
          .el-bubble-content {
            position: relative;
            background-color: #f5f7fa;
            border: 1px solid transparent;
            border-radius: 8px;
            padding: 12px 16px;
            transition: all 0.2s;
            cursor: pointer;
            min-height: 44px;

            // 悬浮状态
            &:hover {
              background-color: #e8f0fe;
              border-color: #c6dafc;
            }

            // 勾选框绝对定位在左上角
            .delete-checkbox-inline {
              position: absolute;
              left: 12px;
              top: 12px;
              z-index: 2;

              .el-checkbox {
                --el-checkbox-input-height: 20px;
                --el-checkbox-input-width: 20px;
              }
            }

            // AI 内容区域左边距
            .ai-content-wrapper {
              margin-left: 36px;
            }

            // 用户消息容器 - 宽度铺满（和 AI 消息一样）
            .user-content-wrapper {
              margin-left: 36px;
              width: calc(100% - 36px);
              align-items: flex-start;

              // 编辑模式宽度100%
              .edit-message-wrapper-full {
                width: 100%;
                max-width: 100%;
              }
            }

            // 删除模式下：覆盖默认的 end 布局，让宽度 100%
            &[class*="end"] {
              width: 100%;
              max-width: 100%;

              .el-bubble-content {
                width: 100%;
                max-width: 100%;
              }
            }
          }

          // 选中状态
          &:has(.el-checkbox.is-checked) .el-bubble-content {
            background-color: #d2e3fc;
            border-color: #8ab4f8;
          }
        }
      }
    }

    .el-bubble {
      padding: 0 12px;
      padding-bottom: 24px;

      // AI消息（非用户消息）：宽度100%，无气泡形状
      &[class*="start"] {
        width: 100%;
        max-width: 100%;

        .el-bubble-content {
          width: 100%;
          max-width: 100%;
        }
      }

      // 用户消息（end布局）：宽度100%
      &[class*="end"] {
        width: 100%;
        max-width: 100%;

        // 正常模式下：去掉 flex:auto
        .el-bubble-content-wrapper {
          flex: none;
        }

        // 编辑模式下：加回 flex:auto
        &:has(.edit-message-wrapper-full) .el-bubble-content-wrapper {
          flex: auto;
        }

        .el-bubble-content {
          width: 100%;
          max-width: 100%;
        }
      }

      // 隐藏头像
      .el-avatar {
        display: none !important;
      }
    }
    .el-typewriter {
      overflow: hidden;
      border-radius: 12px;
    }
    .user-content-wrapper {
      display: flex;
      flex-direction: column;
      gap: 8px;
      width: 100%;

      // 编辑模式下：宽度100%，无气泡样式
      &:has(.edit-message-wrapper-full) {
        width: 100%;
        max-width: 100%;
      }
    }
    .user-images {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;
      margin-bottom: 4px;
    }
    .user-image {
      max-width: 200px;
      max-height: 200px;
      border-radius: 8px;
      object-fit: cover;
      cursor: pointer;
      transition: transform 0.2s;
      &:hover {
        transform: scale(1.05);
      }
    }
    .user-files {
      display: flex;
      flex-direction: column;
      gap: 6px;
      margin-bottom: 4px;
    }
    .user-file-item {
      display: flex;
      align-items: center;
      gap: 8px;
      padding: 8px 12px;
      background: rgba(0, 0, 0, 0.05);
      border-radius: 6px;
      font-size: 13px;
      .file-icon {
        font-size: 16px;
        color: #409eff;
      }
      .file-name {
        flex: 1;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
      .file-size {
        color: #909399;
        font-size: 12px;
      }
    }
    .user-content {
      white-space: pre-wrap;
      line-height: 1.6;
      color: #333;
    }
    .markdown-body {
      background-color: transparent;
    }
    .markdown-elxLanguage-header-div {
      top: -25px !important;
    }

    // xmarkdown 样式
    .elx-xmarkdown-container {
      padding: 8px 4px;
    }
  }
  .chat-defaul-sender {
    width: 100%;
    margin-bottom: 22px;
  }
}

.footer-wrapper {
  display: flex;
  align-items: center;
  margin-top: 8px;
  padding: 0 2px;
}

.footer-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: 12px;

  .footer-info {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 12px;
    color: #8c8c8c;

    .footer-time {
      display: flex;
      align-items: center;
      gap: 4px;

      .el-icon {
        font-size: 12px;
        color: #bfbfbf;
      }
    }

    .footer-token {
      display: flex;
      align-items: center;
      gap: 4px;
      color: #8c8c8c;

      &::before {
        content: '';
        width: 4px;
        height: 4px;
        background: #bfbfbf;
        border-radius: 50%;
      }
    }
  }

  .footer-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    opacity: 0.4;
    transition: opacity 0.2s ease;

    .footer-wrapper:hover & {
      opacity: 1;
    }

    .el-button {
      width: 26px;
      height: 26px;
      padding: 0;
      font-size: 13px;
      color: #8c8c8c;
      border: none;
      background: transparent;
      border-radius: 6px;
      transition: all 0.2s ease;

      &:hover {
        color: #409eff;
        background: #f0f7ff;
      }

      &:active {
        background: #e6f2ff;
      }

      &[disabled] {
        color: #d9d9d9;
        background: transparent;
      }

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

// 删除模式：整行点击区域（覆盖整个内容区）
// 删除模式：用户内容右对齐，宽度铺满（和AI消息一样）
.delete-mode-user-content {
  display: flex;
  justify-content: flex-end;
  width: 100%;

  .user-content-wrapper {
    width: 100% !important;
    max-width: 100% !important;
  }
}

// 删除模式：AI 内容宽度100%，点击不穿透
.delete-mode-ai-content {
  width: 100%;
}

.loading-container {
  font-size: 14px;
  color: #333;
  padding: 12px;
  background: linear-gradient(to right, #fdfcfb 0%, #ffd1ab 100%);
  border-radius: 15px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.loading-container span {
  display: inline-block;
  margin-left: 8px;
}

// 删除模式工具栏
.delete-mode-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  background: linear-gradient(135deg, #fff7ed 0%, #ffedd5 100%);
  border: 1px solid #fed7aa;
  border-radius: 6px;
  margin-bottom: 12px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);

  .selected-count {
    font-size: 13px;
    color: #ea580c;
    font-weight: 500;
    display: flex;
    align-items: center;
    gap: 6px;

    &::before {
      content: '';
      width: 6px;
      height: 6px;
      background: #ea580c;
      border-radius: 50%;
      display: inline-block;
    }
  }

  .toolbar-actions {
    display: flex;
    gap: 6px;

    .el-button {
      font-size: 12px;
      padding: 6px 12px;
      border-radius: 4px;
      transition: all 0.2s ease;

      &--danger {
        background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
        border: none;
        color: #fff;

        &:hover {
          background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);
          transform: translateY(-1px);
          box-shadow: 0 2px 4px rgba(220, 38, 38, 0.2);
        }
      }

      &:not(.el-button--danger) {
        &:hover {
          background: #fff;
          border-color: #fed7aa;
        }
      }
    }
  }
}

// 正常模式内容
.normal-mode-content {
  width: 100%;

  // AI 消息包装器：宽度100%，无气泡形状
  .ai-content-wrapper {
    width: 100%;
    max-width: 100%;
    padding: 0;

    .markdown-body {
      width: 100%;
      max-width: 100%;
    }
  }
}

// 编辑消息样式 - 全宽
.edit-message-wrapper-full {
  display: flex;
  flex-direction: column;
  gap: 12px;
  width: 100%;
  max-width: 100%;

  :deep(.el-textarea__inner) {
    min-height: 80px !important;
    font-size: 14px;
    line-height: 1.6;
  }

  .edit-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
  }
}

/* 移动端响应式优化 */
@media (max-width: 768px) {
  .chat-with-id-container {
    padding: 0 12px;

    .chat-header {
      height: 50px;

      .left-box {
        padding-left: 8px;
        gap: 8px;
      }

      .middle-box {
        margin-left: 8px;
      }
    }

    .chat-warp {
      height: calc(100vh - 110px);

      .thinking-chain-warp {
        margin-bottom: 8px;
      }
    }

    /* 气泡列表优化 */
    :deep(.el-bubble-list) {
      padding-top: 16px;
    }

    :deep(.el-bubble) {
      padding: 0 8px;
      padding-bottom: 16px;
    }

    /* 用户图片优化 */
    :deep(.user-image) {
      max-width: 150px;
      max-height: 150px;
    }

    /* 文件项优化 */
    :deep(.user-file-item) {
      padding: 6px 10px;
      font-size: 12px;

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

    /* Sender 输入框优化 */
    .chat-defaul-sender {
      margin-bottom: 16px;
    }

    /* Footer 优化 */
    .footer-wrapper {
      flex-wrap: wrap;
      gap: 6px;
    }

    .footer-time {
      font-size: 11px;

      .footer-token {
        padding: 0 3px;
        font-size: 11px;
      }
    }
  }
}

/* 超小屏幕优化 */
@media (max-width: 480px) {
  .chat-with-id-container {
    padding: 0 8px;

    .chat-header {
      height: 48px;

      .left-box {
        padding-left: 4px;
        gap: 6px;
      }

      .middle-box {
        margin-left: 6px;
      }
    }

    .chat-warp {
      height: calc(100vh - 100px);
    }

    :deep(.el-bubble-list) {
      padding-top: 12px;
    }

    :deep(.el-bubble) {
      padding: 0 6px;
      padding-bottom: 12px;
    }

    :deep(.user-image) {
      max-width: 120px;
      max-height: 120px;
    }

    .chat-defaul-sender {
      margin-bottom: 12px;
    }

    .footer-time {
      font-size: 10px;

      .footer-token {
        font-size: 10px;
      }
    }
  }
}
</style>
