/**
 * MessageManager - 消息管理核心模块
 * 
 * 单一数据源原则：所有消息相关状态统一在此管理
 * 解决核心问题：
 * 1. 竞态条件：确保消息立即处理并同步到所有订阅者
 * 2. 状态同步：已读状态在所有组件间保持一致
 * 
 * 架构特点：
 * - 管理conversations和messages状态
 * - 统一处理SSE消息
 * - 统一处理本地数据库读写
 * - 提供订阅机制供React组件使用
 *
 * UI 只应订阅 MessageManager / hooks：列表数据可能来自网络游标或 SQLite 缓存回退，对界面透明。
 */

import { ConversationResponse, MessageResponse, MessageSegment, UserDTO } from '../types/dto';
import { messageService } from '../services/messageService';
import {
  sseService,
  WSChatMessage,
  WSGroupChatMessage,
  WSReadMessage,
  WSGroupReadMessage,
  WSRecallMessage,
  WSGroupRecallMessage,
  WSGroupTypingMessage,
  WSGroupNoticeMessage,
  GroupNoticeType,
} from '../services/sseService';
import {
  saveMessage,
  saveMessagesBatch,
  getMessagesByConversation,
  getMaxSeq,
  getMinSeq,
  getMessagesBeforeSeq,
  markConversationAsRead,
  updateConversationCacheUnreadCount,
  CachedMessage,
  getUserCache,
  saveUserCache,
  updateMessageStatus,
  deleteConversation as deleteConversationFromDb,
  saveConversationsWithRelatedCache,
} from '../services/database';
import { api } from '../services/api';
import { vibrateOnMessage } from '../services/messageVibrationService';
import { useAuthStore } from './authStore';
import {
  type IConversationListPagedSource,
  SqliteConversationListPagedSource,
  createRemoteConversationListSource,
  CONVERSATION_LIST_PAGE_SIZE,
} from './conversationListSources';

// ==================== 类型定义 ====================

export type MessageEventType =
  | 'conversations_updated'
  | 'conversations_loading'
  | 'messages_updated'
  | 'unread_count_updated'
  | 'connection_changed'
  | 'message_sent'
  | 'message_read'
  | 'message_received'
  | 'message_recalled'
  | 'typing_status'
  | 'group_notice'
  | 'error';

export interface MessageEvent {
  type: MessageEventType;
  payload: any;
  timestamp: number;
}

export type MessageSubscriber = (event: MessageEvent) => void;

// ==================== 内部状态接口 ====================

interface MessageManagerState {
  // 会话相关
  conversations: Map<string, ConversationResponse>;
  conversationList: ConversationResponse[];

  // 消息相关 - 按会话ID存储
  messagesMap: Map<string, MessageResponse[]>;

  // 未读数
  totalUnreadCount: number;
  systemUnreadCount: number;

  // 连接状态
  isSSEConnected: boolean;

  // 当前活动会话ID（用户正在查看的会话）
  currentConversationId: string | null;

  // 加载状态
  isLoadingConversations: boolean;
  loadingMessagesSet: Set<string>; // 正在加载消息的会话ID集合

  // 初始化状态
  isInitialized: boolean;

  // 订阅者
  subscribers: Set<MessageSubscriber>;

  // 输入状态 - 按群组ID存储正在输入的用户ID列表
  typingUsersMap: Map<string, string[]>;

  // 当前用户的禁言状态 - 按群组ID存储
  mutedStatusMap: Map<string, boolean>;
}

// ==================== 已读状态保护机制常量 ====================

/**
 * 已读状态保护延迟时间（毫秒）
 * API 完成后，继续保护一段时间，防止 fetchConversations 的旧数据覆盖
 */
const READ_STATE_PROTECTION_DELAY = 5000; // 5秒

/** 可注入会话列表源，便于测试或替换实现 */
export interface MessageManagerConversationListDeps {
  remoteConversationListSource?: IConversationListPagedSource;
  localConversationListSource?: IConversationListPagedSource;
  /**
   * 未传 remoteConversationListSource 时：默认 `cursor`（/conversations/cursor），
   * `offset` 为常规页码（/conversations?page=&page_size=）。
   */
  remoteListKind?: 'cursor' | 'offset';
  /** 与 remoteListKind 搭配，默认与 CONVERSATION_LIST_PAGE_SIZE 一致 */
  remoteListPageSize?: number;
}

/**
 * 已读状态记录接口
 */
interface ReadStateRecord {
  /** 标记已读的时间戳 */
  timestamp: number;
  /** 状态版本号，用于防止旧数据覆盖新数据 */
  version: number;
  /** 已上报的已读序号（用于去重） */
  lastReadSeq: number;
  /** 清除保护的定时器ID */
  clearTimer?: NodeJS.Timeout;
}

// ==================== MessageManager 类 ====================

class MessageManager {
  private state: MessageManagerState;
  private sseUnsubscribe: (() => void) | null = null;
  private currentUserId: string | null = null;
  private authUnsubscribe: (() => void) | null = null;
  private lastReconnectSyncAt: number = 0;
  private initializePromise: Promise<void> | null = null;
  private activatingConversationTasks: Map<string, Promise<void>> = new Map();

  /** 正在加载会话列表下一页 */
  private loadingMoreConversations = false;
  /** 聊天页活跃期间延迟的会话列表刷新 */
  private deferredConversationRefresh = false;

  /** 远端会话列表（游标或页码，由注入/remoteListKind 决定） */
  private readonly remoteConversationListSource: IConversationListPagedSource;
  /** 本地会话列表缓存（SQLite，单批） */
  private readonly localConversationListSource: IConversationListPagedSource;

  /**
   * 正在进行中的已读 API 请求集合
   * 用于防止 fetchConversations 的服务器数据覆盖乐观已读状态
   * key: conversationId, value: 已读状态记录（包含时间戳和版本号）
   */
  private pendingReadMap: Map<string, ReadStateRecord> = new Map();

  /**
   * 全局已读状态版本号，每次标记已读时递增
   * 用于判断服务器数据是否比本地状态更旧
   */
  private readStateVersion: number = 0;

  // 初始化阶段缓冲来自 SSE 的消息事件：在已拉取服务器权威状态（会话/未读）前
  // 不把 SSE 事件直接用于震动/未读增量，避免竞态导致“闪一下又消失”
  private bufferedChatMessages: Array<(WSChatMessage | WSGroupChatMessage) & { _isAck?: boolean }> = [];
  private bufferedReadReceipts: Array<WSReadMessage | WSGroupReadMessage> = [];

  // 用于覆盖“初始化完成但仍在刷新服务器权威状态”的过渡窗口
  private isBootstrapping: boolean = false;

  constructor(deps?: MessageManagerConversationListDeps) {
    const pageSize = deps?.remoteListPageSize ?? CONVERSATION_LIST_PAGE_SIZE;
    this.remoteConversationListSource =
      deps?.remoteConversationListSource ??
      createRemoteConversationListSource(
        deps?.remoteListKind === 'offset' ? 'offset' : 'cursor',
        pageSize
      );
    this.localConversationListSource =
      deps?.localConversationListSource ?? new SqliteConversationListPagedSource();

    this.state = {
      conversations: new Map(),
      conversationList: [],
      messagesMap: new Map(),
      totalUnreadCount: 0,
      systemUnreadCount: 0,
      isSSEConnected: false,
      currentConversationId: null,
      isLoadingConversations: false,
      loadingMessagesSet: new Set(),
      isInitialized: false,
      subscribers: new Set(),
      typingUsersMap: new Map(),
      mutedStatusMap: new Map(),
    };

    // 监听认证状态变化
    this.initAuthListener();
  }

  // ==================== 私有工具方法 ====================

  private initAuthListener() {
    // 获取当前用户ID
    const authState = useAuthStore.getState();
    this.currentUserId = authState.currentUser?.id || null;

    // 如果已登录，自动初始化
    if (this.currentUserId && !this.state.isInitialized) {
      this.initialize();
    }

    // 监听登录态变化，修复冷启动时 currentUser 延迟就绪导致未初始化的问题
    if (!this.authUnsubscribe) {
      this.authUnsubscribe = useAuthStore.subscribe((state) => {
        const nextUserId = state.currentUser?.id || null;
        const prevUserId = this.currentUserId;
        this.currentUserId = nextUserId;

        if (nextUserId && !this.state.isInitialized) {
          this.initialize();
        }

        // 冷启动时若用户信息后到，自动重激活当前会话，保证首进 Chat 不丢首次拉取
        if (nextUserId && this.state.currentConversationId) {
          this.activateConversation(this.state.currentConversationId, { forceSync: true }).catch(error => {
            console.error('[MessageManager] 登录态就绪后重激活会话失败:', error);
          });
        }

        // 退出登录时清理内存状态，避免脏数据残留
        if (!nextUserId && prevUserId && this.state.isInitialized) {
          this.destroy();
        }
      });
    }
  }

  private getCurrentUserId(): string | null {
    if (!this.currentUserId) {
      this.currentUserId = useAuthStore.getState().currentUser?.id || null;
    }
    return this.currentUserId;
  }

  private normalizeConversationId(conversationId: string | number | null | undefined): string {
    return conversationId == null ? '' : String(conversationId);
  }

  private notifySubscribers(event: MessageEvent) {
    this.state.subscribers.forEach(subscriber => {
      try {
        subscriber(event);
      } catch (error) {
        console.error('[MessageManager] 订阅者执行失败:', error);
      }
    });
  }

  private shouldDeferConversationRefresh(source: string, forceRefresh: boolean): boolean {
    if (!this.state.currentConversationId) return false;
    if (!forceRefresh) return false;
    // 列表域后台刷新来源：聊天活跃期间一律延后执行
    return source === 'sse-reconnect' || source === 'prefetch' || source === 'hooks-initial-refresh';
  }

  async requestConversationListRefresh(
    source: string,
    options?: { force?: boolean; allowDefer?: boolean }
  ): Promise<void> {
    const forceRefresh = options?.force ?? true;
    const allowDefer = options?.allowDefer ?? true;
    if (allowDefer && this.shouldDeferConversationRefresh(source, forceRefresh)) {
      this.deferredConversationRefresh = true;
      if (__DEV__) {
        console.log('[MessageManager] defer conversation refresh request', {
          source,
          activeConversationId: this.state.currentConversationId,
        });
      }
      return;
    }
    await this.fetchConversations(forceRefresh, source);
  }

