/**
 * 消息状态管理器
 * 只负责管理状态，不包含业务逻辑
 */

import type { Message, Conversation, UnreadCount } from '../../core/entities/Message';

export type MessageEventType =
  | 'conversations_updated'
  | '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;

export interface MessageState {
  conversations: Map<string, Conversation>;
  conversationList: Conversation[];
  messagesMap: Map<string, Message[]>;
  unreadCount: UnreadCount;
  isSSEConnected: boolean;
  currentConversationId: string | null;
  isLoading: boolean;
  typingUsersMap: Map<string, string[]>;
  mutedStatusMap: Map<string, boolean>;
}

export class MessageStateManager {
  private state: MessageState;
  private subscribers: Set<MessageSubscriber>;
  private readStateVersion: number = 0;
  private pendingReadMap: Map<string, { timestamp: number; version: number }> = new Map();

  constructor() {
    this.state = {
      conversations: new Map(),
      conversationList: [],
      messagesMap: new Map(),
      unreadCount: { total: 0, system: 0 },
      isSSEConnected: false,
      currentConversationId: null,
      isLoading: false,
      typingUsersMap: new Map(),
      mutedStatusMap: new Map(),
    };
    this.subscribers = new Set();
  }

  // ==================== 状态获取 ====================

  getState(): MessageState {
    return this.state;
  }

  getConversations(): Conversation[] {
    return this.state.conversationList;
  }

  getConversation(id: string): Conversation | undefined {
    return this.state.conversations.get(id);
  }

  getMessages(conversationId: string): Message[] {
    return this.state.messagesMap.get(conversationId) || [];
  }

  getUnreadCount(): UnreadCount {
    return this.state.unreadCount;
  }

  getCurrentConversationId(): string | null {
    return this.state.currentConversationId;
  }

  isConnected(): boolean {
    return this.state.isSSEConnected;
  }

  getTypingUsers(groupId: string): string[] {
    return this.state.typingUsersMap.get(groupId) || [];
  }

  getMutedStatus(groupId: string): boolean {
    return this.state.mutedStatusMap.get(groupId) || false;
  }

  // ==================== 状态更新 ====================

  setConversations(conversations: Conversation[]): void {
    this.state.conversations.clear();
    this.state.conversationList = conversations;
    
    for (const conv of conversations) {
      this.state.conversations.set(conv.id, conv);
    }
    
    this.updateUnreadCount();
    this.notify({ type: 'conversations_updated', payload: conversations });
  }

  addConversation(conversation: Conversation): void {
    this.state.conversations.set(conversation.id, conversation);
    this.state.conversationList = Array.from(this.state.conversations.values());
    this.updateUnreadCount();
    this.notify({ type: 'conversations_updated', payload: this.state.conversationList });
  }

  updateConversation(id: string, updates: Partial<Conversation>): void {
    const existing = this.state.conversations.get(id);
    if (existing) {
      const updated = { ...existing, ...updates };
      this.state.conversations.set(id, updated);
      this.state.conversationList = Array.from(this.state.conversations.values());
      this.updateUnreadCount();
      this.notify({ type: 'conversations_updated', payload: this.state.conversationList });
    }
  }

  removeConversation(id: string): void {
    this.state.conversations.delete(id);
    this.state.messagesMap.delete(id);
    this.state.conversationList = Array.from(this.state.conversations.values());
    this.updateUnreadCount();
    this.notify({ type: 'conversations_updated', payload: this.state.conversationList });
  }

  setMessages(conversationId: string, messages: Message[]): void {
    this.state.messagesMap.set(conversationId, messages);
    this.notify({ type: 'messages_updated', payload: { conversationId, messages } });
  }

  addMessage(conversationId: string, message: Message): void {
    const messages = this.state.messagesMap.get(conversationId) || [];
    const existingIndex = messages.findIndex(m => m.id === message.id);
    
    if (existingIndex >= 0) {
      messages[existingIndex] = message;
    } else {
      messages.push(message);
    }
    
    this.state.messagesMap.set(conversationId, messages);
    this.notify({ type: 'messages_updated', payload: { conversationId, messages } });
  }

