/**
 * 对话服务
 * 整合 SSE 通信、工具执行、用户交互
 */
import * as vscode from "vscode";
import * as fs from "fs";
import * as path from "path";
import {
  startStreamDialog,
  generateTaskId,
  SSEController,
  SSECallbacks,
} from "./sseHandler";
import {
  executeToolCall,
  createToolExecutorContext,
  ToolExecutorContext,
} from "./toolExecutor";
import { userInteractionManager } from "./userInteraction";
import { getConfig } from "../config/settings";
import type {
  DialogRequest,
  ToolCallRequest,
  AskUserEvent,
  RunMode,
  ServiceTier,
  ToolConfirmEvent,
  PlanConfirmEvent,
} from "../types/api";
import { submitToolConfirm, submitAnswer, stopDialog } from "./apiClient";
import { ChatHistoryManager } from "../utils/chatHistoryManager";
import { getUserIdFromToken, isTokenExpired } from "../utils/jwtUtils";
import { updateCachedBalance } from "./creditsService";

/**
 * 消息段落类型
 */
export interface MessageSegment {
  type: "text" | "tool" | "question" | "agent" | "plan" | "progress";
  content?: string;
  toolName?: string;
  toolStatus?: "running" | "success" | "error";
  toolResult?: string;
  toolDescription?: string;
  askId?: string;
  question?: string;
  options?: string[];
  // 智能体相关字段
  agentId?: string;
  agentName?: string;
  agentStatus?: "running" | "completed" | "error";
  agentSteps?: AgentStep[];
  // 计划相关字段
  planTitle?: string;
  planPhases?: import("../types/api").PlanPhase[];
  planSteps?: string[];
  planSummary?: string;
  // 进度条相关字段（独立于 plan，用于执行模式）
  progressPhases?: import("../types/api").PlanPhase[];
}

/**
 * 智能体执行步骤
 */
export interface AgentStep {
  step: number;
  toolName: string;
  toolInput?: unknown;
  toolResult?: string;
  status: "running" | "completed" | "error";
}

/**
 * 对话回调接口
 */
export interface DialogCallbacks {
  /** 收到文本（可能多次调用，流式） */
  onText?: (text: string, isStreaming: boolean) => void;
  /** 工具开始执行 */
  onToolStart?: (toolName: string) => void;
  /** 工具执行完成 */
  onToolComplete?: (toolName: string, result: string) => void;
  /** 工具执行错误 */
  onToolError?: (toolName: string, error: string) => void;
  /** 工具确认请求（Ask 模式） */
  onToolConfirm?: (
    confirmId: number,
    toolName: string,
    toolInput: Record<string, unknown>
  ) => void;
  /** 计划确认请求（Plan 模式） */
  onPlanConfirm?: (
    confirmId: number,
    title: string,
    phases: import("../types/api").PlanPhase[] | undefined,
    steps: string[] | undefined,
    summary: string
  ) => void;
  /** 显示问题（ask_user） */
  onQuestion?: (askId: string, question: string, options: string[]) => void;
  /** 实时更新段落（流式过程中） */
  onSegmentUpdate?: (segments: MessageSegment[]) => void;
  /** 对话完成，返回所有段落 */
  onComplete?: (segments: MessageSegment[]) => void;
  /** 错误 */
  onError?: (message: string) => void;
  /** 通知消息 */
  onNotification?: (message: string) => void;
  /** 上下文使用量更新 */
  onContextUsage?: (data: {
    currentTokens: number;
    maxTokens: number;
    percentage: number;
  }) => void;
  /** 阶段进度更新 */
  onPhaseProgress?: (phaseId: string, status: string) => void;
}

/**
 * 对话会话
 */
export class DialogSession {
  private taskId: string;
  private sseController: SSEController | null = null;
  private toolContext: ToolExecutorContext;
  private accumulatedText = "";
  private isActive = false;
  private hasCompleted = false; // 标记是否已收到 complete 事件
  private segments: MessageSegment[] = [];
  private currentTextSegment: MessageSegment | null = null;
  private completeCallback: ((segments: MessageSegment[]) => void) | null =
    null; // 保存完成回调，用于 abort 时触发

  constructor(extensionPath: string, existingTaskId?: string) {
    // 支持复用现有 taskId（用于 Plan 模式确认后继续执行）
    this.taskId = existingTaskId || generateTaskId();
    this.toolContext = createToolExecutorContext(extensionPath);
  }