  /**
   * 按 message_id 合并消息并按 seq 排序。
   * 后者覆盖前者，可用来吸收更完整的同 ID 消息体（例如服务端回包/SSE）。
   */
  private mergeMessagesById(base: MessageResponse[], incoming: MessageResponse[]): MessageResponse[] {
    if (incoming.length === 0) return base;
    const merged = new Map<string, MessageResponse>();
    [...base, ...incoming].forEach(msg => {
      merged.set(String(msg.id), msg);
    });
    return Array.from(merged.values()).sort((a, b) => a.seq - b.seq);
  }

  /**
   * 历史消息合并优化：
   * - 常见场景：incoming 全部比 existing 更旧，直接前插，避免全量排序
   * - 异常/重叠场景：回退到通用 mergeMessagesById
   */
  private mergeOlderMessages(existing: MessageResponse[], incoming: MessageResponse[]): MessageResponse[] {
    if (incoming.length === 0) return existing;

    const incomingAsc = [...incoming].sort((a, b) => a.seq - b.seq);
    if (existing.length === 0) return incomingAsc;

    const existingMinSeq = existing[0]?.seq ?? Number.MAX_SAFE_INTEGER;
    const incomingMaxSeq = incomingAsc[incomingAsc.length - 1]?.seq ?? Number.MIN_SAFE_INTEGER;

    // 纯历史前插快路径：避免全量 merge + sort
    if (incomingMaxSeq < existingMinSeq) {
      return [...incomingAsc, ...existing];
    }

    // 兜底：存在重叠/乱序时走通用路径
    return this.mergeMessagesById(existing, incomingAsc);
  }

  private updateConversationList() {
    // 会话排序：置顶优先，再按最后消息时间排序
    const list = Array.from(this.state.conversations.values()).sort((a, b) => {
      const aPinned = a.is_pinned ? 1 : 0;
      const bPinned = b.is_pinned ? 1 : 0;
      if (aPinned !== bPinned) {
        return bPinned - aPinned;
      }
      const aTime = new Date(a.last_message_at || a.updated_at || 0).getTime();
      const bTime = new Date(b.last_message_at || b.updated_at || 0).getTime();
      return bTime - aTime;
    });
    this.state.conversationList = list;
  }

  /**
   * 当已读游标已追上 last_seq 时，强制未读为 0（修复本地 SQLite 中 unread_count 与已读状态不一致）
   */
  private normalizeConversationUnreadFromReadCursor(conv: ConversationResponse): ConversationResponse {
    const lastSeq = Number(conv.last_seq || 0);
    const myRead = Number(conv.my_last_read_seq ?? 0);
    if (lastSeq > 0 && myRead >= lastSeq && (conv.unread_count || 0) > 0) {
      return { ...conv, unread_count: 0 };
    }
    return conv;
  }

  /**
   * 将游标接口返回的单条会话写入 Map（统一 string id、尊重 pendingReadMap 已读保护）
   */
  private applyConversationFromFetch(conv: ConversationResponse): void {
    const id = this.normalizeConversationId(conv.id);
    const readRecord = this.pendingReadMap.get(id);
    let next: ConversationResponse;
    if (readRecord) {
      const shouldPreserveLocalRead = (conv.unread_count || 0) > 0;
      next = shouldPreserveLocalRead
        ? { ...conv, id, unread_count: 0 }
        : { ...conv, id };
    } else {
      next = { ...conv, id };
    }
    next = this.normalizeConversationUnreadFromReadCursor(next);
    this.state.conversations.set(id, next);
  }

  /** 与会话列表同步写入本地缓存（参与者 / 群 / 列表） */
  private persistConversationListCache(): void {
    const list = Array.from(this.state.conversations.values());
    const users = list.flatMap(conv => [
      ...(conv.participants || []),
      ...(conv.last_message?.sender ? [conv.last_message.sender] : []),
    ]);
    const groups = list
      .map(conv => conv.group)
      .filter((group): group is NonNullable<ConversationResponse['group']> => Boolean(group));
    
    saveConversationsWithRelatedCache(list, users, groups).catch(error => {
      console.error('[MessageManager] 持久化会话列表失败:', error);
    });
  }

  private recomputeConversationTotalUnread(): void {
    this.state.totalUnreadCount = Array.from(this.state.conversations.values()).reduce(
      (sum, conv) => sum + (conv.unread_count || 0),
      0
    );
  }

  private emitConversationListAndUnreadUpdates(): void {
    this.persistConversationListCache();
    this.notifySubscribers({
      type: 'conversations_updated',
      payload: { conversations: this.state.conversationList },
      timestamp: Date.now(),
    });
    this.notifySubscribers({
      type: 'unread_count_updated',
      payload: {
        totalUnreadCount: this.state.totalUnreadCount,
        systemUnreadCount: this.state.systemUnreadCount,
      },
      timestamp: Date.now(),
    });
  }

  /** 通过本地分页源灌入内存（暖机 / 网络失败回退） */
  private async hydrateConversationsFromLocalSource(): Promise<boolean> {
    this.localConversationListSource.restart();
    const page = await this.localConversationListSource.loadNext();
    if (!page.items.length) {
      return false;
    }
    this.state.conversations.clear();
    page.items.forEach(conv => this.applyConversationFromFetch(conv));
    this.updateConversationList();
    this.recomputeConversationTotalUnread();
    return true;
  }

  // ==================== 初始化与销毁 ====================

  async initialize(): Promise<void> {
    if (this.state.isInitialized) {
      return;
    }

    if (this.initializePromise) {
      await this.initializePromise;
      return;
    }


    this.initializePromise = (async () => {
      try {
        // 1. 获取当前用户ID
        this.currentUserId = this.getCurrentUserId();
        if (!this.currentUserId) {
          console.warn('[MessageManager] 用户未登录，延迟初始化');
          return;
        }

        this.isBootstrapping = true;

        // 2. 初始化SSE监听
        this.initSSEListeners();

        // 3. 加载会话列表
        await this.fetchConversations(false, 'initialize');

        // 4. 加载未读数
        await this.fetchUnreadCount();

        this.state.isInitialized = true;

        // 初始化窗口期内缓冲的 SSE 事件：刷新为服务器权威，避免“未读闪一下又消失”
        await this.flushBufferedSSEEvents();

        this.isBootstrapping = false;

        this.notifySubscribers({
          type: 'conversations_updated',
          payload: { conversations: this.state.conversationList },
          timestamp: Date.now(),
        });

        // 若初始化完成时已有活动会话（用户已在 Chat 页面），立即补齐该会话同步
        if (this.state.currentConversationId) {
          await this.fetchMessages(this.state.currentConversationId);
        }
      } catch (error) {
        console.error('[MessageManager] 初始化失败:', error);
        this.isBootstrapping = false;
        this.notifySubscribers({
          type: 'error',
          payload: { error, context: 'initialize' },
          timestamp: Date.now(),
        });
      }
    })();

    try {
      await this.initializePromise;
    } finally {
      this.initializePromise = null;
    }
  }

  /**
   * 初始化完成后，处理在初始化阶段被缓冲的 SSE 事件。
   *
   * 架构目标：
   * 1) 初始化阶段不把 SSE 用于未读增量/震动（避免竞态“先加后清”）
   * 2) 初始化完成后，用服务器权威状态刷新会话/未读，再把事件用于消息内容展示
   */
  private async flushBufferedSSEEvents(): Promise<void> {
    // 为了覆盖“刷新服务器权威状态过程中又到了一些 SSE”这种窗口，这里做一个有上限的循环清空缓冲。
    // 如果在线流持续不断，会产生更多轮次；因此使用上限避免长时间阻塞初始化。
    const MAX_FLUSH_ITERATIONS = 3;
    for (let i = 0; i < MAX_FLUSH_ITERATIONS; i++) {
      const hasBuffered = this.bufferedChatMessages.length > 0 || this.bufferedReadReceipts.length > 0;
      if (!hasBuffered) return;

      const chatEvents = this.bufferedChatMessages;
      const readEvents = this.bufferedReadReceipts;
      this.bufferedChatMessages = [];
      this.bufferedReadReceipts = [];

      // 先把消息内容灌进内存（用于 ChatScreen 如果正好激活能立刻看到）
      // 不在这里修改 unread_count / 不触发震动 / 不做自动标记已读。
      for (const m of chatEvents) {
        await this.handleNewMessage(m, {
          suppressUnreadIncrement: true,
          suppressVibration: true,
          suppressConversationUpdates: true,
          suppressAutoMarkAsRead: true,
        });
      }

      // 已读回执目前在本仓库实现为空（handleReadReceipt / handleGroupReadReceipt 是 no-op），保留扩展位
      for (const r of readEvents) {
        if (r.type === 'read') {
          this.handleReadReceipt(r);
        } else {
          this.handleGroupReadReceipt(r as WSGroupReadMessage);
        }
      }

      // 使用服务器权威刷新会话与未读，避免初始化窗口期内漏算/重复算
      await this.fetchConversations(true, 'sse-buffer-flush');
      await this.fetchUnreadCount();
    }
  }

  destroy(): void {
    if (this.sseUnsubscribe) {
      this.sseUnsubscribe();
      this.sseUnsubscribe = null;
    }
    this.state.subscribers.clear();
    this.state.isInitialized = false;
    this.initializePromise = null;
    this.activatingConversationTasks.clear();
    this.remoteConversationListSource.restart();
    this.localConversationListSource.restart();
    this.loadingMoreConversations = false;
  }

  // ==================== SSE 处理 ====================