  prependMessages(conversationId: string, newMessages: Message[]): void {
    const existing = this.state.messagesMap.get(conversationId) || [];
    const merged = [...newMessages, ...existing];
    const unique = this.deduplicateMessages(merged);
    this.state.messagesMap.set(conversationId, unique);
    this.notify({ type: 'messages_updated', payload: { conversationId, messages: unique } });
  }

  appendMessages(conversationId: string, newMessages: Message[]): void {
    const existing = this.state.messagesMap.get(conversationId) || [];
    const merged = [...existing, ...newMessages];
    const unique = this.deduplicateMessages(merged);
    this.state.messagesMap.set(conversationId, unique);
    this.notify({ type: 'messages_updated', payload: { conversationId, messages: unique } });
  }

  updateMessage(conversationId: string, messageId: string, updates: Partial<Message>): void {
    const messages = this.state.messagesMap.get(conversationId);
    if (!messages) return;

    const index = messages.findIndex(m => m.id === messageId);
    if (index >= 0) {
      messages[index] = { ...messages[index], ...updates };
      this.notify({ type: 'messages_updated', payload: { conversationId, messages } });
    }
  }

  setUnreadCount(count: UnreadCount): void {
    this.state.unreadCount = count;
    this.notify({ type: 'unread_count_updated', payload: count });
  }

  setSSEConnected(connected: boolean): void {
    this.state.isSSEConnected = connected;
    this.notify({ type: 'connection_changed', payload: connected });
  }

  setCurrentConversation(id: string | null): void {
    this.state.currentConversationId = id;
  }

  setLoading(loading: boolean): void {
    this.state.isLoading = loading;
  }

  setTypingUsers(groupId: string, userIds: string[]): void {
    this.state.typingUsersMap.set(groupId, userIds);
    this.notify({ type: 'typing_status', payload: { groupId, userIds } });
  }

  setMutedStatus(groupId: string, muted: boolean): void {
    this.state.mutedStatusMap.set(groupId, muted);
  }

  // ==================== 已读状态保护 ====================

  beginReadOperation(conversationId: string): number {
    this.readStateVersion++;
    this.pendingReadMap.set(conversationId, {
      timestamp: Date.now(),
      version: this.readStateVersion,
    });
    return this.readStateVersion;
  }

  endReadOperation(conversationId: string): void {
    setTimeout(() => {
      this.pendingReadMap.delete(conversationId);
    }, 5000);
  }

  isReadOperationPending(conversationId: string): boolean {
    const record = this.pendingReadMap.get(conversationId);
    if (!record) return false;
    return Date.now() - record.timestamp < 5000;
  }

  getReadStateVersion(): number {
    return this.readStateVersion;
  }

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

  subscribe(callback: MessageSubscriber): () => void {
    this.subscribers.add(callback);
    return () => this.subscribers.delete(callback);
  }

  private notify(event: Omit<MessageEvent, 'timestamp'>): void {
    const fullEvent: MessageEvent = {
      ...event,
      timestamp: Date.now(),
    };
    this.subscribers.forEach(callback => {
      try {
        callback(fullEvent);
      } catch (error) {
        console.error('[MessageStateManager] Subscriber error:', error);
      }
    });
  }

  // ==================== 工具方法 ====================

  private updateUnreadCount(): void {
    let total = 0;
    let system = 0;
    
    for (const conv of this.state.conversations.values()) {
      total += conv.unreadCount || 0;
    }
    
    this.state.unreadCount = { total, system };
    this.notify({ type: 'unread_count_updated', payload: this.state.unreadCount });
  }

  private deduplicateMessages(messages: Message[]): Message[] {
    const seen = new Set<string>();
    return messages.filter(msg => {
      if (seen.has(msg.id)) return false;
      seen.add(msg.id);
      return true;
    });
  }

  reset(): void {
    this.state = {
      conversations: new Map(),
      conversationList: [],
      messagesMap: new Map(),
      unreadCount: { total: 0, system: 0 },
      isSSEConnected: false,
      currentConversationId: null,
      isLoading: false,
      typingUsersMap: new Map(),
      mutedStatusMap: new Map(),
    };
    this.pendingReadMap.clear();
    this.readStateVersion = 0;
  }
}

export const messageStateManager = new MessageStateManager();