  /**
   * 添加文本到当前文本段落
   */
  private appendText(text: string): void {
    if (!this.currentTextSegment) {
      this.currentTextSegment = { type: "text", content: "" };
      this.segments.push(this.currentTextSegment);
    }
    this.currentTextSegment.content =
      (this.currentTextSegment.content || "") + text;
  }

  /**
   * 结束当前文本段落
   */
  private finalizeTextSegment(): void {
    this.currentTextSegment = null;
  }

  /**
   * 添加工具段落
   */
  private addToolSegment(
    toolName: string,
    status: "running" | "success" | "error",
    result?: string
  ): MessageSegment {
    this.finalizeTextSegment();
    const segment: MessageSegment = {
      type: "tool",
      toolName,
      toolStatus: status,
      toolResult: result,
    };
    this.segments.push(segment);
    return segment;
  }

  /**
   * 更新工具段落状态
   */
  private updateToolSegment(
    toolName: string,
    status: "success" | "error",
    result?: string,
    description?: string
  ): void {
    // 找到最后一个匹配的工具段落
    for (let i = this.segments.length - 1; i >= 0; i--) {
      const seg = this.segments[i];
      if (
        seg.type === "tool" &&
        seg.toolName === toolName &&
        seg.toolStatus === "running"
      ) {
        seg.toolStatus = status;
        seg.toolResult = result;
        if (description !== undefined) {
          seg.toolDescription = description;
        }
        break;
      }
    }
  }

  /**
   * 获取任务ID
   */
  getTaskId(): string {
    return this.taskId;
  }

  /**
   * 是否活跃
   */
  get active(): boolean {
    return this.isActive;
  }

  /**
   * 加载知识图谱数据
   * 从 .iccoder/knowledge.json 读取
   */
  private async loadKnowledgeData(): Promise<string | null> {
    console.log("[DialogSession] loadKnowledgeData 开始执行");

    // 等待 workspaceFolders 就绪（首次打开窗口/首次触发命令时可能为空）
    const workspaceFolders = await this.waitForWorkspaceFolders();
    if (!workspaceFolders || workspaceFolders.length === 0) {
      console.log("[DialogSession] 没有工作区文件夹");
      return null;
    }

    // 多根工作区场景：优先读取实际存在 knowledge.json 的根目录
    for (const folder of this.getWorkspaceFolderCandidates(workspaceFolders)) {
      const knowledgeUri = vscode.Uri.joinPath(
        folder.uri,
        ".iccoder",
        "knowledge.json"
      );
      console.log("[DialogSession] 知识图谱 URI:", knowledgeUri.toString());

      try {
        const content = await this.readTextFileWithRetry(knowledgeUri, 5);
        if (!content) {
          continue;
        }

        // 基础校验 + 清洗：避免偶发读取到半截内容导致后端反序列化失败
        try {
          const parsed = JSON.parse(content) as any;

          // 兼容：后端 KnowledgeGraph.isEmpty() 可能被序列化为 "empty"，老后端反序列化会失败
          if (parsed && typeof parsed === "object" && "empty" in parsed) {
            delete parsed.empty;
          }

          const sanitized = JSON.stringify(parsed);
          console.log(
            "[DialogSession] 知识图谱已清洗, sanitizedLen:",
            sanitized.length
          );
          return sanitized;
        } catch (e) {
          console.warn(
            "[DialogSession] 知识图谱 JSON 解析失败，跳过本次读取:",
            e
          );
          continue;
        }
      } catch (error) {
        console.warn("[DialogSession] 加载知识图谱失败:", error);
      }
    }

    return null;
  }

  private async waitForWorkspaceFolders(): Promise<
    readonly vscode.WorkspaceFolder[] | undefined
  > {
    for (let i = 0; i < 10; i++) {
      const folders = vscode.workspace.workspaceFolders;
      if (folders && folders.length > 0) {
        return folders;
      }
      await new Promise((resolve) => setTimeout(resolve, 100));
    }
    return vscode.workspace.workspaceFolders;
  }