  private initSSEListeners(): void {
    if (this.sseUnsubscribe) {
      this.sseUnsubscribe();
    }


    // 监听私聊消息
    sseService.on('chat', (message: WSChatMessage) => {
      if (!this.state.isInitialized || this.isBootstrapping) {
        this.bufferedChatMessages.push(message);
        return;
      }
      this.handleNewMessage(message);
    });

    // 监听群聊消息
    sseService.on('group_message', (message: WSGroupChatMessage) => {
      if (!this.state.isInitialized || this.isBootstrapping) {
        this.bufferedChatMessages.push(message);
        return;
      }
      this.handleNewMessage(message);
    });

    // 监听私聊已读回执
    sseService.on('read', (message: WSReadMessage) => {
      if (!this.state.isInitialized || this.isBootstrapping) {
        this.bufferedReadReceipts.push(message);
        return;
      }
      this.handleReadReceipt(message);
    });

    // 监听群聊已读回执
    sseService.on('group_read', (message: WSGroupReadMessage) => {
      if (!this.state.isInitialized || this.isBootstrapping) {
        this.bufferedReadReceipts.push(message);
        return;
      }
      this.handleGroupReadReceipt(message);
    });

    // 监听私聊消息撤回
    sseService.on('recall', (message: WSRecallMessage) => {
      this.handleRecallMessage(message);
    });

    // 监听群聊消息撤回
    sseService.on('group_recall', (message: WSGroupRecallMessage) => {
      this.handleGroupRecallMessage(message);
    });

    // 监听群聊输入状态
    sseService.on('group_typing', (message: WSGroupTypingMessage) => {
      this.handleGroupTyping(message);
    });

    // 监听群通知
    sseService.on('group_notice', (message: WSGroupNoticeMessage) => {
      this.handleGroupNotice(message);
    });

    // 监听连接状态
    sseService.onConnect(() => {
      this.state.isSSEConnected = true;
      this.notifySubscribers({
        type: 'connection_changed',
        payload: { connected: true },
        timestamp: Date.now(),
      });

      // 冷启动/重连兜底：连接恢复后同步会话和当前会话消息，避免首屏空数据
      const now = Date.now();
      if (now - this.lastReconnectSyncAt > 1500) {
        this.lastReconnectSyncAt = now;
        // 聊天页活跃时不强刷会话列表，避免触发不必要的 UI 抖动/重算
        if (!this.state.currentConversationId) {
          this.requestConversationListRefresh('sse-reconnect', { force: true, allowDefer: true }).catch(error => {
            console.error('[MessageManager] 连接后同步会话失败:', error);
          });
        } else {
          this.fetchUnreadCount().catch(error => {
            console.error('[MessageManager] 连接后同步未读数失败:', error);
          });
        }
        if (this.state.currentConversationId) {
          this.fetchMessages(this.state.currentConversationId).catch(error => {
            console.error('[MessageManager] 连接后同步当前会话消息失败:', error);
          });
        }
      }
    });

    sseService.onDisconnect(() => {
      this.state.isSSEConnected = false;
      this.notifySubscribers({
        type: 'connection_changed',
        payload: { connected: false },
        timestamp: Date.now(),
      });
    });
  }

  // ==================== 消息处理核心方法 ====================

  // 已处理消息ID集合（用于去重，防止ACK消息和正常消息重复处理）
  private processedMessageIds: Set<string> = new Set();
  private processedMessageIdsExpiry: Map<string, number> = new Map();

  /**
   * 清理过期的消息ID（防止内存泄漏）
   */
  private cleanupProcessedMessageIds(): void {
    const now = Date.now();
    const expiryTime = 5 * 60 * 1000; // 5分钟过期
    for (const [id, timestamp] of this.processedMessageIdsExpiry.entries()) {
      if (now - timestamp > expiryTime) {
        this.processedMessageIds.delete(id);
        this.processedMessageIdsExpiry.delete(id);
      }
    }
  }

  /**
   * 检查消息是否已处理
   */
  private isMessageProcessed(messageId: string): boolean {
    return this.processedMessageIds.has(messageId);
  }

  /**
   * 标记消息已处理
   */
  private markMessageAsProcessed(messageId: string): void {
    this.processedMessageIds.add(messageId);
    this.processedMessageIdsExpiry.set(messageId, Date.now());
    // 定期清理
    if (this.processedMessageIds.size > 1000) {
      this.cleanupProcessedMessageIds();
    }
  }

  // 正在获取用户信息的请求映射（用于去重）
  private pendingUserRequests: Map<string, Promise<UserDTO | null>> = new Map();

  /**
   * 根据群通知类型构建系统提示文案
   */
  private buildGroupNoticeText(noticeType: GroupNoticeType, data: any): string {
    const username = data?.username || '用户';
    switch (noticeType) {
      case 'member_join':
        return `"${username}" 加入了群聊`;
      case 'member_leave':
        return `"${username}" 退出了群聊`;
      case 'member_removed':
        return `"${username}" 被移出群聊`;
      case 'muted':
        return `"${username}" 已被管理员禁言`;
      case 'unmuted':
        return `"${username}" 已被管理员解除禁言`;
      default:
        return '';
    }
  }

  /**
   * 根据群组ID查找会话ID
   */
  private findConversationIdByGroupId(groupId: string): string | null {
    for (const conv of this.state.conversationList) {
      if (String(conv.group?.id || '') === groupId) {
        return conv.id;
      }
    }
    return null;
  }

  /**
   * 批量异步填充消息的 sender 信息，填充完成后更新内存并通知订阅者
   */
  private enrichMessagesWithSenderInfo(conversationId: string, messages: MessageResponse[]): void {
    const currentUserId = this.getCurrentUserId();
    // 收集所有需要查询的唯一 sender_id（排除当前用户）
    const senderIds = [...new Set(
      messages
        .filter(m => m.sender_id && m.sender_id !== currentUserId && m.sender_id !== '10000' && !m.sender)
        .map(m => m.sender_id)
    )];

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

    // 并发获取所有 sender 信息
    Promise.all(senderIds.map(id => this.getSenderInfo(id).then(user => ({ id, user }))))
      .then(results => {
        const senderMap = new Map<string, UserDTO>();
        results.forEach(({ id, user }) => {
          if (user) senderMap.set(id, user);
        });

        if (senderMap.size === 0) return;

        const current = this.state.messagesMap.get(conversationId);
        if (!current) return;

        let changed = false;
        const updated = current.map(m => {
          if (!m.sender && m.sender_id && senderMap.has(m.sender_id)) {
            changed = true;
            return { ...m, sender: senderMap.get(m.sender_id) };
          }
          return m;
        });

        if (!changed) return;

        this.state.messagesMap.set(conversationId, updated);
        this.notifySubscribers({
          type: 'messages_updated',
          payload: { conversationId, messages: [...updated] },
          timestamp: Date.now(),
        });
      })
      .catch(error => {
        console.error('[MessageManager] 批量获取 sender 信息失败:', error);
      });
  }

  /**
   * 获取用户信息（带缓存和去重）
   */
  private async getSenderInfo(userId: string): Promise<UserDTO | null> {
    // 1. 先检查本地缓存
    const cachedUser = await getUserCache(userId);
    if (cachedUser) {
      return cachedUser;
    }

    // 2. 检查是否已有正在进行的请求
    const pendingRequest = this.pendingUserRequests.get(userId);
    if (pendingRequest) {
      return pendingRequest;
    }

    // 3. 发起新请求
    const request = this.fetchUserInfo(userId);
    this.pendingUserRequests.set(userId, request);

    try {
      const user = await request;
      return user;
    } finally {
      // 请求完成后清理
      this.pendingUserRequests.delete(userId);
    }
  }

  /**
   * 从服务器获取用户信息
   */
  private async fetchUserInfo(userId: string): Promise<UserDTO | null> {
    try {
      const response = await api.get<UserDTO>(`/users/${userId}`);
      if (response.code === 0 && response.data) {
        // 缓存到本地数据库
        await saveUserCache(response.data);
        return response.data;
      }
      return null;
    } catch (error) {
      console.error(`[MessageManager] 获取用户信息失败: ${userId}`, error);
      return null;
    }
  }

