/**
 * 消息同步服务
 * 负责从服务器同步消息和会话
 */

import { messageService } from '../../services/messageService';
import { messageRepository } from '../../data/repositories/MessageRepository';
import type { Message, Conversation } from '../../core/entities/Message';
import type { ConversationListResponse, MessageListResponse } from '../../types/dto';

export interface SyncOptions {
  force?: boolean;
  lastSeq?: number;
}

export interface SyncResult {
  conversations: Conversation[];
  messages: Message[];
  hasMore: boolean;
}

export class MessageSyncService {
  private syncingConversations: boolean = false;
  private syncingMessages: Map<string, boolean> = new Map();

  async syncConversations(): Promise<Conversation[]> {
    if (this.syncingConversations) {
      console.log('[MessageSyncService] Already syncing conversations');
      return [];
    }

    this.syncingConversations = true;

    try {
      const response: ConversationListResponse = await messageService.getConversations();
      const conversations = this.mapConversations(response.list || []);
      return conversations;
    } catch (error) {
      console.error('[MessageSyncService] Failed to sync conversations:', error);
      throw error;
    } finally {
      this.syncingConversations = false;
    }
  }

  async syncMessages(
    conversationId: string,
    options: SyncOptions = {}
  ): Promise<SyncResult> {
    const key = conversationId;
    
    if (this.syncingMessages.get(key)) {
      console.log('[MessageSyncService] Already syncing messages for:', conversationId);
      return { conversations: [], messages: [], hasMore: false };
    }

    this.syncingMessages.set(key, true);

    try {
      const lastSeq = options.lastSeq ?? await messageRepository.getMaxSeq(conversationId);
      
      const response: MessageListResponse = await messageService.getMessages(
        conversationId,
        lastSeq,
        undefined,
        50
      );

      const messages = this.mapMessages(response.messages || []);
      
      if (messages.length > 0) {
        await messageRepository.saveMessages(messages, true);
      }

      return {
        conversations: [],
        messages,
        hasMore: messages.length >= 50,
      };
    } catch (error) {
      console.error('[MessageSyncService] Failed to sync messages:', error);
      throw error;
    } finally {
      this.syncingMessages.delete(key);
    }
  }

  async loadHistoryMessages(
    conversationId: string,
    beforeSeq: number,
    limit: number = 20
  ): Promise<Message[]> {
    try {
      const response: MessageListResponse = await messageService.getMessages(
        conversationId,
        undefined,
        beforeSeq,
        limit
      );

      const messages = this.mapMessages(response.messages || []);
      
      if (messages.length > 0) {
        await messageRepository.saveMessages(messages, true);
      }

      return messages;
    } catch (error) {
      console.error('[MessageSyncService] Failed to load history:', error);
      throw error;
    }
  }

  async loadLocalMessages(
    conversationId: string,
    limit: number = 50
  ): Promise<Message[]> {
    return messageRepository.getMessagesByConversation(conversationId, limit);
  }

  async loadHistoryFromLocal(
    conversationId: string,
    beforeSeq: number,
    limit: number = 20
  ): Promise<Message[]> {
    return messageRepository.getMessagesBeforeSeq(conversationId, beforeSeq, limit);
  }

  private mapConversations(list: ConversationListResponse['list']): Conversation[] {
    return list.map(conv => ({
      id: conv.id,
      type: conv.type || 'private',
      isPinned: conv.is_pinned || false,
      lastSeq: conv.last_seq || 0,
      lastMessageAt: conv.last_message_at || new Date().toISOString(),
      unreadCount: conv.unread_count || 0,
      participants: (conv.participants || []).map(p => ({
        id: p.id,
        username: p.username,
        avatar: p.avatar || undefined,
        nickname: p.nickname,
      })),
      group: conv.group ? {
        id: String(conv.group.id),
        name: conv.group.name,
        avatar: conv.group.avatar,
      } : undefined,
      createdAt: conv.created_at || new Date().toISOString(),
      updatedAt: conv.updated_at || new Date().toISOString(),
    }));
  }

  private mapMessages(messages: MessageListResponse['messages']): Message[] {
    return messages.map(msg => ({
      id: msg.id,
      conversationId: msg.conversation_id,
      senderId: msg.sender_id,
      seq: msg.seq,
      segments: msg.segments || [],
      createdAt: msg.created_at,
      status: msg.status || 'normal',
      sender: msg.sender ? {
        id: msg.sender.id,
        username: msg.sender.username,
        avatar: msg.sender.avatar || undefined,
        nickname: msg.sender.nickname,
      } : undefined,
    }));
  }

  isSyncingConversations(): boolean {
    return this.syncingConversations;
  }

  isSyncingMessages(conversationId: string): boolean {
    return this.syncingMessages.get(conversationId) || false;
  }
}

export const messageSyncService = new MessageSyncService();