// @ts-nocheck
import { debugLog } from './common';
import { useModelStore } from '../../stores/model';

export const messageMethods = {
  buildRuntimeQueueSnapshotKey(messages = []) {
    const list = Array.isArray(messages) ? messages : [];
    return JSON.stringify(
      list.map((item) => [
        String(item?.id || ''),
        String(item?.text || ''),
        Number(item?.createdAt || 0)
      ])
    );
  },

  setRuntimeQueueSyncLock(messages = [], ttlMs = 1800) {
    this.runtimeQueueSyncLockKey = this.buildRuntimeQueueSnapshotKey(messages);
    this.runtimeQueueSyncLockUntil = Date.now() + Math.max(300, Number(ttlMs || 0));
  },

  ensureRuntimeQueueSuppressionState() {
    if (!(this.runtimeQueueSuppressedMessageIds instanceof Set)) {
      this.runtimeQueueSuppressedMessageIds = new Set();
    }
    if (
      !this.runtimeGuidanceSuppressedTextCounts ||
      typeof this.runtimeGuidanceSuppressedTextCounts !== 'object' ||
      Array.isArray(this.runtimeGuidanceSuppressedTextCounts)
    ) {
      this.runtimeGuidanceSuppressedTextCounts = {};
    }
  },

  markRuntimeQueueSuppressedByManualStop() {
    this.ensureRuntimeQueueSuppressionState();
    const queueList = Array.isArray(this.runtimeQueuedMessages) ? this.runtimeQueuedMessages : [];
    queueList.forEach((item) => {
      const id = String(item?.id || '').trim();
      if (id) {
        this.runtimeQueueSuppressedMessageIds.add(id);
      }
    });

    const fallbackList = Array.isArray(this.runtimeGuidanceFallbackQueue)
      ? this.runtimeGuidanceFallbackQueue
      : [];
    fallbackList.forEach((item) => {
      const text = String(item || '').trim();
      if (!text) return;
      const counts = this.runtimeGuidanceSuppressedTextCounts;
      counts[text] = Number(counts[text] || 0) + 1;
    });
  },

  consumeSuppressedRuntimeGuidanceText(rawText) {
    this.ensureRuntimeQueueSuppressionState();
    const text = String(rawText || '').trim();
    if (!text) return false;
    const counts = this.runtimeGuidanceSuppressedTextCounts;
    const current = Number(counts[text] || 0);
    return Number.isFinite(current) && current > 0;
  },

  consumeSuppressedRuntimeQueueMessageId(rawId) {
    this.ensureRuntimeQueueSuppressionState();
    const id = String(rawId || '').trim();
    if (!id) return false;
    return this.runtimeQueueSuppressedMessageIds.has(id);
  },

  clearRuntimeQueueSuppressionState() {
    this.runtimeQueueSuppressedMessageIds = new Set();
    this.runtimeGuidanceSuppressedTextCounts = {};
  },

  pruneSuppressedRuntimeQueues() {
    this.ensureRuntimeQueueSuppressionState();
    const blockedIds = this.runtimeQueueSuppressedMessageIds;
    const currentQueue = Array.isArray(this.runtimeQueuedMessages)
      ? this.runtimeQueuedMessages
      : [];
    const nextQueue = currentQueue.filter((item) => {
      const id = String(item?.id || '').trim();
      if (!id) return false;
      return !blockedIds.has(id);
    });
    if (nextQueue.length !== currentQueue.length) {
      this.runtimeQueuedMessages = nextQueue;
      this.setRuntimeQueueSyncLock(nextQueue, 2200);
    }

    const currentFallback = Array.isArray(this.runtimeGuidanceFallbackQueue)
      ? this.runtimeGuidanceFallbackQueue
      : [];
    if (currentFallback.length > 0) {
      const keptFallback = [];
      currentFallback.forEach((item) => {
        const text = String(item || '').trim();
        if (!text) {
          return;
        }
        if (this.consumeSuppressedRuntimeGuidanceText(text)) {
          return;
        }
        keptFallback.push(text);
      });
      if (keptFallback.length !== currentFallback.length) {
        this.runtimeGuidanceFallbackQueue = keptFallback;
      }
    }
  },

  async executeSystemCommand(rawCommand, options = {}) {
    const command = (rawCommand || '').toString().trim();
    if (!command) {
      return { success: false, message: '命令不能为空' };
    }

    if (!this.isConnected) {
      if (options.showToast !== false) {
        this.uiPushToast({
          title: '连接不可用',
          message: '当前无法执行命令，请稍后重试。',
          type: 'error'
        });
      }
      return { success: false, message: '连接不可用' };
    }

    try {
      const response = await fetch('/api/commands', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ command })
      });

      const payload = await response.json().catch(() => ({}));
      const result = {
        command: payload.command || command.replace(/^\//, ''),
        success: !!payload.success,
        message: payload.message,
        data: payload.data
      };
      this.handleSystemCommandResult(result, options);
      return result;
    } catch (error) {
      const message = error instanceof Error ? error.message : '命令执行失败';
      const result = {
        command: command.replace(/^\//, ''),
        success: false,
        message
      };
      this.handleSystemCommandResult(result, options);
      return result;
    }
  },

  handleSystemCommandResult(data, options = {}) {
    const showToast = options.showToast !== false;
    if (data.command === 'clear' && data.success) {
      this.logMessageState?.('command_result-clear', { data });
      this.messages = [];
      this.logMessageState?.('command_result-cleared', { data });
      this.currentMessageIndex = -1;
      this.chatClearExpandedBlocks();
      this.resetTokenStatistics();
      if (showToast) {
        this.uiPushToast({
          title: '已清除',
          message: data.message || '对话已清除',
          type: 'success'
        });
      }
      return;
    }

    if (data.command === 'status' && data.success) {
      this.addSystemMessage(`系统状态:\n${JSON.stringify(data.data || {}, null, 2)}`);
      if (showToast) {
        this.uiPushToast({
          title: '状态已更新',
          message: '已获取系统状态',
          type: 'success'
        });
      }
      return;
    }

    if (!data.success) {
      this.addSystemMessage(`命令失败: ${data.message || '未知错误'}`);
      if (showToast) {
        this.uiPushToast({
          title: '命令执行失败',
          message: data.message || '请稍后重试',
          type: 'error'
        });
      }
      return;
    }

    if (showToast) {
      this.uiPushToast({
        title: '命令已执行',
        message: data.command || '完成',
        type: 'success'
      });
    }
  },

  applyRuntimeQueuedMessages(messages = []) {
    this.ensureRuntimeQueueSuppressionState();
    const previousList = Array.isArray(this.runtimeQueuedMessages)
      ? this.runtimeQueuedMessages
      : [];
    const previousById = new Map(previousList.map((item) => [item?.id, item]));
    const previousIndexById = new Map(previousList.map((item, index) => [item?.id, index]));
    const limit = Math.max(1, Number(this.runtimeQueueLimit || 5));
    const normalizedRaw = (Array.isArray(messages) ? messages : [])
      .map((item) => {
        if (!item) return null;
        const id = String(item.id || '').trim();
        const text = String(item.text || '').trim();
        if (!id || !text) return null;
        const previous = previousById.get(id);
        const rawCreatedAt = Number(item.created_at ?? item.createdAt ?? Date.now());
        return {
          id,
          text,
          createdAt: Number.isFinite(rawCreatedAt) ? rawCreatedAt : Date.now(),
          source: previous?.source || 'user'
        };
      })
      .filter((item) => !!item);

    const dedupById = new Map();
    normalizedRaw.forEach((item) => {
      if (!item?.id || dedupById.has(item.id)) {
        return;
      }
      dedupById.set(item.id, item);
    });

    const normalized = Array.from(dedupById.values())
      .sort((a, b) => {
        const at = Number(a?.createdAt || 0);
        const bt = Number(b?.createdAt || 0);
        if (at !== bt) {
          return at - bt;
        }
        const ai = previousIndexById.has(a?.id)
          ? Number(previousIndexById.get(a?.id))
          : Number.MAX_SAFE_INTEGER;
        const bi = previousIndexById.has(b?.id)
          ? Number(previousIndexById.get(b?.id))
          : Number.MAX_SAFE_INTEGER;
        if (ai !== bi) {
          return ai - bi;
        }
        return String(a?.id || '').localeCompare(String(b?.id || ''));
      })
      .slice(0, limit);

    const unchanged =
      previousList.length === normalized.length &&
      previousList.every((item, index) => {
        const next = normalized[index];
        return (
          item?.id === next?.id &&
          item?.text === next?.text &&
          Number(item?.createdAt || 0) === Number(next?.createdAt || 0)
        );
      });

    if (unchanged) {
      return previousList;
    }
    this.runtimeQueuedMessages = normalized;
    return normalized;
  },

  async enqueueRuntimeQueuedMessage(rawMessage) {
    const text = (rawMessage || '').toString().trim();
    if (!text) {
      return false;
    }
    try {
      const { useTaskStore } = await import('../../stores/task');
      const taskStore = useTaskStore();
      const taskId = taskStore.currentTaskId;
      if (!taskId) {
        this.uiPushToast({
          title: '暂不可堆积',
          message: '未检测到活跃任务，请稍后再试',
          type: 'warning'
        });
        return false;
      }
      const response = await fetch(`/api/tasks/${encodeURIComponent(taskId)}/runtime_queue`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          message: text
        })
      });
      const payload = await response.json().catch(() => ({}));
      if (!response.ok || !payload?.success) {
        throw new Error(payload?.error || '堆积消息失败');
      }
      const nextQueue = this.applyRuntimeQueuedMessages(payload?.data?.messages || []) || [];
      this.setRuntimeQueueSyncLock(nextQueue, 2200);
      return true;
    } catch (error) {
      this.uiPushToast({
        title: '堆积失败',
        message: error?.message || '请稍后重试',
        type: 'error'
      });
      return false;
    }
  },

  async handleDeleteRuntimeMessage(messageId) {
    const targetId = String(messageId || '').trim();
    if (!targetId) {
      return;
    }
    try {
      const { useTaskStore } = await import('../../stores/task');
      const taskStore = useTaskStore();
      const taskId = taskStore.currentTaskId;
      if (!taskId) {
        const nextQueue = (this.runtimeQueuedMessages || []).filter(
          (item) => item?.id !== targetId
        );
        this.runtimeQueuedMessages = nextQueue;
        this.setRuntimeQueueSyncLock(nextQueue, 1200);
        return;
      }
      const response = await fetch(
        `/api/tasks/${encodeURIComponent(taskId)}/runtime_queue/${encodeURIComponent(targetId)}`,
        {
          method: 'DELETE'
        }
      );
      const payload = await response.json().catch(() => ({}));
      if (!response.ok || !payload?.success) {
        throw new Error(payload?.error || '删除失败');
      }
      const nextQueue = this.applyRuntimeQueuedMessages(payload?.data?.messages || []) || [];
      this.setRuntimeQueueSyncLock(nextQueue, 2200);
    } catch (error) {
      this.uiPushToast({
        title: '删除失败',
        message: error?.message || '请稍后重试',
        type: 'error'
      });
    }
  },

  async handleGuideRuntimeMessage(messageId) {
    const item = (this.runtimeQueuedMessages || []).find((entry) => entry?.id === messageId);
    if (!item?.text) {
      return;
    }
    if (!this.composerBusy) {
      const sent = !!(await this.sendMessage({
        presetText: String(item.text || '').trim(),
        source: 'runtime_queue_manual_guide'
      }));
      if (!sent) {
        this.uiPushToast({
          title: '发送失败',
          message: '引导消息未发出，请稍后重试',
          type: 'warning'
        });
        return;
      }
      const currentQueue = Array.isArray(this.runtimeQueuedMessages)
        ? [...this.runtimeQueuedMessages]
        : [];
      const nextQueue = currentQueue.filter((entry) => entry?.id !== item.id);
      if (nextQueue.length !== currentQueue.length) {
        this.runtimeQueuedMessages = nextQueue;
        this.setRuntimeQueueSyncLock(nextQueue, 2200);
      }
      this.ensureRuntimeQueueSuppressionState();
      if (item?.id) {
        this.runtimeQueueSuppressedMessageIds.delete(item.id);
      }
      return;
    }
    try {
      const { useTaskStore } = await import('../../stores/task');
      const taskStore = useTaskStore();
      const taskId = taskStore.currentTaskId;
      if (!taskId) {
        this.uiPushToast({
          title: '暂不可引导',
          message: '未检测到活跃任务，请稍后再试',
          type: 'warning'
        });
        return;
      }
      const response = await fetch(
        `/api/tasks/${encodeURIComponent(taskId)}/runtime_queue/${encodeURIComponent(messageId)}/guide`,
        {
          method: 'POST'
        }
      );
      const payload = await response.json().catch(() => ({}));
      if (!response.ok || !payload?.success) {
        throw new Error(payload?.error || '提交引导失败');
      }
      const nextQueue = this.applyRuntimeQueuedMessages(payload?.data?.messages || []) || [];
      this.setRuntimeQueueSyncLock(nextQueue, 2200);
      this.uiPushToast({
        title: '已设为引导对话',
        message: '将在下一次工具结果后插入到当前对话',
        type: 'success',
        duration: 1800
      });
    } catch (error) {
      this.uiPushToast({
        title: '引导失败',
        message: error?.message || '请稍后重试',
        type: 'error'
      });
    }
  },

  async tryAutoSendRuntimeQueuedMessages(reason = 'unspecified') {
    if (this.runtimeQueueAutoSendInProgress) {
      return false;
    }
    if (
      this.composerBusy ||
      this.streamingMessage ||
      this.taskInProgress ||
      this.stopRequested ||
      this.waitingForSubAgent
    ) {
      return false;
    }

    const fallbackQueue = Array.isArray(this.runtimeGuidanceFallbackQueue)
      ? this.runtimeGuidanceFallbackQueue
      : [];
    const runtimeQueue = Array.isArray(this.runtimeQueuedMessages)
      ? this.runtimeQueuedMessages
      : [];
    let nextText = '';
    let source = 'runtime_queue';
    let runtimeQueueMessageId = null;
    let fallbackIndex = -1;

    if (fallbackQueue.length > 0) {
      for (let i = 0; i < fallbackQueue.length; i += 1) {
        const candidate = (fallbackQueue[i] || '').toString().trim();
        if (!candidate) {
          continue;
        }
        if (this.consumeSuppressedRuntimeGuidanceText(candidate)) {
          continue;
        }
        nextText = candidate;
        source = 'runtime_guidance_fallback';
        fallbackIndex = i;
        break;
      }
    }

    if (!nextText && runtimeQueue.length > 0) {
      for (let i = 0; i < runtimeQueue.length; i += 1) {
        const next = runtimeQueue[i];
        const candidateId = String(next?.id || '').trim();
        const candidateText = (next?.text || '').toString().trim();
        if (!candidateId || !candidateText) {
          continue;
        }
        if (this.consumeSuppressedRuntimeQueueMessageId(candidateId)) {
          continue;
        }
        nextText = candidateText;
        source = next?.source || 'runtime_queue';
        runtimeQueueMessageId = candidateId;
        break;
      }
    }

    if (!nextText) {
      return false;
    }

    this.runtimeQueueAutoSendInProgress = true;
    let sent = false;
    try {
      sent = !!(await this.sendMessage({
        presetText: nextText,
        source
      }));
    } catch {
      sent = false;
    } finally {
      this.runtimeQueueAutoSendInProgress = false;
    }

    if (!sent) {
      return false;
    }

    if (source === 'runtime_guidance_fallback') {
      const current = Array.isArray(this.runtimeGuidanceFallbackQueue)
        ? [...this.runtimeGuidanceFallbackQueue]
        : [];
      const removeIndex =
        fallbackIndex >= 0
          ? fallbackIndex
          : current.findIndex((item) => String(item || '').trim() === nextText);
      if (removeIndex >= 0) {
        current.splice(removeIndex, 1);
        this.runtimeGuidanceFallbackQueue = current;
      }
    } else {
      const current = Array.isArray(this.runtimeQueuedMessages)
        ? [...this.runtimeQueuedMessages]
        : [];
      if (runtimeQueueMessageId) {
        const nextQueue = current.filter((item) => item?.id !== runtimeQueueMessageId);
        this.runtimeQueuedMessages = nextQueue;
        this.setRuntimeQueueSyncLock(nextQueue, 1500);
      } else {
        const removeIndex = current.findIndex(
          (item) => String(item?.text || '').trim() === nextText
        );
        if (removeIndex >= 0) {
          current.splice(removeIndex, 1);
          this.runtimeQueuedMessages = current;
          this.setRuntimeQueueSyncLock(current, 1500);
        }
      }
    }
    debugLog('[RuntimeQueue] auto-send success', {
      reason,
      source,
      messagePreview: nextText.slice(0, 60)
    });
    return true;
  },

  async handleSendOrStop() {
    if (this.compressionInProgress) {
      this.uiPushToast({
        title: '对话自动压缩中',
        message: '当前不可发送/停止，请等待压缩完成',
        type: 'warning'
      });
      return;
    }
    const hasText = !!((this.inputMessage || '').trim().length > 0);
    const hasMedia =
      (Array.isArray(this.selectedImages) && this.selectedImages.length > 0) ||
      (Array.isArray(this.selectedVideos) && this.selectedVideos.length > 0);
    if (this.composerBusy) {
      if (hasText) {
        const queued = await this.enqueueRuntimeQueuedMessage(this.inputMessage);
        if (queued) {
          this.inputClearMessage();
          this.inputSetLineCount(1);
          this.inputSetMultiline(false);
          this.autoResizeInput();
        }
        return;
      }
      if (hasMedia) {
        this.uiPushToast({
          title: '运行中仅支持文本',
          message: '图片/视频请等待当前任务结束后发送',
          type: 'warning'
        });
        return;
      }
      this.stopTask();
    } else {
      this.sendMessage();
    }
  },

  async sendMessage(options = {}) {
    console.log('[DEBUG_AWAITING] ===== sendMessage =====');
    const presetText = typeof options?.presetText === 'string' ? options.presetText : null;
    const usePresetText = presetText !== null;

    if (this.compressionInProgress) {
      this.uiPushToast({
        title: '对话自动压缩中',
        message: '压缩完成后才能继续发送消息',
        type: 'warning'
      });
      return false;
    }
    if (this.streamingUi && !usePresetText) {
      return false;
    }
    if (!this.isConnected) {
      this.uiPushToast({
        title: '连接已断开',
        message: '当前无法发送消息，请等待连接恢复后重试',
        type: 'warning'
      });
      return false;
    }
    if (this.mediaUploading && !usePresetText) {
      this.uiPushToast({
        title: '上传中',
        message: '请等待图片/视频上传完成后再发送',
        type: 'info'
      });
      return false;
    }

    const text = ((usePresetText ? presetText : this.inputMessage) || '').trim();
    const images = usePresetText
      ? []
      : Array.isArray(this.selectedImages)
        ? this.selectedImages.slice(0, 9)
        : [];
    const videos = usePresetText
      ? []
      : Array.isArray(this.selectedVideos)
        ? this.selectedVideos.slice(0, 1)
        : [];
    const hasText = text.length > 0;
    const hasImages = images.length > 0;
    const hasVideos = videos.length > 0;

    if (!hasText && !hasImages && !hasVideos) {
      return false;
    }

    const quotaType = this.thinkingMode ? 'thinking' : 'fast';
    if (this.isQuotaExceeded(quotaType)) {
      this.showQuotaToast({ type: quotaType });
      return false;
    }

    const modelStore = useModelStore();
    const currentModel = modelStore.models.find((m) => m.key === this.currentModelKey);
    if (hasImages && !currentModel?.supportsImage) {
      this.uiPushToast({
        title: '当前模型不支持图片',
        message: '请切换到支持图片输入的模型再发送图片',
        type: 'error'
      });
      return false;
    }

    if (hasVideos && !currentModel?.supportsVideo) {
      this.uiPushToast({
        title: '当前模型不支持视频',
        message: '请切换到支持视频输入的模型后再发送视频',
        type: 'error'
      });
      return false;
    }

    if (hasVideos && hasImages) {
      this.uiPushToast({
        title: '请勿同时发送',
        message: '视频与图片需分开发送，每条仅包含一种媒体',
        type: 'warning'
      });
      return false;
    }

    if (hasVideos) {
      this.uiPushToast({
        title: '视频处理中',
        message: '读取视频需要较长时间，请耐心等待',
        type: 'info',
        duration: 5000
      });
    }

    const message = text;

    const wasBlank = this.isConversationBlank();
    if (wasBlank) {
      this.blankHeroExiting = true;
      this.blankHeroActive = true;
      setTimeout(() => {
        this.blankHeroExiting = false;
        this.blankHeroActive = false;
      }, 320);
    }

    let targetConversationId = this.currentConversationId;
    if (!targetConversationId) {
      try {
        const createResp = await fetch('/api/conversations', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            thinking_mode: this.thinkingMode,
            mode: this.runMode
          })
        });
        const createResult = await createResp.json().catch(() => ({}));
        if (!createResp.ok || !createResult?.success || !createResult?.conversation_id) {
          throw new Error(createResult?.message || createResult?.error || '创建对话失败');
        }
        targetConversationId = createResult.conversation_id;
        this.skipConversationHistoryReload = true;
        this.currentConversationId = targetConversationId;
        this.currentConversationTitle = '新对话';
        this.conversations = [
          {
            id: targetConversationId,
            title: '新对话',
            updated_at: new Date().toISOString(),
            total_messages: 0,
            total_tools: 0
          },
          ...this.conversations.filter((conv) => conv && conv.id !== targetConversationId)
        ];
        const pathFragment = this.stripConversationPrefix(targetConversationId);
        history.replaceState({ conversationId: targetConversationId }, '', `/${pathFragment}`);
        await this.applyPendingVersioningToConversation(targetConversationId);
      } catch (error) {
        this.uiPushToast({
          title: '发送失败',
          message: error?.message || '创建新对话失败，请重试',
          type: 'error'
        });
        return false;
      }
    }

    // 标记任务进行中，直到任务完成或用户手动停止
    this.taskInProgress = true;
    const localMessageSource = usePresetText ? (options?.source === 'runtime_queue' ? 'presend' : 'guidance') : 'user';
    this.chatAddUserMessage(message, images, videos, [], localMessageSource);
    // 关键体验修复：用户发送后立刻显示 assistant 头部 + 工作中计时 + 等待提示，
    // 不等待 createTask / 轮询首事件返回。
    this.chatStartAssistantMessage();
    this.stopRequested = false;
    if (typeof this.monitorShowPendingReply === 'function') {
      this.monitorShowPendingReply();
    }
    if (this.autoScrollEnabled) {
      this.scrollToBottom();
    }

    // 使用 REST API 创建任务（轮询模式）
    try {
      const { useTaskStore } = await import('../../stores/task');
      const taskStore = useTaskStore();
      if (typeof this.clearProcessedEvents === 'function') {
        this.clearProcessedEvents();
      }

      await taskStore.createTask(message, images, videos, targetConversationId, {
        model_key: this.currentModelKey,
        run_mode: this.runMode,
        thinking_mode: this.thinkingMode,
        message_source: localMessageSource,
        eventHandler: (event: any) => this.handleTaskEvent(event)
      });

      debugLog('[Message] 任务已创建，开始轮询');
    } catch (error) {
      console.error('[Message] 创建任务失败:', error);
      this.uiPushToast({
        title: '发送失败',
        message: error.message || '创建任务失败，请重试',
        type: 'error'
      });
      this.streamingMessage = false;
      this.taskInProgress = false;
      if (typeof this.cleanupTrailingEmptyAssistantPlaceholder === 'function') {
        this.cleanupTrailingEmptyAssistantPlaceholder('create_task_failed');
      }
      if (typeof this.forceUnlockMonitor === 'function') {
        this.forceUnlockMonitor('create_task_failed');
      }
      return false;
    }

    if (!usePresetText) {
      this.inputClearMessage();
      this.inputClearSelectedImages();
      this.inputClearSelectedVideos();
      this.inputSetImagePickerOpen(false);
      this.inputSetVideoPickerOpen(false);
      this.inputSetLineCount(1);
      this.inputSetMultiline(false);
      this.persistComposerDraftNow({
        reason: 'send-message-cleared',
        force: true,
        keepalive: true
      }).catch(() => {});
    }
    if (hasImages) {
      this.conversationHasImages = true;
      this.conversationHasVideos = false;
    }
    if (hasVideos) {
      this.conversationHasVideos = true;
      this.conversationHasImages = false;
    }
    if (this.autoScrollEnabled) {
      this.scrollToBottom();
    }
    this.autoResizeInput();

    // 发送消息后延迟更新当前上下文Token（关键修复：恢复原逻辑）
    setTimeout(() => {
      if (this.currentConversationId) {
        this.updateCurrentContextTokens();
      }
    }, 1000);
    return true;
  },

  // 新增：停止任务方法
  async stopTask() {
    console.log('[DEBUG_AWAITING] ===== stopTask =====');
    if (this.compressionInProgress) {
      this.uiPushToast({
        title: '对话自动压缩中',
        message: '压缩进行中，当前不可停止任务',
        type: 'warning'
      });
      return;
    }

    const canStop = this.composerBusy && !this.stopRequested;
    if (!canStop) {
      return;
    }

    const shouldDropToolEvents = this.streamingUi;
    if (typeof this.markRuntimeQueueSuppressedByManualStop === 'function') {
      this.markRuntimeQueueSuppressedByManualStop();
    }
    this.stopRequested = true;
    this.dropToolEvents = shouldDropToolEvents;

    try {
      const { useTaskStore } = await import('../../stores/task');
      const taskStore = useTaskStore();

      if (taskStore.currentTaskId) {
        await taskStore.cancelTask();
      }

      // 等待后端确认
      await new Promise((resolve) => setTimeout(resolve, 300));
      const shouldKeepBusy =
        Boolean(taskStore.currentTaskId) &&
        ['running', 'pending', 'cancel_requested'].includes(String(taskStore.taskStatus));

      // 清理前端状态
      this.clearPendingTools('user_stop');
      this.streamingMessage = false;
      // 若后台已回传停止事件，不要再次把输入区锁回“停止中”
      this.taskInProgress = shouldKeepBusy;
      this.forceUnlockMonitor('user_stop');
      if (typeof this.clearProcessedEvents === 'function') {
        this.clearProcessedEvents();
      }

      // 清理assistant消息的等待动画状态
      const lastMessage = this.messages[this.messages.length - 1];
      const before = {
        hasLastMessage: !!lastMessage,
        role: lastMessage?.role,
        awaitingFirstContent: lastMessage?.awaitingFirstContent,
        generatingLabel: lastMessage?.generatingLabel
      };

      if (lastMessage && lastMessage.role === 'assistant') {
        lastMessage.awaitingFirstContent = false;
        lastMessage.generatingLabel = '';
      }

      console.log('[DEBUG_AWAITING] stopTask 清理完成', {
        before,
        after: {
          awaitingFirstContent: lastMessage?.awaitingFirstContent,
          generatingLabel: lastMessage?.generatingLabel
        }
      });
    } catch (error) {
      console.error('[Message] 取消任务失败:', error);
      const { useTaskStore } = await import('../../stores/task');
      const taskStore = useTaskStore();
      const shouldKeepBusy =
        Boolean(taskStore.currentTaskId) &&
        ['running', 'pending', 'cancel_requested'].includes(String(taskStore.taskStatus));

      // 即使失败也清理状态
      this.clearPendingTools('user_stop');
      this.streamingMessage = false;
      // 如果任务其实已结束，允许按钮恢复发送态
      this.taskInProgress = shouldKeepBusy;
      this.forceUnlockMonitor('user_stop');
      if (typeof this.clearProcessedEvents === 'function') {
        this.clearProcessedEvents();
      }

      // 清理assistant消息的等待动画状态
      const lastMessage = this.messages[this.messages.length - 1];
      if (lastMessage && lastMessage.role === 'assistant') {
        lastMessage.awaitingFirstContent = false;
        lastMessage.generatingLabel = '';
      }

      this.uiPushToast({
        title: '停止失败',
        message: '任务可能仍在运行，请刷新页面',
        type: 'warning'
      });
    } finally {
      // 确保清除 dropToolEvents 和 stopRequested 标志
      this.dropToolEvents = false;
      this.stopRequested = false;
    }
  },

  async clearChat() {
    const confirmed = await this.confirmAction({
      title: '清除对话',
      message: '确定要清除所有对话记录吗？该操作不可撤销。',
      confirmText: '清除',
      cancelText: '取消'
    });
    if (confirmed) {
      await this.executeSystemCommand('/clear', { showToast: false });
    }
  },

  async compressConversation() {
    if (!this.currentConversationId) {
      this.uiPushToast({
        title: '无法压缩',
        message: '当前没有可压缩的对话。',
        type: 'info'
      });
      return;
    }

    if (this.compressing) {
      return;
    }

    const confirmed = await this.confirmAction({
      title: '压缩对话',
      message: '确定要压缩当前对话记录吗？压缩后会生成新的对话副本。',
      confirmText: '压缩',
      cancelText: '取消'
    });
    if (!confirmed) {
      return;
    }

    this.compressing = true;
    this.compressionInProgress = true;
    this.compressionMode = 'manual';
    this.compressionStage = 'requesting';
    this.compressionError = '';
    if (this.compressionToastId) {
      this.uiDismissToast(this.compressionToastId);
      this.compressionToastId = null;
    }
    this.compressionToastId = this.uiPushToast({
      title: '压缩中',
      message: '对话正在压缩，请稍候…',
      type: 'info',
      duration: null,
      closable: false
    });

    try {
      const response = await fetch(`/api/conversations/${this.currentConversationId}/compress`, {
        method: 'POST'
      });

      const result = await response.json();

      if (response.ok && result.success) {
        this.compressionStage = 'switching';
        const newId = result.compressed_conversation_id;
        if (newId) {
          await this.loadConversation(newId, { force: true });
        }
        const guideMessage = (result.guide_message || '').trim();
        const autoTaskStarted = !!result.auto_task_started;
        const autoTaskId = result.auto_task_id;
        if (autoTaskStarted && autoTaskId) {
          const { useTaskStore } = await import('../../stores/task');
          const taskStore = useTaskStore();
          if (typeof this.clearProcessedEvents === 'function') {
            this.clearProcessedEvents();
          }
          taskStore.resumeTask(autoTaskId, {
            status: result.auto_task_status || 'running',
            resetOffset: true,
            eventHandler: (event) => this.handleTaskEvent(event)
          });
          this.taskInProgress = true;
          if (typeof this.monitorShowPendingReply === 'function') {
            this.monitorShowPendingReply();
          }
        } else if (guideMessage) {
          await this.sendAutoUserMessage(guideMessage);
        }

        this.conversationsOffset = 0;
        await this.loadConversationsList();

        debugLog('对话压缩完成:', result);
        this.uiPushToast({
          title: '压缩完成',
          message: '已生成压缩后的新对话',
          type: 'success',
          duration: 2200
        });
      } else {
        const message = result.message || result.error || '压缩失败';
        this.compressionError = message;
        this.uiPushToast({
          title: '压缩失败',
          message,
          type: 'error'
        });
      }
    } catch (error) {
      console.error('压缩对话异常:', error);
      this.compressionError = error.message || '请稍后重试';
      this.uiPushToast({
        title: '压缩对话异常',
        message: error.message || '请稍后重试',
        type: 'error'
      });
    } finally {
      if (this.compressionToastId) {
        this.uiDismissToast(this.compressionToastId);
        this.compressionToastId = null;
      }
      this.compressing = false;
      this.compressionInProgress = false;
      this.compressionMode = '';
      this.compressionStage = '';
    }
  },

  async sendAutoUserMessage(text) {
    const message = (text || '').trim();
    if (!message || !this.isConnected) {
      return false;
    }
    const quotaType = this.thinkingMode ? 'thinking' : 'fast';
    if (this.isQuotaExceeded(quotaType)) {
      this.showQuotaToast({ type: quotaType });
      return false;
    }
    this.taskInProgress = true;
    this.chatAddUserMessage(message, [], [], [], 'user');
    this.chatStartAssistantMessage();
    this.stopRequested = false;
    if (typeof this.monitorShowPendingReply === 'function') {
      this.monitorShowPendingReply();
    }
    try {
      const { useTaskStore } = await import('../../stores/task');
      const taskStore = useTaskStore();
      if (typeof this.clearProcessedEvents === 'function') {
        this.clearProcessedEvents();
      }
      await taskStore.createTask(message, [], [], this.currentConversationId, {
        eventHandler: (event: any) => this.handleTaskEvent(event)
      });
    } catch (error) {
      console.error('[Message] 自动消息创建任务失败:', error);
      this.uiPushToast({
        title: '发送失败',
        message: error?.message || '创建任务失败，请重试',
        type: 'error'
      });
      this.streamingMessage = false;
      this.taskInProgress = false;
      if (typeof this.cleanupTrailingEmptyAssistantPlaceholder === 'function') {
        this.cleanupTrailingEmptyAssistantPlaceholder('auto_create_task_failed');
      }
      if (typeof this.forceUnlockMonitor === 'function') {
        this.forceUnlockMonitor('auto_create_task_failed');
      }
      return false;
    }
    if (this.autoScrollEnabled) {
      this.scrollToBottom();
    }
    this.autoResizeInput();
    setTimeout(() => {
      if (this.currentConversationId) {
        this.updateCurrentContextTokens();
      }
    }, 1000);
    return true;
  },

  autoResizeInput() {
    this.$nextTick(() => {
      const textarea = this.getComposerElement('stadiumInput');
      if (!textarea || !(textarea instanceof HTMLTextAreaElement)) {
        return;
      }
      const previousHeight = textarea.offsetHeight;
      textarea.style.height = 'auto';
      const computedStyle = window.getComputedStyle(textarea);
      const lineHeight = parseFloat(computedStyle.lineHeight || '20') || 20;
      const maxHeight = lineHeight * 6;
      const targetHeight = Math.min(textarea.scrollHeight, maxHeight);
      this.inputSetLineCount(Math.max(1, Math.round(targetHeight / lineHeight)));
      this.inputSetMultiline(targetHeight > lineHeight * 1.4);
      if (Math.abs(targetHeight - previousHeight) <= 0.5) {
        textarea.style.height = `${targetHeight}px`;
        return;
      }
      textarea.style.height = `${previousHeight}px`;
      void textarea.offsetHeight;
      requestAnimationFrame(() => {
        textarea.style.height = `${targetHeight}px`;
      });
    });
  }
};