  /**
   * 处理新消息（SSE推送）
   * 这是核心方法，必须立即处理并同步到所有订阅者
   */
  private async handleNewMessage(
    message: (WSChatMessage | WSGroupChatMessage) & { _isAck?: boolean },
    options?: {
      suppressUnreadIncrement?: boolean;
      suppressVibration?: boolean;
      suppressConversationUpdates?: boolean;
      suppressAutoMarkAsRead?: boolean;
    }
  ): Promise<void> {
    const { conversation_id, id, sender_id, seq, segments, created_at, _isAck } = message;
    const normalizedConversationId = this.normalizeConversationId(conversation_id);
    const currentUserId = this.getCurrentUserId();
    const suppressUnreadIncrement = options?.suppressUnreadIncrement ?? false;
    const suppressVibration = options?.suppressVibration ?? false;
    const suppressConversationUpdates = options?.suppressConversationUpdates ?? false;
    const suppressAutoMarkAsRead = options?.suppressAutoMarkAsRead ?? false;

    // 1. 消息去重检查 - 防止ACK消息和正常消息重复处理
    if (this.isMessageProcessed(id)) {
      return;
    }
    this.markMessageAsProcessed(id);

    // 2. 对于群聊消息，获取发送者信息（如果不是当前用户发送的）
    if (message.type === 'group_message' && sender_id && sender_id !== currentUserId && sender_id !== '10000') {
      // 异步获取发送者信息，不阻塞消息显示
      this.getSenderInfo(sender_id).then(user => {
        if (user) {
          // 更新消息对象中的发送者信息
          const messages = this.state.messagesMap.get(normalizedConversationId);
          if (messages) {
            // 创建新的数组和对象，确保React能检测到变化
            const updatedMessages = messages.map(m => 
              m.id === id ? { ...m, sender: user } : m
            );
            this.state.messagesMap.set(normalizedConversationId, updatedMessages);
            // 通知订阅者消息已更新
            this.notifySubscribers({
              type: 'messages_updated',
              payload: {
                conversationId: normalizedConversationId,
                messages: [...updatedMessages], // 创建新数组确保React检测到变化
              },
              timestamp: Date.now(),
            });
          }
        }
      }).catch(error => {
        console.error('[MessageManager][ERROR] 获取发送者信息失败:', { userId: sender_id, error });
      });
    }

    // 3. 构造消息对象
    const newMessage: MessageResponse = {
      id,
      conversation_id: normalizedConversationId,
      sender_id,
      seq,
      segments: segments || [],
      created_at,
      status: 'normal',
    };

    // 2. 立即更新内存中的消息列表（关键：确保ChatScreen能立即看到）
    const existingMessages = this.state.messagesMap.get(normalizedConversationId) || [];
    const messageExists = existingMessages.some(m => String(m.id) === String(id));

    if (!messageExists) {
      const updatedMessages = this.mergeMessagesById(existingMessages, [newMessage]);
      this.state.messagesMap.set(normalizedConversationId, updatedMessages);

      // 3. 立即通知订阅者（关键：解决竞态条件）
      this.notifySubscribers({
        type: 'messages_updated',
        payload: {
          conversationId: normalizedConversationId,
          messages: updatedMessages,
          newMessage,
        },
        timestamp: Date.now(),
      });
    }

    // 4. 更新会话信息（初始化缓冲刷新阶段可选择跳过，避免会话未读/排序竞态）
    if (!suppressConversationUpdates) {
      this.updateConversationWithNewMessage(normalizedConversationId, newMessage, created_at);
    }

    // 5. 更新未读数（如果不是当前用户发送且不是当前活动会话）
    const isCurrentUserMessage = sender_id === currentUserId;
    const isActiveConversation = normalizedConversationId === this.state.currentConversationId;

    const shouldIncrementUnread =
      !suppressUnreadIncrement &&
      !isCurrentUserMessage &&
      !isActiveConversation &&
      !!currentUserId &&
      !_isAck;
    
    if (shouldIncrementUnread) {
      if (!suppressVibration) {
        const vibrationType = message.type === 'group_message' ? 'group_message' : 'chat';
        vibrateOnMessage(vibrationType).catch(() => {});
      }
      this.incrementUnreadCount(normalizedConversationId);
    }

    // 6. 如果是当前活动会话，自动标记已读
    if (isActiveConversation && !isCurrentUserMessage && !suppressAutoMarkAsRead) {
      this.markAsRead(normalizedConversationId, seq);
    }

    // 7. 异步保存到本地数据库（不阻塞UI更新）
    const textContent = segments?.filter((s: any) => s.type === 'text').map((s: any) => s.data?.text || '').join('') || '';
    saveMessage({
      id,
      conversationId: normalizedConversationId,
      senderId: sender_id || '',
      content: textContent,
      type: segments?.find((s: any) => s.type === 'image') ? 'image' : 'text',
      isRead: isActiveConversation, // 如果是当前活动会话，标记为已读
      createdAt: new Date(created_at).toISOString(),
      seq,
      status: 'normal',
      segments,
    }).catch(error => {
      console.error('[MessageManager] 保存消息到本地失败:', error);
    });

    // 8. 通知收到新消息
    this.notifySubscribers({
      type: 'message_received',
      payload: {
        conversationId: conversation_id,
        message: newMessage,
        isCurrentUser: isCurrentUserMessage,
      },
      timestamp: Date.now(),
    });
  }

  /**
   * 更新会话的最后消息信息
   */
  private updateConversationWithNewMessage(
    conversationId: string,
    message: MessageResponse,
    createdAt: string
  ): void {
    const conversation = this.state.conversations.get(conversationId);

    if (conversation) {
      
      // 更新现有会话
      const updatedConv: ConversationResponse = {
        ...conversation,
        last_seq: message.seq,
        last_message: message,
        last_message_at: createdAt,
        updated_at: createdAt,
      };

      this.state.conversations.set(conversationId, updatedConv);
      
    } else {
      // 新会话，需要获取详情
      // 异步获取会话详情
      this.fetchConversationDetail(conversationId);
    }

    // 更新会话列表排序
    this.updateConversationList();

    // 通知会话列表更新
    this.notifySubscribers({
      type: 'conversations_updated',
      payload: { conversations: this.state.conversationList },
      timestamp: Date.now(),
    });
  }

  /**
   * 处理私聊已读回执
   */
  private handleReadReceipt(message: WSReadMessage): void {
    // 可以在这里处理对方已读的状态更新
  }

  /**
   * 处理群聊已读回执
   */
  private handleGroupReadReceipt(message: WSGroupReadMessage): void {
  }

  /**
   * 将指定消息标记为已撤回（保留占位，不删除）
   */
  private markMessageAsRecalled(conversationId: string, messageId: string): void {
    const normalizedConversationId = this.normalizeConversationId(conversationId);
    const messages = this.state.messagesMap.get(normalizedConversationId);
    if (!messages) {
      return;
    }

    let changed = false;
    const updatedMessages: MessageResponse[] = messages.map((m): MessageResponse => {
      if (String(m.id) !== String(messageId) || m.status === 'recalled') {
        return m;
      }
      changed = true;
      return {
        ...m,
        status: 'recalled' as MessageResponse['status'],
        segments: [],
      };
    });

    if (!changed) {
      return;
    }

    this.state.messagesMap.set(normalizedConversationId, updatedMessages);
    this.notifySubscribers({
      type: 'messages_updated',
      payload: { conversationId: normalizedConversationId, messages: updatedMessages },
      timestamp: Date.now(),
    });
  }

  /**
   * 如果撤回的是会话最后一条消息，同步会话列表中的 last_message 状态
   */
  private syncConversationLastMessageOnRecall(conversationId: string, messageId: string): void {
    const normalizedConversationId = this.normalizeConversationId(conversationId);
    const conversation = this.state.conversations.get(normalizedConversationId);
    if (!conversation?.last_message) {
      return;
    }
    if (String(conversation.last_message.id) !== String(messageId)) {
      return;
    }
    if (conversation.last_message.status === 'recalled') {
      return;
    }

    const updatedConversation: ConversationResponse = {
      ...conversation,
      last_message: {
        ...conversation.last_message,
        status: 'recalled',
      },
    };
    this.state.conversations.set(normalizedConversationId, updatedConversation);
    this.updateConversationList();
    this.notifySubscribers({
      type: 'conversations_updated',
      payload: { conversations: this.state.conversationList },
      timestamp: Date.now(),
    });
  }

  /**
   * 处理私聊消息撤回
   */
  private handleRecallMessage(message: WSRecallMessage): void {
    const { conversation_id, message_id } = message;
    const normalizedConversationId = this.normalizeConversationId(conversation_id);

    this.markMessageAsRecalled(normalizedConversationId, message_id);
    this.syncConversationLastMessageOnRecall(normalizedConversationId, message_id);

    // 通知订阅者消息被撤回
    this.notifySubscribers({
      type: 'message_recalled',
      payload: { conversationId: normalizedConversationId, messageId: message_id },
      timestamp: Date.now(),
    });

    // 同步本地数据库状态，避免冷启动后撤回占位丢失
    updateMessageStatus(message_id, 'recalled', true).catch(error => {
      console.error('[MessageManager] 更新本地消息撤回状态失败:', error);
    });
  }

  /**
   * 处理群聊消息撤回
   */
  private handleGroupRecallMessage(message: WSGroupRecallMessage): void {
    const { conversation_id, message_id } = message;
    const normalizedConversationId = this.normalizeConversationId(conversation_id);

    this.markMessageAsRecalled(normalizedConversationId, message_id);
    this.syncConversationLastMessageOnRecall(normalizedConversationId, message_id);

    // 通知订阅者消息被撤回
    this.notifySubscribers({
      type: 'message_recalled',
      payload: { conversationId: normalizedConversationId, messageId: message_id, isGroup: true },
      timestamp: Date.now(),
    });

    // 同步本地数据库状态，避免冷启动后撤回占位丢失
    updateMessageStatus(message_id, 'recalled', true).catch(error => {
      console.error('[MessageManager] 更新本地消息撤回状态失败:', error);
    });
  }

  /**
   * 处理群聊输入状态
   */
  private handleGroupTyping(message: WSGroupTypingMessage): void {
    const { group_id, user_id, is_typing } = message;
    const groupIdStr = String(group_id);

    const currentTypingUsers = this.state.typingUsersMap.get(groupIdStr) || [];
    let updatedTypingUsers: string[];

    if (is_typing) {
      // 添加用户到输入列表
      if (!currentTypingUsers.includes(user_id)) {
        updatedTypingUsers = [...currentTypingUsers, user_id];
      } else {
        updatedTypingUsers = currentTypingUsers;
      }
    } else {
      // 从输入列表移除用户
      updatedTypingUsers = currentTypingUsers.filter(id => id !== user_id);
    }

    // 只有变化时才更新
    if (updatedTypingUsers.length !== currentTypingUsers.length) {
      this.state.typingUsersMap.set(groupIdStr, updatedTypingUsers);
      this.notifySubscribers({
        type: 'typing_status',
        payload: { groupId: groupIdStr, typingUsers: updatedTypingUsers },
        timestamp: Date.now(),
      });
    }
  }

  /**
   * 处理群通知
   */
  private handleGroupNotice(message: WSGroupNoticeMessage): void {
    const { notice_type, group_id, data, timestamp, message_id, seq } = message;
    const groupIdStr = String(group_id);

    // 处理禁言/解除禁言通知 - 更新本地状态
    if (notice_type === 'muted' || notice_type === 'unmuted') {
      const mutedUserId = data?.user_id;
      const currentUserId = this.getCurrentUserId();

      // 如果是当前用户被禁言/解除禁言，更新状态
      if (mutedUserId && mutedUserId === currentUserId) {
        const isMuted = notice_type === 'muted';
        this.state.mutedStatusMap.set(groupIdStr, isMuted);
      }
    }

    // 对于携带 message_id/seq 的群通知，补一条系统消息到当前会话消息流
    // 这样 UI 会按系统通知样式渲染，而不是当作普通用户消息。
    if (message_id && typeof seq === 'number' && seq > 0) {
      const conversationId = this.findConversationIdByGroupId(groupIdStr);
      if (conversationId) {
        const existingMessages = this.state.messagesMap.get(conversationId) || [];
        const exists = existingMessages.some(m => String(m.id) === String(message_id));
        if (!exists) {
          const noticeText = this.buildGroupNoticeText(notice_type, data);
          const systemNoticeMessage: MessageResponse = {
            id: String(message_id),
            conversation_id: conversationId,
            sender_id: '10000',
            seq,
            segments: noticeText
              ? [{ type: 'text', data: { text: noticeText } as any }]
              : [],
            status: 'normal',
            category: 'notification',
            created_at: new Date(timestamp || Date.now()).toISOString(),
          };

          const updatedMessages = [...existingMessages, systemNoticeMessage].sort((a, b) => a.seq - b.seq);
          this.state.messagesMap.set(conversationId, updatedMessages);

          this.notifySubscribers({
            type: 'messages_updated',
            payload: {
              conversationId,
              messages: updatedMessages,
              newMessage: systemNoticeMessage,
              source: 'group_notice',
            },
            timestamp: Date.now(),
          });
        }
      }
    }

    // 通知订阅者群通知
    this.notifySubscribers({
      type: 'group_notice',
      payload: {
        groupId: groupIdStr,
        noticeType: notice_type,
        data,
        timestamp,
        messageId: message_id,
        seq,
      },
      timestamp: Date.now(),
    });
  }