  private getWorkspaceFolderCandidates(
    workspaceFolders: readonly vscode.WorkspaceFolder[]
  ): vscode.WorkspaceFolder[] {
    const result: vscode.WorkspaceFolder[] = [];

    // 1) 当前激活文件所在的 workspace folder（如果有）
    const activeUri = vscode.window.activeTextEditor?.document?.uri;
    const activeFolder = activeUri
      ? vscode.workspace.getWorkspaceFolder(activeUri)
      : undefined;
    if (activeFolder) {
      result.push(activeFolder);
    }

    // 2) 其它 workspace folders（去重）
    for (const folder of workspaceFolders) {
      if (!result.some((f) => f.uri.toString() === folder.uri.toString())) {
        result.push(folder);
      }
    }

    return result;
  }

  private async readTextFileWithRetry(
    uri: vscode.Uri,
    maxAttempts: number
  ): Promise<string | null> {
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        const bytes = await vscode.workspace.fs.readFile(uri);
        const text = Buffer.from(bytes).toString("utf-8");
        if (!text || !text.trim()) {
          return null;
        }
        return text;
      } catch (error) {
        // 文件不存在：不是错误，直接返回 null
        if (
          error instanceof vscode.FileSystemError &&
          error.code === "FileNotFound"
        ) {
          return null;
        }

        const retryable =
          (error instanceof vscode.FileSystemError &&
            error.code === "Unavailable") ||
          (typeof (error as any)?.code === "string" &&
            ["EBUSY", "EPERM", "EACCES"].includes((error as any).code));

        if (!retryable || attempt >= maxAttempts) {
          throw error;
        }

        const delayMs = 50 * attempt;
        console.log(
          `[DialogSession] 读取知识图谱失败（可重试）: attempt=${attempt}/${maxAttempts}, delay=${delayMs}ms`
        );
        await new Promise((resolve) => setTimeout(resolve, delayMs));
      }
    }

    return null;
  }

  /**
   * 获取工具操作描述（用于确认对话框）
   */
  private getToolDescription(
    toolName: string,
    toolInput: Record<string, unknown>
  ): string {
    const lines: string[] = [];

    switch (toolName) {
      case "file_write":
        lines.push(`文件路径: ${toolInput.path || "未知"}`);
        if (toolInput.content) {
          const content = String(toolInput.content);
          lines.push(`内容长度: ${content.length} 字符`);
          lines.push(
            `内容预览: ${content.substring(0, 100)}${
              content.length > 100 ? "..." : ""
            }`
          );
        }
        break;
      case "file_delete":
        lines.push(`删除文件: ${toolInput.path || "未知"}`);
        break;
      case "syntax_check":
        lines.push("执行语法检查");
        if (toolInput.code) {
          const code = String(toolInput.code);
          lines.push(`代码长度: ${code.length} 字符`);
        }
        break;
      case "simulation":
        lines.push(`RTL文件: ${toolInput.rtlPath || "未知"}`);
        lines.push(`TB文件: ${toolInput.tbPath || "未知"}`);
        if (toolInput.duration) {
          lines.push(`仿真时长: ${toolInput.duration}`);
        }
        break;
      default:
        lines.push(`参数: ${JSON.stringify(toolInput, null, 2)}`);
    }

    return lines.join("\n");
  }

  /**
   * 发送消息并开始流式对话
   */
  async sendMessage(
    message: string,
    callbacks: DialogCallbacks,
    mode?: RunMode,
    serviceTier?: ServiceTier // 新增：服务等级参数
  ): Promise<void> {
    if (this.isActive) {
      callbacks.onError?.("当前有对话正在进行中");
      return;
    }

    this.isActive = true;
    this.hasCompleted = false; // 重置完成标志
    this.accumulatedText = "";
    this.segments = [];
    this.currentTextSegment = null;
    this.completeCallback = callbacks.onComplete || null; // 保存完成回调，用于 abort 时触发

    const config = getConfig();

    // 从登录 session 获取真实 userId 和 token
    let userId = config.userId; // 默认值
    let token: string | undefined;
    try {
      console.log("[DialogSession] 尝试获取登录 session...");
      const session = await vscode.authentication.getSession("iccoder", [], {
        silent: true,
      });
      console.log(
        "[DialogSession] session 结果:",
        session ? "已获取" : "null/undefined"
      );
      if (session?.accessToken) {
        console.log(
          "[DialogSession] accessToken 长度:",
          session.accessToken.length
        );

        // 检测 token 是否过期
        const expired = isTokenExpired(session.accessToken);
        if (expired === true) {
          console.error("[DialogSession] token 已过期，需要重新登录");
          vscode.window
            .showErrorMessage("登录已过期，请重新登录", "重新登录")
            .then((selection) => {
              if (selection === "重新登录") {
                vscode.commands.executeCommand("ic-coder.login", {
                  forceReauth: true,
                });
              }
            });
          throw new Error("登录已过期，请重新登录");
        }

        token = session.accessToken; // 保存 token 用于扣费
        const parsedUserId = getUserIdFromToken(session.accessToken);
        console.log("[DialogSession] 解析的 userId:", parsedUserId);
        if (parsedUserId) {
          userId = parsedUserId;
          console.log("[DialogSession] 使用真实 userId:", userId);
        }
      } else {
        console.log(
          "[DialogSession] 未获取到 accessToken，使用默认 userId:",
          userId
        );
      }
    } catch (error) {
      console.warn("[DialogSession] 获取登录 session 失败:", error);
    }

    // 获取压缩数据和新消息（用于后端重启后恢复）
    const historyManager = ChatHistoryManager.getInstance();
    const compactedData = await historyManager.loadCompactedData(this.taskId);
    const newMessages = historyManager.getNewMessagesSinceCompaction();

    // 加载知识图谱数据
    const knowledgeData = await this.loadKnowledgeData();
    console.log(
      "[DialogSession] knowledgeData 加载结果:",
      knowledgeData ? `${knowledgeData.length} 字符` : "null"
    );

    console.log(
      "[DialogSession] serviceTier 参数:",
      serviceTier,
      "-> 使用:",
      serviceTier || config.serviceTier
    );

    const request: DialogRequest = {
      taskId: this.taskId,
      message,
      userId,
      mode: mode || "agent",
      serviceTier: serviceTier || config.serviceTier, // 优先使用传入的参数
      token, // JWT token 用于扣费
      compactedData: compactedData || undefined,
      newMessages: newMessages.length > 0 ? newMessages : undefined,
      knowledgeData: knowledgeData || undefined,
    };

    // 追踪用户消息
    historyManager.trackUserMessage(message);

    const sseCallbacks: SSECallbacks = {
      onTextDelta: (data) => {
        this.accumulatedText += data.text;
        this.appendText(data.text);
        console.log(
          "[DialogSession] onTextDelta, 累积文本长度:",
          this.accumulatedText.length
        );
        callbacks.onText?.(this.accumulatedText, true);
        // 实时发送段落更新
        callbacks.onSegmentUpdate?.(this.segments);
      },

      onToolCall: async (data: ToolCallRequest) => {
        const toolName = data.params.name;
        console.log("[DialogSession] onToolCall:", toolName);

        // 检查是否有活跃的智能体（如果有，工具执行会显示在智能体卡片内，不需要单独显示）
        const hasActiveAgent = this.segments.some(
          (s) => s.type === "agent" && s.agentStatus === "running"
        );

        if (hasActiveAgent) {
          console.log(
            "[DialogSession] onToolCall: 智能体执行中，跳过工具段落:",
            toolName
          );
        } else {
          // 检查是否已经有相同的工具段落（可能由 onToolStart 添加）
          const lastToolSegment = this.segments
            .filter((s) => s.type === "tool")
            .pop();
          if (
            lastToolSegment &&
            lastToolSegment.toolName === toolName &&
            lastToolSegment.toolStatus === "running"
          ) {
            console.log(
              "[DialogSession] onToolCall: 跳过重复的工具段落:",
              toolName
            );
          } else {
            this.addToolSegment(toolName, "running");
            // 实时发送段落更新
            callbacks.onSegmentUpdate?.(this.segments);
          }
        }

        // 注意：不在这里调用 callbacks.onToolStart，避免与 onToolStart 事件重复
        try {
          await executeToolCall(data, this.toolContext);
          if (!hasActiveAgent) {
            this.updateToolSegment(toolName, "success", "执行完成");
            // 实时发送段落更新
            callbacks.onSegmentUpdate?.(this.segments);
          }
          // 也不调用 callbacks.onToolComplete，避免重复
        } catch (error) {
          const errorMsg = error instanceof Error ? error.message : "未知错误";
          if (!hasActiveAgent) {
            this.updateToolSegment(toolName, "error", errorMsg);
            callbacks.onSegmentUpdate?.(this.segments);
          }
          callbacks.onToolError?.(toolName, errorMsg);
        }
      },

      onToolStart: (data) => {
        console.log("[DialogSession] onToolStart:", data.tool_name);
        // 检查是否已经有相同的工具段落（可能由 onToolCall 添加）
        const lastToolSegment = this.segments
          .filter((s) => s.type === "tool")
          .pop();
        if (
          lastToolSegment &&
          lastToolSegment.toolName === data.tool_name &&
          lastToolSegment.toolStatus === "running"
        ) {
          console.log("[DialogSession] 跳过重复的工具段落:", data.tool_name);
        } else {
          this.addToolSegment(data.tool_name, "running");
          // 实时发送段落更新
          callbacks.onSegmentUpdate?.(this.segments);
        }
        console.log("[DialogSession] segments 数量:", this.segments.length);
        callbacks.onToolStart?.(data.tool_name);
      },

      onToolComplete: (data) => {
        this.updateToolSegment(data.tool_name, "success", data.result, data.description);
        callbacks.onToolComplete?.(data.tool_name, data.result);
        // 实时发送段落更新
        callbacks.onSegmentUpdate?.(this.segments);
        // 追踪工具执行结果（用于后端重启后恢复）
        historyManager.trackToolResult(data.tool_name, data.result);
      },

      onToolError: (data) => {
        this.updateToolSegment(data.tool_name, "error", data.error);
        callbacks.onToolError?.(data.tool_name, data.error);
        // 实时发送段落更新
        callbacks.onSegmentUpdate?.(this.segments);
        // 追踪工具执行错误（用于后端重启后恢复）
        historyManager.trackToolResult(data.tool_name, `[错误] ${data.error}`);
      },

      onToolConfirm: async (data: ToolConfirmEvent) => {
        console.log(
          "[DialogSession] onToolConfirm:",
          data.toolName,
          data.confirmId
        );

        // 结束当前文本段落
        this.finalizeTextSegment();

        // 生成工具描述
        const toolDescription = this.getToolDescription(
          data.toolName,
          data.toolInput
        );

        // 构建问题文本
        const toolNameMap: Record<string, string> = {
          file_write: "写入文件",
          file_delete: "删除文件",
          syntax_check: "语法检查",
          simulation: "运行仿真",
        };
        const toolDisplayName = toolNameMap[data.toolName] || data.toolName;
        const question = `确认执行操作：${toolDisplayName}\n\n${toolDescription}`;

        // 生成唯一的 askId
        const askId = `tool_confirm_${data.confirmId}`;

        // 添加问题段落到聊天界面
        this.segments.push({
          type: "question",
          askId: askId,
          question: question,
          options: ["确认执行", "取消"],
        });

        // 实时发送段落更新
        callbacks.onSegmentUpdate?.(this.segments);

        // 调用回调通知 UI
        callbacks.onToolConfirm?.(
          data.confirmId,
          data.toolName,
          data.toolInput
        );

        // 使用 userInteractionManager 等待用户回答
        try {
          await userInteractionManager.handleAskUser(
            {
              askId: askId,
              question: question,
              options: ["确认执行", "取消"],
            } as AskUserEvent,
            this.taskId
          );

          // 注意：用户回答后，需要在 receiveAnswer 中处理 tool_confirm 类型的 askId
          // 这里不直接调用 submitToolConfirm，而是在 userInteractionManager 中统一处理
        } catch (error) {
          console.error("[DialogSession] 处理工具确认失败:", error);
          // 如果出错，默认取消执行
          try {
            await submitToolConfirm({
              confirmId: data.confirmId,
              taskId: this.taskId,
              approved: false,
            });
          } catch (submitError) {
            console.error("[DialogSession] 发送取消响应失败:", submitError);
          }
        }
      },

      onPlanConfirm: async (data: PlanConfirmEvent) => {
        console.log("[DialogSession] onPlanConfirm:", data.title);

        // 结束当前文本段落
        this.finalizeTextSegment();

        const askId = `ask_${data.confirmId}`;

        // 添加计划段落到聊天界面（包含 askId 用于响应）
        // 支持新格式（phases）和旧格式（steps）
        this.segments.push({
          type: "plan",
          askId: askId,
          planTitle: data.title,
          planPhases: data.phases,
          planSteps: data.steps,
          planSummary: data.summary,
        });

        // 实时发送段落更新
        callbacks.onSegmentUpdate?.(this.segments);

        // 注册问题到前端（类似 askUser），以便用户回答时能找到
        const planEvent = {
          askId: askId,
          question: `请确认执行计划：${data.title}`,
          options: ["确认执行", "修改计划", "取消"],
        };
        try {
          await userInteractionManager.handleAskUser(
            planEvent as AskUserEvent,
            this.taskId
          );
        } catch (error) {
          console.error("[DialogSession] 处理计划确认失败:", error);
        }

        // 调用回调通知 UI
        callbacks.onPlanConfirm?.(
          data.confirmId,
          data.title,
          data.phases,
          data.steps,
          data.summary
        );
      },

      onPhaseProgress: (data: import("../types/api").PhaseProgressEvent) => {
        console.log(
          "[DialogSession] onPhaseProgress:",
          data.phaseId,
          data.status
        );

        // 1. 尝试更新 plan segment（兼容旧逻辑）
        for (let i = this.segments.length - 1; i >= 0; i--) {
          const seg = this.segments[i];
          if (seg.type === "plan" && seg.planPhases) {
            seg.planPhases = seg.planPhases.map((phase) => {
              if (phase.id === data.phaseId) {
                return { ...phase, status: data.status };
              }
              return phase;
            });
            callbacks.onSegmentUpdate?.(this.segments);
            break;
          }
        }

        // 2. 通知外部更新独立进度条
        callbacks.onPhaseProgress?.(data.phaseId, data.status);
      },

      onPlanStepAdd: (data: import("../types/api").PlanStepAddEvent) => {
        console.log("[DialogSession] onPlanStepAdd:", data.phaseId, data.step);

        for (let i = this.segments.length - 1; i >= 0; i--) {
          const seg = this.segments[i];
          if (seg.type === "plan" && seg.planPhases) {
            seg.planPhases = seg.planPhases.map((phase) => {
              if (phase.id === data.phaseId) {
                const newSteps = [...(phase.steps || [])];
                if (data.index >= 0 && data.index < newSteps.length) {
                  newSteps.splice(data.index, 0, data.step);
                } else {
                  newSteps.push(data.step);
                }
                return { ...phase, steps: newSteps };
              }
              return phase;
            });
            break;
          }
        }
        callbacks.onSegmentUpdate?.(this.segments);
      },

      onPlanStepRemove: (data: import("../types/api").PlanStepRemoveEvent) => {
        console.log(
          "[DialogSession] onPlanStepRemove:",
          data.phaseId,
          data.stepIndex
        );

        for (let i = this.segments.length - 1; i >= 0; i--) {
          const seg = this.segments[i];
          if (seg.type === "plan" && seg.planPhases) {
            seg.planPhases = seg.planPhases.map((phase) => {
              if (phase.id === data.phaseId && phase.steps) {
                const newSteps = [...phase.steps];
                newSteps.splice(data.stepIndex, 1);
                return { ...phase, steps: newSteps };
              }
              return phase;
            });
            break;
          }
        }
        callbacks.onSegmentUpdate?.(this.segments);
      },

      onPlanStepUpdate: (data: import("../types/api").PlanStepUpdateEvent) => {
        console.log(
          "[DialogSession] onPlanStepUpdate:",
          data.phaseId,
          data.stepIndex
        );

        for (let i = this.segments.length - 1; i >= 0; i--) {
          const seg = this.segments[i];
          if (seg.type === "plan" && seg.planPhases) {
            seg.planPhases = seg.planPhases.map((phase) => {
              if (phase.id === data.phaseId && phase.steps) {
                const newSteps = [...phase.steps];
                if (data.stepIndex >= 0 && data.stepIndex < newSteps.length) {
                  newSteps[data.stepIndex] = data.step;
                }
                return { ...phase, steps: newSteps };
              }
              return phase;
            });
            break;
          }
        }
        callbacks.onSegmentUpdate?.(this.segments);
      },

      onPlanSummaryUpdate: (
        data: import("../types/api").PlanSummaryUpdateEvent
      ) => {
        console.log("[DialogSession] onPlanSummaryUpdate");

        for (let i = this.segments.length - 1; i >= 0; i--) {
          const seg = this.segments[i];
          if (seg.type === "plan") {
            seg.planSummary = data.summary;
            break;
          }
        }
        callbacks.onSegmentUpdate?.(this.segments);
      },

      onAskUser: async (data: AskUserEvent) => {
        this.finalizeTextSegment();
        this.segments.push({
          type: "question",
          askId: data.askId,
          question: data.question,
          options: data.options,
        });
        // 实时发送段落更新（包含问题）
        callbacks.onSegmentUpdate?.(this.segments);
        // 同时调用 onQuestion 用于更新状态栏等
        callbacks.onQuestion?.(data.askId, data.question, data.options);
        try {
          await userInteractionManager.handleAskUser(data, this.taskId);
        } catch (error) {
          console.error("[DialogSession] 处理用户问题失败:", error);
        }
      },

      onComplete: (data) => {
        this.isActive = false;
        this.hasCompleted = true; // 标记已收到 complete 事件
        this.finalizeTextSegment();

        // 追踪 AI 消息（用于后端重启后恢复）
        if (this.accumulatedText) {
          historyManager.trackAiMessage(this.accumulatedText);
        }

        // 发送所有段落
        callbacks.onComplete?.(this.segments);
      },

      onError: (data) => {
        this.isActive = false;

        // 检测登录状态过期（只弹一次窗，不再传递错误）
        if (
          data.message.includes("LOGIN_EXPIRED") ||
          data.message.includes("登录状态已过期")
        ) {
          vscode.window
            .showErrorMessage("登录状态已过期，请重新登录", "重新登录")
            .then((selection) => {
              if (selection === "重新登录") {
                vscode.commands.executeCommand("ic-coder.login", {
                  forceReauth: true,
                });
              }
            });
          // 登录过期错误已处理，不再传递给外部
          return;
        }

        callbacks.onError?.(data.message);
      },

      onWarning: (data) => {
        callbacks.onNotification?.(`⚠️ ${data.message}`);
      },

      onNotification: (data) => {
        callbacks.onNotification?.(data.message);
      },

      // 智能体事件处理
      onAgentStart: (data) => {
        console.log("[DialogSession] onAgentStart:", data.agentId);
        this.finalizeTextSegment();
        this.segments.push({
          type: "agent",
          agentId: data.agentId,
          agentName: data.agentName,
          content: data.instruction,
          agentStatus: "running",
          agentSteps: [],
        });
        callbacks.onSegmentUpdate?.(this.segments);
      },

      onAgentProgress: (data) => {
        console.log(
          "[DialogSession] onAgentProgress:",
          data.agentId,
          data.step,
          data.status
        );
        const agentSegment = this.segments.find(
          (s) => s.type === "agent" && s.agentId === data.agentId
        );
        if (agentSegment && agentSegment.agentSteps) {
          if (data.status === "running") {
            agentSegment.agentSteps.push({
              step: data.step,
              toolName: data.toolName,
              toolInput: data.toolInput,
              status: "running",
            });
          } else {
            const step = agentSegment.agentSteps.find(
              (s) => s.step === data.step
            );
            if (step) {
              step.status = data.status;
              step.toolResult = data.toolResult;
            }
          }
          callbacks.onSegmentUpdate?.(this.segments);
        }
      },

      onAgentComplete: (data) => {
        console.log("[DialogSession] onAgentComplete:", data.agentId);
        const agentSegment = this.segments.find(
          (s) => s.type === "agent" && s.agentId === data.agentId
        );
        if (agentSegment) {
          agentSegment.agentStatus = "completed";
          agentSegment.content = data.summary;
          callbacks.onSegmentUpdate?.(this.segments);
        }
      },

      onAgentError: (data) => {
        console.log("[DialogSession] onAgentError:", data.agentId, data.error);
        const agentSegment = this.segments.find(
          (s) => s.type === "agent" && s.agentId === data.agentId
        );
        if (agentSegment) {
          agentSegment.agentStatus = "error";
          agentSegment.content = data.error;
          callbacks.onSegmentUpdate?.(this.segments);
        }
      },

      onMemoryCompacted: async (data) => {
        console.log("[DialogSession] onMemoryCompacted:", data.taskId);
        // 保存压缩数据到本地
        await historyManager.saveCompactedData(data.compactedData);
      },

      onContextUsage: (data) => {
        console.log(
          "[DialogSession] onContextUsage:",
          data.currentTokens,
          "/",
          data.maxTokens
        );
        callbacks.onContextUsage?.(data);
      },

      onCreditUpdate: (data) => {
        console.log(
          "[DialogSession] onCreditUpdate: 扣除",
          data.deductedCredits,
          "剩余",
          data.remainingCredits
        );
        // 更新余额缓存
        updateCachedBalance(data.remainingCredits);
        // 资源点余额低于阈值时弹窗提醒
        const LOW_CREDIT_THRESHOLD = 5;
        if (data.remainingCredits < LOW_CREDIT_THRESHOLD) {
          vscode.window
            .showWarningMessage(
              `资源点余额不足！当前剩余 ${data.remainingCredits.toFixed(
                2
              )} 点，请及时充值。`,
              "去充值"
            )
            .then((selection) => {
              if (selection === "去充值") {
                // 打开充值页面
                vscode.env.openExternal(
                  vscode.Uri.parse("https://iccoder.com/recharge")
                );
              }
            });
        }
      },

      onOpen: () => {
        console.log("[DialogSession] SSE 连接已建立");
      },

      onClose: () => {
        console.log("[DialogSession] SSE 连接已关闭");
        // 如果没有收到 complete 事件，需要补充完成逻辑
        if (!this.hasCompleted && this.isActive) {
          console.log("[DialogSession] 未收到 complete 事件，补充完成处理");
          this.finalizeTextSegment();
          if (this.accumulatedText) {
            historyManager.trackAiMessage(this.accumulatedText);
          }
          callbacks.onComplete?.(this.segments);
        }
        this.isActive = false;
      },
    };

    try {
      this.sseController = await startStreamDialog(request, sseCallbacks);
    } catch (error) {
      this.isActive = false;
      const errorMsg = error instanceof Error ? error.message : "连接失败";
      callbacks.onError?.(errorMsg);
      throw error;
    }
  }

  /**
   * 中止当前对话
   */
  abort(): void {
    // 先标记完成，防止 onClose 重复触发
    const wasActive = this.isActive;
    this.hasCompleted = true;
    this.isActive = false;

    if (this.sseController) {
      this.sseController.abort();
      this.sseController = null;
    }
    userInteractionManager.cancelAll();

    // 如果之前是活跃状态，触发完成回调以结束 Promise
    if (wasActive && this.completeCallback) {
      this.finalizeTextSegment();
      console.log("[DialogSession] abort 触发完成回调");
      this.completeCallback(this.segments);
      this.completeCallback = null;
    }

    // 通知后端停止处理
    stopDialog(this.taskId).catch((err) => {
      console.warn("[DialogSession] 停止对话请求失败:", err);
    });
  }

  /**
   * 获取当前的消息段落（用于中止时保存）
   */
  getSegments(): MessageSegment[] {
    return this.segments;
  }

  /**
   * 获取累积的文本内容
   */
  getAccumulatedText(): string {
    return this.accumulatedText;
  }

  /**
   * 提交用户回答
   */
  async submitAnswer(
    askId: string,
    selected?: string[],
    customInput?: string
  ): Promise<void> {
    // 直接调用 receiveAnswer，传递 taskId 作为 fallbackTaskId
    // 如果 pendingQuestions 中有问题，走正常流程
    // 如果没有，receiveAnswer 会使用 fallbackTaskId 直接发送到后端
    await userInteractionManager.receiveAnswer(
      askId,
      selected,
      customInput,
      this.taskId
    );
  }
}

/**
 * 全局对话会话管理
 */
class DialogManager {
  private currentSession: DialogSession | null = null;

  /**
   * 创建新会话
   * @param extensionPath 扩展路径
   * @param existingTaskId 可选，复用现有的 taskId（用于 Plan 模式确认后继续执行）
   */
  createSession(extensionPath: string, existingTaskId?: string): DialogSession {
    // 如果有活跃会话，先中止
    if (this.currentSession?.active) {
      this.currentSession.abort();
    }
    this.currentSession = new DialogSession(extensionPath, existingTaskId);
    return this.currentSession;
  }

  /**
   * 获取当前会话
   */
  getCurrentSession(): DialogSession | null {
    return this.currentSession;
  }

  /**
   * 中止当前会话
   */
  abortCurrentSession(): void {
    this.currentSession?.abort();
    this.currentSession = null; // 清空会话，确保下次创建新会话
  }
}

export const dialogManager = new DialogManager();
