/**
 * MessageManager - 重构版
 * 作为协调者，整合各个专注的服务模块
 */

import { messageStateManager, MessageStateManager } from './MessageStateManager';
import { sseMessageHandler, SSEMessageHandler } from './SSEMessageHandler';
import { messageSyncService, MessageSyncService } from './MessageSyncService';
import { readReceiptManager, ReadReceiptManager } from './ReadReceiptManager';
import { messageRepository } from '../../data/repositories/MessageRepository';
import { useAuthStore } from '../authStore';
import type { Message, Conversation } from '../../core/entities/Message';
import type { ConversationResponse, MessageResponse } from '../../types/dto';

export type {
  MessageEventType,
  MessageEvent,
  MessageSubscriber,
} from './MessageStateManager';

export class MessageManager {
  private stateManager: MessageStateManager;
  private sseHandler: SSEMessageHandler;
  private syncService: MessageSyncService;
  private readManager: ReadReceiptManager;

  private initialized: boolean = false;
  private authUnsubscribe: (() => void) | null = null;
  private sseUnsubscribe: (() => void) | null = null;
  private currentUserId: string | null = null;

  constructor() {
    this.stateManager = messageStateManager;
    this.sseHandler = sseMessageHandler;
    this.syncService = messageSyncService;
    this.readManager = readReceiptManager;

    this.readManager.setStateManager(this.stateManager);
    this.setupSSEHandlers();
    this.initAuthListener();
  }

  private initAuthListener(): void {
    const authState = useAuthStore.getState();
    this.currentUserId = authState.currentUser?.id || null;

    if (this.currentUserId && !this.initialized) {
      this.initialize();
    }

    this.authUnsubscribe = useAuthStore.subscribe((state) => {
      const nextUserId = state.currentUser?.id || null;
      this.currentUserId = nextUserId;

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

  private setupSSEHandlers(): void {
    this.sseUnsubscribe = this.sseHandler.subscribe((event) => {
      switch (event.type) {
        case 'chat_message':
        case 'group_message':
          this.handleNewMessage(event.payload);
          break;
        case 'read_receipt':
        case 'group_read_receipt':
          this.handleReadReceipt(event.payload);
          break;
        case 'message_recalled':
        case 'group_message_recalled':
          this.handleMessageRecall(event.payload);
          break;
        case 'typing':
          this.handleTypingStatus(event.payload);
          break;
        case 'group_notice':
          this.handleGroupNotice(event.payload);
          break;
      }
    });
  }

  async initialize(): Promise<void> {
    if (this.initialized) return;

    try {
      console.log('[MessageManager] Initializing...');

      this.sseHandler.connect();

      const conversations = await this.syncService.syncConversations();
      this.stateManager.setConversations(conversations);

      this.initialized = true;
      console.log('[MessageManager] Initialized successfully');
    } catch (error) {
      console.error('[MessageManager] Initialization failed:', error);
      throw error;
    }
  }

  async activateConversation(conversationId: string): Promise<void> {
    this.stateManager.setCurrentConversation(conversationId);

    const existing = this.stateManager.getMessages(conversationId);
    if (existing.length === 0) {
      await this.loadMessages(conversationId);
    }

    const conversation = this.stateManager.getConversation(conversationId);
    if (conversation && conversation.unreadCount > 0) {
      await this.readManager.markAsRead(conversationId, conversation.lastSeq);
    }
  }

  deactivateConversation(): void {
    this.stateManager.setCurrentConversation(null);
  }

  async loadMessages(conversationId: string): Promise<Message[]> {
    const localMessages = await this.syncService.loadLocalMessages(conversationId);
    
    if (localMessages.length > 0) {
      this.stateManager.setMessages(conversationId, localMessages);
    }

    const syncResult = await this.syncService.syncMessages(conversationId);
    
    if (syncResult.messages.length > 0) {
      this.stateManager.appendMessages(conversationId, syncResult.messages);
      return [...localMessages, ...syncResult.messages];
    }

    return localMessages;
  }

  async loadHistory(conversationId: string): Promise<Message[]> {
    const messages = this.stateManager.getMessages(conversationId);
    const oldestSeq = messages.length > 0 ? Math.min(...messages.map(m => m.seq)) : 0;

    const history = await this.syncService.loadHistoryMessages(
      conversationId,
      oldestSeq,
      20
    );

    if (history.length > 0) {
      this.stateManager.prependMessages(conversationId, history);
    }

    return history;
  }

  async sendMessage(
    conversationId: string,
    content: string,
    type: 'private' | 'group' = 'private'
  ): Promise<Message> {
    throw new Error('sendMessage not implemented - use existing implementation');
  }

  private async handleNewMessage(message: Message): Promise<void> {
    await messageRepository.saveMessage(message, true);

    this.stateManager.addMessage(message.conversationId, message);

    const currentConvId = this.stateManager.getCurrentConversationId();
    if (currentConvId !== message.conversationId) {
      const conv = this.stateManager.getConversation(message.conversationId);
      if (conv) {
        this.stateManager.updateConversation(message.conversationId, {
          unreadCount: (conv.unreadCount || 0) + 1,
          lastSeq: message.seq,
          lastMessageAt: message.createdAt,
        });
      }
    }
  }

  private handleReadReceipt(payload: any): void {
    const { conversationId, lastReadSeq } = payload;
    
    this.stateManager.updateConversation(conversationId, {
      unreadCount: 0,
    });
  }

  private async handleMessageRecall(payload: any): Promise<void> {
    const { messageId, conversationId } = payload;

    await messageRepository.updateMessageStatus(messageId, 'recalled', true);

    this.stateManager.updateMessage(conversationId, messageId, {
      status: 'recalled',
    });
  }

  private handleTypingStatus(payload: any): void {
    const { groupId, userIds } = payload;
    this.stateManager.setTypingUsers(groupId, userIds);
  }

  private handleGroupNotice(notice: any): void {
    console.log('[MessageManager] Group notice:', notice);
  }

  subscribe(callback: any): () => void {
    return this.stateManager.subscribe(callback);
  }

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

  getMessages(conversationId: string): Message[] {
    return this.stateManager.getMessages(conversationId);
  }

  getUnreadCount(): { total: number; system: number } {
    return this.stateManager.getUnreadCount();
  }

  isConnected(): boolean {
    return this.sseHandler.isConnected();
  }

  reset(): void {
    this.initialized = false;
    this.stateManager.reset();
    this.readManager.reset();
    this.sseHandler.disconnect();
  }

  destroy(): void {
    if (this.authUnsubscribe) {
      this.authUnsubscribe();
      this.authUnsubscribe = null;
    }
    if (this.sseUnsubscribe) {
      this.sseUnsubscribe();
      this.sseUnsubscribe = null;
    }
    this.reset();
  }
}

export const messageManager = new MessageManager();
export default messageManager;