  // ==================== 数据获取方法 ====================

  /**
   * 获取会话列表（首屏/下拉刷新：优先网络游标；可回退 SQLite，对 UI 透明）
   */
  async fetchConversations(forceRefresh = false, source: string = 'unknown'): Promise<void> {
    if (this.state.isLoadingConversations && !forceRefresh) {
      return;
    }

    if (this.shouldDeferConversationRefresh(source, forceRefresh)) {
      this.deferredConversationRefresh = true;
      if (__DEV__) {
        console.log('[MessageManager] defer fetchConversations', {
          source,
          activeConversationId: this.state.currentConversationId,
        });
      }
      return;
    }

    if (__DEV__) {
      console.log('[MessageManager] fetchConversations', {
        source,
        forceRefresh,
        activeConversationId: this.state.currentConversationId,
      });
    }

    // 非强制刷新且内存为空：先用本地源暖机，便于离线/弱网先展示列表
    if (!forceRefresh && this.state.conversations.size === 0) {
      const warmed = await this.hydrateConversationsFromLocalSource();
      if (warmed) {
        this.emitConversationListAndUnreadUpdates();
      }
    }

    this.state.isLoadingConversations = true;
    const emitLoadingToUi = this.state.conversationList.length === 0;
    if (emitLoadingToUi) {
      this.notifySubscribers({
        type: 'conversations_loading',
        payload: { loading: true },
        timestamp: Date.now(),
      });
    }

    try {
      this.remoteConversationListSource.restart();
      const page = await this.remoteConversationListSource.loadNext();

      this.state.conversations.clear();
      page.items.forEach(conv => this.applyConversationFromFetch(conv));

      this.updateConversationList();

      this.recomputeConversationTotalUnread();

      if (this.pendingReadMap.size > 0) {
        for (const convId of this.pendingReadMap.keys()) {
          updateConversationCacheUnreadCount(convId, 0).catch(error => {
            console.error('[MessageManager] 修复本地缓存未读数失败:', convId, error);
          });
        }
      }

      this.emitConversationListAndUnreadUpdates();
    } catch (error) {
      console.error('[MessageManager] 获取会话列表失败:', error);
      if (this.state.conversationList.length === 0) {
        const recovered = await this.hydrateConversationsFromLocalSource();
        if (recovered) {
          this.emitConversationListAndUnreadUpdates();
        }
      }
      this.notifySubscribers({
        type: 'error',
        payload: { error, context: 'fetchConversations' },
        timestamp: Date.now(),
      });
    } finally {
      this.state.isLoadingConversations = false;
      if (emitLoadingToUi) {
        this.notifySubscribers({
          type: 'conversations_loading',
          payload: { loading: false },
          timestamp: Date.now(),
        });
      }
    }
  }

  /**
   * 会话列表加载下一页（游标追加，不清空已有会话）
   */
  async loadMoreConversations(): Promise<void> {
    if (!this.remoteConversationListSource.hasMore) {
      return;
    }
    if (this.loadingMoreConversations || this.state.isLoadingConversations) {
      return;
    }

    this.loadingMoreConversations = true;
    try {
      const page = await this.remoteConversationListSource.loadNext();

      page.items.forEach(conv => this.applyConversationFromFetch(conv));

      this.updateConversationList();

      this.recomputeConversationTotalUnread();

      this.emitConversationListAndUnreadUpdates();
    } catch (error) {
      console.error('[MessageManager] 加载更多会话失败:', error);
      this.notifySubscribers({
        type: 'error',
        payload: { error, context: 'loadMoreConversations' },
        timestamp: Date.now(),
      });
    } finally {
      this.loadingMoreConversations = false;
    }
  }

  /**
   * 获取单个会话详情
   */
  async fetchConversationDetail(conversationId: string): Promise<ConversationResponse | null> {
    const normalizedId = this.normalizeConversationId(conversationId);
    try {
      const detail = await messageService.getConversationById(normalizedId);
      if (detail) {
        // 若此会话有进行中的已读请求或处于保护期内，保留 unread_count=0
        const readRecord = this.pendingReadMap.get(normalizedId);
        const isPending = !!readRecord;
        // 使用智能合并：如果服务器返回 unread_count > 0 但本地有更晚的已读记录，保留本地状态
        const shouldPreserveLocalRead = isPending && (detail.unread_count || 0) > 0;
        const safeDetail = this.normalizeConversationUnreadFromReadCursor(
          shouldPreserveLocalRead
            ? { ...(detail as ConversationResponse), id: normalizedId, unread_count: 0 }
            : { ...(detail as ConversationResponse), id: normalizedId }
        );
        this.state.conversations.set(normalizedId, safeDetail);
        this.updateConversationList();

        // getConversationById 内部会调用 saveConversationCache 写入服务器旧数据，
        // 若有 pending 已读请求或处于保护期内，需要修复本地缓存
        if (isPending) {
          updateConversationCacheUnreadCount(normalizedId, 0).catch(error => {
            console.error('[MessageManager] 修复本地缓存未读数失败:', normalizedId, error);
          });
        }

        this.notifySubscribers({
          type: 'conversations_updated',
          payload: { conversations: this.state.conversationList },
          timestamp: Date.now(),
        });
      }
      return detail as ConversationResponse;
    } catch (error) {
      console.error('[MessageManager] 获取会话详情失败:', error);
      return null;
    }
  }

  /**
   * 获取会话消息（增量同步）
   * 关键方法：确保消息立即显示，解决竞态条件
   */
  async fetchMessages(conversationId: string, afterSeq?: number): Promise<void> {
    // 防止重复加载
    if (this.state.loadingMessagesSet.has(conversationId)) {
      return;
    }

    this.state.loadingMessagesSet.add(conversationId);

    try {
      const mergeMessages = (base: MessageResponse[], incoming: MessageResponse[]): MessageResponse[] => {
        return this.mergeMessagesById(base, incoming);
      };
      const existingMessagesAtStart = this.state.messagesMap.get(conversationId) || [];
      const hasInMemoryMessages = existingMessagesAtStart.length > 0;
      let baselineMaxSeq = hasInMemoryMessages
        ? existingMessagesAtStart.reduce((max, m) => Math.max(max, m.seq || 0), 0)
        : 0;

      // 1. 先从本地数据库加载（确保立即有数据展示）
      if (!afterSeq) {
        let localMessages: any[] = [];
        let localMaxSeq = 0;
        if (!hasInMemoryMessages) {
          try {
            localMessages = await getMessagesByConversation(conversationId, 20);
            localMaxSeq = await getMaxSeq(conversationId);
            baselineMaxSeq = localMaxSeq;
          } catch (error) {
            // 架构原则：本地存储异常不阻断在线同步
            console.warn('[MessageManager] 读取本地消息失败，回退到服务端同步:', error);
          }
        }


        if (!hasInMemoryMessages && localMessages.length > 0) {
          // 转换格式
          const formattedMessages: MessageResponse[] = localMessages.map(m => ({
            id: m.id,
            conversation_id: m.conversationId,
            sender_id: m.senderId,
            seq: m.seq,
            segments: m.segments || [],
            status: m.status as any,
            created_at: m.createdAt,
          }));

          // 立即更新内存和通知（关键：解决竞态条件）
          this.state.messagesMap.set(conversationId, formattedMessages);
          this.notifySubscribers({
            type: 'messages_updated',
            payload: {
              conversationId,
              messages: formattedMessages,
              source: 'local',
            },
            timestamp: Date.now(),
          });
          // 异步填充 sender 信息
          this.enrichMessagesWithSenderInfo(conversationId, formattedMessages);
        } else if (!hasInMemoryMessages) {
          // 冷启动兜底：先下发空列表事件，避免 ChatScreen 长时间停留在 loading
          this.state.messagesMap.set(conversationId, []);
          this.notifySubscribers({
            type: 'messages_updated',
            payload: {
              conversationId,
              messages: [],
              source: 'local_empty',
            },
            timestamp: Date.now(),
          });

          // 再直接向服务端拉一页最新消息，不依赖 detail.last_seq，避免缓存 last_seq 过旧导致首屏空白
          try {
            const latestResponse = await messageService.getMessages(conversationId, undefined, undefined, 20);
            const latestMessages = latestResponse?.messages || [];
            if (latestMessages.length > 0) {
              const sortedLatestMessages = [...latestMessages].sort((a, b) => a.seq - b.seq);
              this.state.messagesMap.set(conversationId, sortedLatestMessages);
              this.notifySubscribers({
                type: 'messages_updated',
                payload: {
                  conversationId,
                  messages: sortedLatestMessages,
                  newMessages: sortedLatestMessages,
                  source: 'server_bootstrap',
                },
                timestamp: Date.now(),
              });
              this.enrichMessagesWithSenderInfo(conversationId, sortedLatestMessages);

              // 持久化是副作用，不阻断 UI
              saveMessagesBatch(latestMessages.map((m: any) => ({
                id: m.id,
                conversationId: m.conversation_id || conversationId,
                senderId: m.sender_id,
                content: m.content,
                type: m.type || 'text',
                isRead: m.is_read || false,
                createdAt: m.created_at,
                seq: m.seq,
                status: m.status || 'normal',
                segments: m.segments,
              }))).catch(error => {
                console.error('[MessageManager] 保存最新消息到本地失败:', error);
              });
            }
          } catch (error) {
            console.error('[MessageManager] 冷启动拉取最新消息失败:', error);
          }
        }

        // 2. 服务端快照 + 增量同步（架构修复：不再依赖 detail.last_seq 单点判断）
        try {
          // 2.1 总是先拉一页最新快照，确保 Chat 首次激活有权威来源
          const snapshotResp = await messageService.getMessages(conversationId, undefined, undefined, 50);
          const snapshotMessages = snapshotResp?.messages || [];
          if (snapshotMessages.length > 0) {
            const existingMessages = this.state.messagesMap.get(conversationId) || [];
            const mergedSnapshot = mergeMessages(existingMessages, snapshotMessages);
            this.state.messagesMap.set(conversationId, mergedSnapshot);
            this.notifySubscribers({
              type: 'messages_updated',
              payload: {
                conversationId,
                messages: mergedSnapshot,
                newMessages: snapshotMessages,
                source: 'server_snapshot',
              },
              timestamp: Date.now(),
            });
            this.enrichMessagesWithSenderInfo(conversationId, mergedSnapshot);
            saveMessagesBatch(snapshotMessages.map((m: any) => ({
              id: m.id,
              conversationId: m.conversation_id || conversationId,
              senderId: m.sender_id,
              content: m.content,
              type: m.type || 'text',
              isRead: m.is_read || false,
              createdAt: m.created_at,
              seq: m.seq,
              status: m.status || 'normal',
              segments: m.segments,
            }))).catch(error => {
              console.error('[MessageManager] 保存快照消息到本地失败:', error);
            });
          }

          // 2.2 再基于 localMaxSeq 做增量补齐（防止快照窗口不足导致漏更老的新消息）
          const snapshotMaxSeq = snapshotMessages.reduce((max, m) => Math.max(max, m.seq || 0), 0);
          if (snapshotMaxSeq > baselineMaxSeq) {
            const incrementalResp = await messageService.getMessages(conversationId, baselineMaxSeq);
            const newMessages = incrementalResp?.messages || [];
            if (newMessages.length > 0) {
              const existingMessages = this.state.messagesMap.get(conversationId) || [];
              const mergedMessages = mergeMessages(existingMessages, newMessages);
              this.state.messagesMap.set(conversationId, mergedMessages);
              this.notifySubscribers({
                type: 'messages_updated',
                payload: {
                  conversationId,
                  messages: mergedMessages,
                  newMessages,
                  source: 'server_incremental',
                },
                timestamp: Date.now(),
              });
              this.enrichMessagesWithSenderInfo(conversationId, mergedMessages);
              saveMessagesBatch(newMessages.map((m: any) => ({
                id: m.id,
                conversationId: m.conversation_id || conversationId,
                senderId: m.sender_id,
                content: m.content,
                type: m.type || 'text',
                isRead: m.is_read || false,
                createdAt: m.created_at,
                seq: m.seq,
                status: m.status || 'normal',
                segments: m.segments,
              }))).catch(error => {
                console.error('[MessageManager] 保存增量消息到本地失败:', error);
              });
            }
          }
        } catch (error) {
          console.error('[MessageManager] 快照/增量同步失败:', error);
        }
      } else {
        // 指定了afterSeq，直接请求服务端
        const response = await messageService.getMessages(conversationId, afterSeq);

        if (response?.messages && response.messages.length > 0) {
          const newMessages = response.messages;

          // 合并消息
          const existingMessages = this.state.messagesMap.get(conversationId) || [];
          const mergedMessages = mergeMessages(existingMessages, newMessages);

          this.state.messagesMap.set(conversationId, mergedMessages);
          this.notifySubscribers({
            type: 'messages_updated',
            payload: {
              conversationId,
              messages: mergedMessages,
              newMessages,
              source: 'server',
            },
            timestamp: Date.now(),
          });
          // 异步填充 sender 信息
          this.enrichMessagesWithSenderInfo(conversationId, mergedMessages);

          // 持久化是副作用，不阻断 UI
          saveMessagesBatch(newMessages.map((m: any) => ({
            id: m.id,
            conversationId: m.conversation_id || conversationId,
            senderId: m.sender_id,
            content: m.content,
            type: m.type || 'text',
            isRead: m.is_read || false,
            createdAt: m.created_at,
            seq: m.seq,
            status: m.status || 'normal',
            segments: m.segments,
          }))).catch(error => {
            console.error('[MessageManager] 保存 afterSeq 消息到本地失败:', error);
          });
        }
      }
    } catch (error) {
      console.error('[MessageManager] 获取消息失败:', error);
      this.notifySubscribers({
        type: 'error',
        payload: { error, context: 'fetchMessages', conversationId },
        timestamp: Date.now(),
      });
    } finally {
      this.state.loadingMessagesSet.delete(conversationId);
    }
  }

  /**
   * 加载更多历史消息
   */
  async loadMoreMessages(conversationId: string, beforeSeq: number, limit = 20): Promise<MessageResponse[]> {

    try {
      // 先从本地获取
      const localMessages = await getMessagesBeforeSeq(conversationId, beforeSeq, limit);

      if (localMessages.length >= limit) {
        // 本地有足够数据
        // 本地查询是 seq DESC，这里转成 ASC，匹配渲染时间序
        const formattedMessages: MessageResponse[] = [...localMessages].reverse().map(m => ({
          id: m.id,
          conversation_id: m.conversationId,
          sender_id: m.senderId,
          seq: m.seq,
          segments: m.segments || [],
          status: m.status as any,
          created_at: m.createdAt,
        }));

        // 合并到现有消息
        const existingMessages = this.state.messagesMap.get(conversationId) || [];
        const mergedMessages = this.mergeOlderMessages(existingMessages, formattedMessages);
        this.state.messagesMap.set(conversationId, mergedMessages);

        this.notifySubscribers({
          type: 'messages_updated',
          payload: { conversationId, messages: mergedMessages, source: 'local_history' },
          timestamp: Date.now(),
        });
        // 性能优化：历史分页仅对新批次做 sender 补全，避免每次扫描全量消息
        this.enrichMessagesWithSenderInfo(conversationId, formattedMessages);

        return formattedMessages;
      }

      // 本地数据不足，从服务端获取
      const response = await messageService.getMessages(conversationId, undefined, beforeSeq, limit);

      if (response?.messages && response.messages.length > 0) {
        const serverMessages = response.messages;

        // 保存到本地
        await saveMessagesBatch(serverMessages.map((m: any) => ({
          id: m.id,
          conversationId: m.conversation_id || conversationId,
          senderId: m.sender_id,
          content: m.content,
          type: m.type || 'text',
          isRead: m.is_read || false,
          createdAt: m.created_at,
          seq: m.seq,
          status: m.status || 'normal',
          segments: m.segments,
        })));

        // 合并消息
        const existingMessages = this.state.messagesMap.get(conversationId) || [];
        const mergedMessages = this.mergeOlderMessages(existingMessages, serverMessages);
        this.state.messagesMap.set(conversationId, mergedMessages);

        this.notifySubscribers({
          type: 'messages_updated',
          payload: { conversationId, messages: mergedMessages, source: 'server_history' },
          timestamp: Date.now(),
        });
        // 性能优化：仅对本次服务端批次做 sender 补全
        this.enrichMessagesWithSenderInfo(conversationId, serverMessages);

        return serverMessages;
      }

      return [];
    } catch (error) {
      console.error('[MessageManager] 加载更多消息失败:', error);
      return [];
    }
  }

  /**
   * 获取未读数
   */
  async fetchUnreadCount(): Promise<void> {
    try {
      const [unreadData, systemUnreadData] = await Promise.all([
        messageService.getUnreadCount(),
        messageService.getSystemUnreadCount(),
      ]);

      this.state.totalUnreadCount = unreadData?.total_unread_count ?? 0;
      this.state.systemUnreadCount = systemUnreadData?.unread_count ?? 0;

      // 服务端汇总未读为 0 时，清掉内存/本地缓存中残留的逐会话红点（常见于仅暖机了 SQLite 旧数据）
      if (this.state.totalUnreadCount === 0 && this.state.conversations.size > 0) {
        let anyCleared = false;
        for (const [cid, conv] of this.state.conversations) {
          if ((conv.unread_count || 0) > 0) {
            this.state.conversations.set(cid, { ...conv, unread_count: 0 });
            anyCleared = true;
          }
        }
        if (anyCleared) {
          this.updateConversationList();
          this.persistConversationListCache();
          this.notifySubscribers({
            type: 'conversations_updated',
            payload: { conversations: this.state.conversationList },
            timestamp: Date.now(),
          });
        }
      }

      this.notifySubscribers({
        type: 'unread_count_updated',
        payload: {
          totalUnreadCount: this.state.totalUnreadCount,
          systemUnreadCount: this.state.systemUnreadCount,
        },
        timestamp: Date.now(),
      });
    } catch (error) {
      console.error('[MessageManager] 获取未读数失败:', error);
    }
  }

  // ==================== 数据操作方法 ====================

  /**
   * 发送消息
   */
  async sendMessage(
    conversationId: string,
    segments: MessageSegment[],
    options?: { replyToId?: string }
  ): Promise<MessageResponse | null> {

    try {
      // 调用API发送
      const response = await messageService.sendMessage(conversationId, {
        segments,
        reply_to_id: options?.replyToId,
      });

      if (response) {
        // 添加到本地消息列表
        const existingMessages = this.state.messagesMap.get(conversationId) || [];
        const newMessage: MessageResponse = {
          id: response.id,
          conversation_id: conversationId,
          sender_id: this.getCurrentUserId() || '',
          seq: response.seq,
          segments,
          created_at: new Date().toISOString(),
          status: 'normal',
        };

        const updatedMessages = this.mergeMessagesById(existingMessages, [newMessage]);
        this.state.messagesMap.set(conversationId, updatedMessages);

        // 关键：立即广播消息列表更新，确保 ChatScreen 立刻显示新消息
        this.notifySubscribers({
          type: 'messages_updated',
          payload: {
            conversationId,
            messages: updatedMessages,
            newMessage,
            source: 'send',
          },
          timestamp: Date.now(),
        });

        // 更新会话
        this.updateConversationWithNewMessage(conversationId, newMessage, newMessage.created_at);

        // 通知
        this.notifySubscribers({
          type: 'message_sent',
          payload: { conversationId, message: newMessage },
          timestamp: Date.now(),
        });

        // 保存到本地数据库
        const textContent = segments?.filter((s: any) => s.type === 'text').map((s: any) => s.data?.text || '').join('') || '';
        saveMessage({
          id: response.id,
          conversationId,
          senderId: this.getCurrentUserId() || '',
          content: textContent,
          type: segments?.find((s: any) => s.type === 'image') ? 'image' : 'text',
          isRead: true,
          createdAt: newMessage.created_at,
          seq: response.seq,
          status: 'normal',
          segments,
        }).catch(console.error);

        return newMessage;
      }

      return null;
    } catch (error) {
      console.error('[MessageManager] 发送消息失败:', error);
      this.notifySubscribers({
        type: 'error',
        payload: { error, context: 'sendMessage' },
        timestamp: Date.now(),
      });
      return null;
    }
  }

  /**
   * 标记会话已读
   * 关键方法：确保已读状态在所有组件间同步
   * 
   * 修复：使用 pendingReadMap 和 readStateVersion 防止已读状态被旧数据覆盖
   * 1. 记录已读时间戳和版本号
   * 2. API 完成后延迟清除保护（5秒）
   * 3. fetchConversations 使用版本号判断数据新旧
   */
  async markAsRead(conversationId: string, seq: number): Promise<void> {
    const normalizedId = this.normalizeConversationId(conversationId);

    const conversation = this.state.conversations.get(normalizedId);
    if (!conversation) {
      console.warn('[MessageManager] 会话不存在:', normalizedId);
      return;
    }

    const prevUnreadCount = conversation.unread_count || 0;
    const existingRecord = this.pendingReadMap.get(normalizedId);

    // 使用 seq 去重：同一会话若已上报到更大/相同 seq，则跳过重复上报
    if (existingRecord && seq <= existingRecord.lastReadSeq) {
      return;
    }

    // 清除可能存在的旧定时器
    if (existingRecord?.clearTimer) {
      clearTimeout(existingRecord.clearTimer);
    }

    // 递增全局版本号
    this.readStateVersion++;
    const currentVersion = this.readStateVersion;

    // 1. 标记此会话有进行中的已读请求（防止 fetchConversations 覆盖乐观状态）
    // 记录时间戳和版本号，用于后续智能合并
    this.pendingReadMap.set(normalizedId, {
      timestamp: Date.now(),
      version: currentVersion,
      lastReadSeq: seq,
    });

    // 2. 乐观更新本地状态（立即反映到UI；同步已读游标避免与 last_seq 不一致）
    const updatedConv: ConversationResponse = {
      ...conversation,
      unread_count: 0,
      my_last_read_seq: Math.max(Number(conversation.my_last_read_seq || 0), seq),
    };
    this.state.conversations.set(normalizedId, updatedConv);
    this.state.totalUnreadCount = Math.max(0, this.state.totalUnreadCount - prevUnreadCount);
    this.updateConversationList();

    // 3. 更新本地数据库
    markConversationAsRead(normalizedId).catch(console.error);

    // 4. 立即通知所有订阅者
    this.notifySubscribers({
      type: 'message_read',
      payload: {
        conversationId: normalizedId,
        unreadCount: 0,
        totalUnreadCount: this.state.totalUnreadCount,
      },
      timestamp: Date.now(),
    });

    this.notifySubscribers({
      type: 'conversations_updated',
      payload: { conversations: this.state.conversationList },
      timestamp: Date.now(),
    });

    this.notifySubscribers({
      type: 'unread_count_updated',
      payload: {
        totalUnreadCount: this.state.totalUnreadCount,
        systemUnreadCount: this.state.systemUnreadCount,
      },
      timestamp: Date.now(),
    });

    // 5. 调用 API，完成后设置延迟清除保护
    try {
      await messageService.markAsRead(normalizedId, seq);
    } catch (error) {
      console.error('[MessageManager] 标记已读API失败:', error);
      // 失败时回滚状态
      this.state.conversations.set(normalizedId, conversation);
      this.state.totalUnreadCount += prevUnreadCount;
      this.updateConversationList();

      this.notifySubscribers({
        type: 'message_read',
        payload: {
          conversationId: normalizedId,
          unreadCount: prevUnreadCount,
          totalUnreadCount: this.state.totalUnreadCount,
        },
        timestamp: Date.now(),
      });
      // API 失败时立即清除保护，允许后续 fetch 恢复状态
      this.pendingReadMap.delete(normalizedId);
      return;
    }

    // API 成功后，设置延迟清除保护
    // 这确保在 API 完成后的一段时间内，fetchConversations 不会用服务器旧数据覆盖已读状态
    const clearTimer = setTimeout(() => {
      const record = this.pendingReadMap.get(normalizedId);
      // 只有版本号匹配时才清除（防止清除新的已读请求的保护）
      if (record && record.version === currentVersion) {
        this.pendingReadMap.delete(normalizedId);
      }
    }, READ_STATE_PROTECTION_DELAY);

    // 更新记录，保存定时器ID
    this.pendingReadMap.set(normalizedId, {
      timestamp: Date.now(),
      version: currentVersion,
      lastReadSeq: seq,
      clearTimer,
    });
  }

  /**
   * 标记所有消息已读
   */
  async markAllAsRead(): Promise<void> {

    // 乐观更新
    const prevConversations = new Map(this.state.conversations);
    const prevTotalUnread = this.state.totalUnreadCount;

    this.state.conversations.forEach(conv => {
      conv.unread_count = 0;
    });
    this.state.totalUnreadCount = 0;

    this.notifySubscribers({
      type: 'unread_count_updated',
      payload: {
        totalUnreadCount: 0,
        systemUnreadCount: this.state.systemUnreadCount,
      },
      timestamp: Date.now(),
    });

    this.notifySubscribers({
      type: 'conversations_updated',
      payload: { conversations: this.state.conversationList },
      timestamp: Date.now(),
    });

    try {
      // 标记系统消息已读
      await messageService.markAllSystemMessagesRead();

      // 标记所有会话已读
      const promises = Array.from(prevConversations.values())
        .filter(conv => (conv.unread_count || 0) > 0)
        .map(conv => messageService.markAsRead(conv.id, conv.last_seq));

      await Promise.all(promises);
    } catch (error) {
      console.error('[MessageManager] 标记所有已读失败:', error);
      // 回滚
      this.state.conversations = prevConversations;
      this.state.totalUnreadCount = prevTotalUnread;

      this.notifySubscribers({
        type: 'unread_count_updated',
        payload: {
          totalUnreadCount: prevTotalUnread,
          systemUnreadCount: this.state.systemUnreadCount,
        },
        timestamp: Date.now(),
      });
    }
  }

  /**
   * 创建私聊会话
   */
  async createConversation(userId: string): Promise<ConversationResponse | null> {

    try {
      const conversation = await messageService.createConversation(userId);

      // 添加到会话列表
      this.state.conversations.set(conversation.id, conversation);
      this.updateConversationList();

      // 通知更新
      this.notifySubscribers({
        type: 'conversations_updated',
        payload: { conversations: this.state.conversationList },
        timestamp: Date.now(),
      });

      return conversation;
    } catch (error) {
      console.error('[MessageManager] 创建会话失败:', error);
      this.notifySubscribers({
        type: 'error',
        payload: { error, context: 'createConversation' },
        timestamp: Date.now(),
      });
      return null;
    }
  }

  /**
   * 本地更新会话信息
   */
  updateConversation(conversationId: string, updates: Partial<ConversationResponse>): void {
    const conversation = this.state.conversations.get(conversationId);
    if (!conversation) {
      console.warn('[MessageManager] 更新会话失败，会话不存在:', conversationId);
      return;
    }

    const updatedConv: ConversationResponse = {
      ...conversation,
      ...updates,
    };

    this.state.conversations.set(conversationId, updatedConv);
    this.updateConversationList();

    // 通知更新
    this.notifySubscribers({
      type: 'conversations_updated',
      payload: { conversations: this.state.conversationList },
      timestamp: Date.now(),
    });
  }

  /**
   * 仅自己删除会话后的本地状态回收
   */
  removeConversation(conversationId: string): void {
    const normalizedConversationId = this.normalizeConversationId(conversationId);
    const target = this.state.conversations.get(normalizedConversationId);
    const removedUnread = target?.unread_count || 0;

    this.state.conversations.delete(normalizedConversationId);
    this.state.messagesMap.delete(normalizedConversationId);
    this.state.totalUnreadCount = Math.max(0, this.state.totalUnreadCount - removedUnread);
    if (this.state.currentConversationId === normalizedConversationId) {
      this.state.currentConversationId = null;
    }
    this.updateConversationList();

    this.notifySubscribers({
      type: 'conversations_updated',
      payload: { conversations: this.state.conversationList },
      timestamp: Date.now(),
    });

    this.notifySubscribers({
      type: 'unread_count_updated',
      payload: {
        totalUnreadCount: this.state.totalUnreadCount,
        systemUnreadCount: this.state.systemUnreadCount,
      },
      timestamp: Date.now(),
    });

    deleteConversationFromDb(normalizedConversationId).catch(error => {
      console.error('[MessageManager] 删除本地会话失败:', error);
    });
  }

  /**
   * 设置系统消息未读数
   */
  setSystemUnreadCount(count: number): void {
    this.state.systemUnreadCount = count;

    this.notifySubscribers({
      type: 'unread_count_updated',
      payload: {
        totalUnreadCount: this.state.totalUnreadCount,
        systemUnreadCount: this.state.systemUnreadCount,
      },
      timestamp: Date.now(),
    });
  }

  /**
   * 增加系统消息未读数
   */
  incrementSystemUnreadCount(): void {
    this.state.systemUnreadCount += 1;

    this.notifySubscribers({
      type: 'unread_count_updated',
      payload: {
        totalUnreadCount: this.state.totalUnreadCount,
        systemUnreadCount: this.state.systemUnreadCount,
      },
      timestamp: Date.now(),
    });
  }

  /**
   * 减少系统消息未读数
   */
  decrementSystemUnreadCount(count = 1): void {
    this.state.systemUnreadCount = Math.max(0, this.state.systemUnreadCount - count);

    this.notifySubscribers({
      type: 'unread_count_updated',
      payload: {
        totalUnreadCount: this.state.totalUnreadCount,
        systemUnreadCount: this.state.systemUnreadCount,
      },
      timestamp: Date.now(),
    });
  }

  /**
   * 更新单个会话未读数
   */
  updateUnreadCount(conversationId: string, count: number): void {
    const conversation = this.state.conversations.get(conversationId);
    if (!conversation) {
      console.warn('[MessageManager] 更新未读数失败，会话不存在:', conversationId);
      return;
    }

    const prevUnreadCount = conversation.unread_count || 0;
    const diff = count - prevUnreadCount;

    // 更新会话未读数
    const updatedConv: ConversationResponse = {
      ...conversation,
      unread_count: count,
    };
    this.state.conversations.set(conversationId, updatedConv);

    // 更新总未读数
    this.state.totalUnreadCount = Math.max(0, this.state.totalUnreadCount + diff);

    this.updateConversationList();

    // 通知更新
    this.notifySubscribers({
      type: 'unread_count_updated',
      payload: {
        totalUnreadCount: this.state.totalUnreadCount,
        systemUnreadCount: this.state.systemUnreadCount,
      },
      timestamp: Date.now(),
    });

    this.notifySubscribers({
      type: 'conversations_updated',
      payload: { conversations: this.state.conversationList },
      timestamp: Date.now(),
    });
  }

  /**
   * 清空会话列表
   */
  clearConversations(): void {
    this.state.conversations.clear();
    this.state.conversationList = [];
    this.state.totalUnreadCount = 0;
    this.state.systemUnreadCount = 0;

    this.notifySubscribers({
      type: 'conversations_updated',
      payload: { conversations: [] },
      timestamp: Date.now(),
    });

    this.notifySubscribers({
      type: 'unread_count_updated',
      payload: {
        totalUnreadCount: 0,
        systemUnreadCount: 0,
      },
      timestamp: Date.now(),
    });
  }

  /**
   * 使缓存失效（与旧版兼容的接口）
   * 实际 MessageManager 使用内存状态，此方法用于兼容性
   */
  invalidateCache(type: 'all' | 'list' | 'unread' = 'all'): void {
    // MessageManager 不使用外部缓存，内存状态始终是最新的
    // 此方法仅用于 API 兼容性
  }

  /**
   * 增加未读数
   */
  private incrementUnreadCount(conversationId: string): void {
    const conversation = this.state.conversations.get(conversationId);
    if (conversation) {
      const prevUnreadCount = conversation.unread_count || 0;
      const newUnreadCount = prevUnreadCount + 1;
      
      
      // 创建新对象而不是直接修改，确保状态一致性
      const updatedConv: ConversationResponse = {
        ...conversation,
        unread_count: newUnreadCount,
      };
      this.state.conversations.set(conversationId, updatedConv);
      this.state.totalUnreadCount += 1;

      // 更新会话列表排序（因为unread_count变化了）
      this.updateConversationList();

      this.notifySubscribers({
        type: 'unread_count_updated',
        payload: {
          totalUnreadCount: this.state.totalUnreadCount,
          systemUnreadCount: this.state.systemUnreadCount,
        },
        timestamp: Date.now(),
      });

      this.notifySubscribers({
        type: 'conversations_updated',
        payload: { conversations: this.state.conversationList },
        timestamp: Date.now(),
      });
    }
  }

  // ==================== 状态查询方法 ====================

  /**
   * 会话列表是否还能加载更多（由数据源响应推导，不暴露游标本身）
   */
  canLoadMoreConversations(): boolean {
    return this.remoteConversationListSource.hasMore;
  }

  /**
   * 获取会话列表
   */
  getConversations(): ConversationResponse[] {
    return this.state.conversationList;
  }

  /**
   * 获取指定会话
   */
  getConversation(conversationId: string): ConversationResponse | null {
    const normalizedConversationId = this.normalizeConversationId(conversationId);
    return this.state.conversations.get(normalizedConversationId) || null;
  }

  /**
   * 获取指定会话的消息
   */
  getMessages(conversationId: string): MessageResponse[] {
    const normalizedConversationId = this.normalizeConversationId(conversationId);
    return this.state.messagesMap.get(normalizedConversationId) || [];
  }

  /**
   * 获取总未读数
   */
  getUnreadCount(): { total: number; system: number } {
    return {
      total: this.state.totalUnreadCount,
      system: this.state.systemUnreadCount,
    };
  }

  /**
   * 获取SSE连接状态
   */
  isConnected(): boolean {
    return this.state.isSSEConnected;
  }

  /**
   * 获取加载状态
   */
  isLoading(): boolean {
    return this.state.isLoadingConversations;
  }

  /**
   * 获取会话消息加载状态
   */
  isLoadingMessages(conversationId: string): boolean {
    const normalizedConversationId = this.normalizeConversationId(conversationId);
    return this.state.loadingMessagesSet.has(normalizedConversationId);
  }

  // ==================== 活动会话管理 ====================

  /**
   * 设置当前活动会话（进入聊天页面时调用）
   */
  setActiveConversation(conversationId: string | null): void {
    const normalizedConversationId = conversationId ? this.normalizeConversationId(conversationId) : null;
    this.state.currentConversationId = normalizedConversationId;
    if (!normalizedConversationId && this.deferredConversationRefresh) {
      this.deferredConversationRefresh = false;
      this.requestConversationListRefresh('deferred-after-chat', { force: true, allowDefer: false }).catch(error => {
        console.error('[MessageManager] 延迟会话刷新失败:', error);
      });
    }
  }

  /**
   * 激活会话（架构入口）
   * 单一职责：设置活动会话 + 保证初始化 + 串行同步该会话消息
   */
  async activateConversation(conversationId: string, options?: { forceSync?: boolean }): Promise<void> {
    const normalizedConversationId = this.normalizeConversationId(conversationId);
    if (!normalizedConversationId) return;

    await this.initialize();
    this.setActiveConversation(normalizedConversationId);

    // 先下发当前内存快照，确保 UI 有确定性起点
    const snapshot = this.getMessages(normalizedConversationId);
    this.notifySubscribers({
      type: 'messages_updated',
      payload: {
        conversationId: normalizedConversationId,
        messages: [...snapshot],
        source: 'activation_snapshot',
      },
      timestamp: Date.now(),
    });

    const existingTask = this.activatingConversationTasks.get(normalizedConversationId);
    if (existingTask && !options?.forceSync) {
      await existingTask;
      return;
    }

    const task = (async () => {
      await this.fetchMessages(normalizedConversationId);
    })();
    this.activatingConversationTasks.set(normalizedConversationId, task);

    try {
      await task;
    } finally {
      if (this.activatingConversationTasks.get(normalizedConversationId) === task) {
        this.activatingConversationTasks.delete(normalizedConversationId);
      }
    }
  }

  /**
   * 获取当前活动会话ID
   */
  getActiveConversation(): string | null {
    return this.state.currentConversationId;
  }

  // ==================== 订阅机制 ====================

  /**
   * 订阅消息事件
   * 返回取消订阅函数
   */
  subscribe(subscriber: MessageSubscriber): () => void {
    this.state.subscribers.add(subscriber);

    // 立即发送当前状态给新订阅者
    subscriber({
      type: 'conversations_updated',
      payload: { conversations: this.state.conversationList },
      timestamp: Date.now(),
    });

    subscriber({
      type: 'unread_count_updated',
      payload: {
        totalUnreadCount: this.state.totalUnreadCount,
        systemUnreadCount: this.state.systemUnreadCount,
      },
      timestamp: Date.now(),
    });

    subscriber({
      type: 'connection_changed',
      payload: { connected: this.state.isSSEConnected },
      timestamp: Date.now(),
    });

    // 【修复】如果当前有活动会话，立即发送该会话的消息给新订阅者
    // 这样新订阅者可以立即获取当前消息状态，而不需要等待下一次更新
    if (this.state.currentConversationId) {
      const currentMessages = this.state.messagesMap.get(this.state.currentConversationId);
      if (currentMessages && currentMessages.length > 0) {
        subscriber({
          type: 'messages_updated',
          payload: {
            conversationId: this.state.currentConversationId,
            messages: [...currentMessages],
            source: 'initial_sync',
          },
          timestamp: Date.now(),
        });
      }
    }

    // 返回取消订阅函数
    return () => {
      this.state.subscribers.delete(subscriber);
    };
  }

  /**
   * 订阅特定会话的消息更新
   */
  subscribeToMessages(conversationId: string, callback: (messages: MessageResponse[]) => void): () => void {
    const subscriber: MessageSubscriber = (event) => {
      if (event.type === 'messages_updated' && event.payload.conversationId === conversationId) {
        callback(event.payload.messages);
      }
    };

    return this.subscribe(subscriber);
  }

  // ==================== 群聊相关状态查询 ====================

  /**
   * 获取群组的输入状态
   */
  getTypingUsers(groupId: string): string[] {
    return this.state.typingUsersMap.get(groupId) || [];
  }

  /**
   * 获取群组的禁言状态
   */
  isMuted(groupId: string): boolean {
    return this.state.mutedStatusMap.get(groupId) || false;
  }

  /**
   * 设置群组的禁言状态（本地）
   */
  setMutedStatus(groupId: string, isMuted: boolean): void {
    this.state.mutedStatusMap.set(groupId, isMuted);
  }
}

// ==================== 单例导出 ====================

export const messageManager = new MessageManager();

// 默认导出
export default messageManager;
