# Lắng Nghe Sự Kiện (Event Listener)

## Tổng Quan

SDK cung cấp hệ thống listener mạnh mẽ để lắng nghe các sự kiện real-time:
- Tin nhắn mới
- Sự kiện nhóm (thêm/xóa thành viên, đổi tên, v.v.)
- Sự kiện bạn bè (kết bạn, unfriend)
- Reaction, typing, seen, delivered
- Undo actions

## Khởi Tạo Listener

### 1. Cấu Hình Cơ Bản

```typescript
import { Zalo, CloseReason } from 'zalo-personal-sdk';

// Khởi tạo với selfListen để nghe tin nhắn của chính mình
const zalo = new Zalo({ selfListen: true });
const api = await zalo.login(credentials);

// Bắt đầu lắng nghe
await api.listener.start();
console.log('🎧 Listener đã khởi động!');
```

### 2. Xử Lý Kết Nối

```typescript
// Sự kiện kết nối
api.listener.on('connect', () => {
  console.log('✅ Đã kết nối listener');
});

// Sự kiện mất kết nối
api.listener.on('disconnect', (reason: CloseReason) => {
  console.log('❌ Mất kết nối:', reason);
  
  switch (reason) {
    case CloseReason.Normal:
      console.log('Ngắt kết nối bình thường');
      break;
    case CloseReason.Error:
      console.log('Lỗi kết nối');
      break;
    case CloseReason.Reconnect:
      console.log('Đang reconnect...');
      break;
  }
});

// Sự kiện lỗi
api.listener.on('error', (error) => {
  console.error('🚨 Listener error:', error);
});
```

### 3. Dừng Listener

```typescript
// Dừng lắng nghe
await api.listener.stop();
console.log('⏹️ Listener đã dừng');

// Hoặc sử dụng trong signal handler
process.on('SIGINT', async () => {
  console.log('🛑 Đang tắt listener...');
  await api.listener.stop();
  process.exit(0);
});
```

## Lắng Nghe Tin Nhắn

### 1. Tin Nhắn Cơ Bản

```typescript
api.listener.on('message', (message) => {
  const { threadId, threadType, data, senderId } = message;
  
  console.log(`💬 Tin nhắn mới từ ${senderId}:`);
  console.log(`   Thread: ${threadId} (${threadType === 0 ? 'User' : 'Group'})`);
  console.log(`   Nội dung: ${data.content || 'File đính kèm'}`);
  console.log(`   Loại: ${data.msgType}`);
  console.log(`   Thời gian: ${new Date(data.ts).toLocaleString()}`);
});
```

### 2. Lọc Tin Nhắn Theo Loại

```typescript
api.listener.on('message', (message) => {
  const { data, senderId, threadId, threadType } = message;
  
  switch (data.msgType) {
    case 'webchat':
      console.log(`📝 Tin nhắn văn bản: ${data.content}`);
      break;
      
    case 'chat.photo':
      console.log(`📷 Ảnh: ${data.href}`);
      console.log(`   Kích thước: ${data.width}x${data.height}`);
      break;
      
    case 'chat.video.msg':
      console.log(`🎥 Video: ${data.href}`);
      console.log(`   Thời lượng: ${data.duration}s`);
      break;
      
    case 'chat.audio':
      console.log(`🎵 Audio: ${data.href}`);
      break;
      
    case 'chat.file':
      console.log(`📎 File: ${data.fileName}`);
      console.log(`   Kích thước: ${data.fileSize} bytes`);
      break;
      
    case 'chat.sticker':
      console.log(`😀 Sticker: ${data.stickerId}`);
      break;
      
    case 'chat.link':
      console.log(`🔗 Link: ${data.href}`);
      break;
      
    case 'chat.location':
      console.log(`📍 Vị trí: ${data.latitude}, ${data.longitude}`);
      break;
      
    default:
      console.log(`❓ Loại tin nhắn không xác định: ${data.msgType}`);
  }
});
```

### 3. Auto Reply Bot

```typescript
api.listener.on('message', async (message) => {
  const { threadId, threadType, data, senderId } = message;
  
  // Bỏ qua tin nhắn của chính mình
  const myId = await api.getOwnId();
  if (senderId === myId) return;
  
  // Bỏ qua nếu không phải tin nhắn văn bản
  if (data.msgType !== 'webchat' || !data.content) return;
  
  const text = data.content.toLowerCase().trim();
  
  try {
    if (text === '/help') {
      const helpText = `
🤖 Bot Commands:
/help - Hiển thị hướng dẫn
/time - Xem thời gian hiện tại  
/weather - Dự báo thời tiết
/ping - Test bot
/info - Thông tin bot
      `.trim();
      
      await api.sendMessage(helpText, threadId, threadType);
      
    } else if (text === '/time') {
      const now = new Date().toLocaleString('vi-VN');
      await api.sendMessage(`🕐 Bây giờ là: ${now}`, threadId, threadType);
      
    } else if (text === '/ping') {
      await api.sendMessage('🏓 Pong!', threadId, threadType);
      
    } else if (text === '/weather') {
      await api.sendMessage('⛅ Hôm nay trời đẹp, nắng nhẹ 25°C', threadId, threadType);
      
    } else if (text === '/info') {
      const info = `
🤖 Zalo Bot SDK v1.0
📅 Khởi động: ${new Date().toLocaleDateString()}
💻 Node.js ${process.version}
      `.trim();
      
      await api.sendMessage(info, threadId, threadType);
      
    } else if (text.startsWith('/echo ')) {
      const echoText = data.content.substring(6);
      await api.sendMessage(`🔊 ${echoText}`, threadId, threadType);
      
    } else if (text.includes('hello') || text.includes('hi') || text.includes('chào')) {
      await api.sendMessage('👋 Xin chào! Gõ /help để xem hướng dẫn.', threadId, threadType);
    }
    
  } catch (error) {
    console.error('❌ Lỗi auto reply:', error.message);
  }
});
```

### 4. Message Analytics

```typescript
class MessageAnalytics {
  private stats = {
    totalMessages: 0,
    messagesByType: new Map<string, number>(),
    messagesByUser: new Map<string, number>(),
    messagesByThread: new Map<string, number>(),
    dailyStats: new Map<string, number>()
  };
  
  constructor(api: any) {
    api.listener.on('message', (message: any) => {
      this.recordMessage(message);
    });
  }
  
  recordMessage(message: any) {
    const { data, senderId, threadId } = message;
    const today = new Date().toDateString();
    
    // Tổng tin nhắn
    this.stats.totalMessages++;
    
    // Theo loại
    const currentTypeCount = this.stats.messagesByType.get(data.msgType) || 0;
    this.stats.messagesByType.set(data.msgType, currentTypeCount + 1);
    
    // Theo user
    const currentUserCount = this.stats.messagesByUser.get(senderId) || 0;
    this.stats.messagesByUser.set(senderId, currentUserCount + 1);
    
    // Theo thread
    const currentThreadCount = this.stats.messagesByThread.get(threadId) || 0;
    this.stats.messagesByThread.set(threadId, currentThreadCount + 1);
    
    // Theo ngày
    const currentDayCount = this.stats.dailyStats.get(today) || 0;
    this.stats.dailyStats.set(today, currentDayCount + 1);
  }
  
  getStats() {
    return {
      total: this.stats.totalMessages,
      byType: Object.fromEntries(this.stats.messagesByType),
      byUser: Object.fromEntries(this.stats.messagesByUser),
      byThread: Object.fromEntries(this.stats.messagesByThread),
      byDay: Object.fromEntries(this.stats.dailyStats)
    };
  }
  
  printStats() {
    const stats = this.getStats();
    
    console.log('📊 Message Statistics:');
    console.log(`   Tổng tin nhắn: ${stats.total}`);
    
    console.log('   Top message types:');
    Object.entries(stats.byType)
      .sort(([,a], [,b]) => (b as number) - (a as number))
      .slice(0, 5)
      .forEach(([type, count]) => {
        console.log(`     ${type}: ${count}`);
      });
      
    console.log('   Hôm nay:', stats.byDay[new Date().toDateString()] || 0);
  }
}

// Sử dụng
const analytics = new MessageAnalytics(api);

// In thống kê mỗi 10 phút
setInterval(() => {
  analytics.printStats();
}, 10 * 60 * 1000);
```

## Sự Kiện Nhóm

### 1. Quản Lý Thành Viên

```typescript
api.listener.on('group_event', (event) => {
  const { groupId, actorId, targetId, type, data } = event;
  
  switch (type) {
    case 'group.member.add':
      console.log(`👥 ${actorId} đã thêm ${targetId} vào nhóm ${groupId}`);
      
      // Chào mừng thành viên mới
      api.sendMessage(
        `🎉 Chào mừng bạn ${targetId} tham gia nhóm!`,
        groupId,
        ThreadType.Group
      );
      break;
      
    case 'group.member.remove':
      console.log(`👋 ${actorId} đã xóa ${targetId} khỏi nhóm ${groupId}`);
      break;
      
    case 'group.member.left':
      console.log(`🚪 ${targetId} đã rời nhóm ${groupId}`);
      break;
      
    case 'group.name.change':
      console.log(`📝 ${actorId} đã đổi tên nhóm ${groupId} thành: ${data.newName}`);
      break;
      
    case 'group.avatar.change':
      console.log(`🖼️ ${actorId} đã thay avatar nhóm ${groupId}`);
      break;
      
    case 'group.admin.add':
      console.log(`👑 ${targetId} đã được thêm làm admin nhóm ${groupId}`);
      break;
      
    case 'group.admin.remove':
      console.log(`👤 ${targetId} đã bị xóa khỏi admin nhóm ${groupId}`);
      break;
  }
});
```

### 2. Auto Moderation

```typescript
class GroupModerator {
  private bannedWords = ['spam', 'hack', 'cheat'];
  private warningCount = new Map<string, number>();
  private api: any;
  
  constructor(api: any) {
    this.api = api;
    
    api.listener.on('message', (message: any) => {
      this.moderateMessage(message);
    });
  }
  
  async moderateMessage(message: any) {
    const { threadId, threadType, data, senderId } = message;
    
    // Chỉ moderate trong nhóm
    if (threadType !== 1) return;
    
    // Bỏ qua nếu không phải tin nhắn văn bản
    if (data.msgType !== 'webchat' || !data.content) return;
    
    const content = data.content.toLowerCase();
    
    // Kiểm tra từ cấm
    const hasBannedWord = this.bannedWords.some(word => content.includes(word));
    
    if (hasBannedWord) {
      try {
        // Xóa tin nhắn
        await this.api.deleteMessage({
          messageId: data.msgId,
          threadId: threadId,
          threadType: threadType
        });
        
        // Cảnh báo user
        const warnings = (this.warningCount.get(senderId) || 0) + 1;
        this.warningCount.set(senderId, warnings);
        
        if (warnings >= 3) {
          // Kick khỏi nhóm sau 3 lần cảnh báo
          await this.api.removeUserFromGroup(threadId, senderId);
          
          await this.api.sendMessage(
            `🚫 ${senderId} đã bị kick khỏi nhóm do vi phạm nhiều lần.`,
            threadId,
            threadType
          );
          
          this.warningCount.delete(senderId);
        } else {
          await this.api.sendMessage(
            `⚠️ @${senderId} Cảnh báo ${warnings}/3: Không sử dụng từ ngữ không phù hợp!`,
            threadId,
            threadType,
            {
              mentions: [{ pos: 2, len: senderId.length + 1, uid: senderId }]
            }
          );
        }
        
        console.log(`🛡️ Đã xóa tin nhắn vi phạm từ ${senderId}`);
        
      } catch (error) {
        console.error('❌ Lỗi moderation:', error.message);
      }
    }
  }
  
  addBannedWord(word: string) {
    this.bannedWords.push(word.toLowerCase());
  }
  
  removeBannedWord(word: string) {
    const index = this.bannedWords.indexOf(word.toLowerCase());
    if (index > -1) {
      this.bannedWords.splice(index, 1);
    }
  }
}

// Sử dụng
const moderator = new GroupModerator(api);
moderator.addBannedWord('badword');
```

## Sự Kiện Bạn Bè

### 1. Quản Lý Lời Mời Kết Bạn

```typescript
api.listener.on('friend_event', async (event) => {
  const { type, fromId, toId, data } = event;
  
  switch (type) {
    case 'friend.request.received':
      console.log(`👋 Nhận lời mời kết bạn từ ${fromId}`);
      
      // Auto accept từ whitelist
      const whitelist = ['trusted-user-1', 'trusted-user-2'];
      if (whitelist.includes(fromId)) {
        try {
          await api.acceptFriendRequest(fromId);
          console.log(`✅ Đã tự động chấp nhận kết bạn với ${fromId}`);
          
          // Gửi tin nhắn chào mừng
          await api.sendMessage(
            '🎉 Chào mừng bạn! Cảm ơn bạn đã kết bạn với mình.',
            fromId,
            ThreadType.User
          );
        } catch (error) {
          console.error('❌ Lỗi auto accept:', error.message);
        }
      }
      break;
      
    case 'friend.request.accepted':
      console.log(`✅ ${toId} đã chấp nhận lời mời kết bạn`);
      break;
      
    case 'friend.removed':
      console.log(`💔 ${fromId} đã unfriend`);
      break;
      
    case 'friend.blocked':
      console.log(`🚫 ${fromId} đã chặn bạn`);
      break;
  }
});
```

### 2. Friend Request Manager

```typescript
class FriendRequestManager {
  private api: any;
  private autoAcceptRules: Array<(fromId: string, data: any) => boolean> = [];
  
  constructor(api: any) {
    this.api = api;
    
    api.listener.on('friend_event', (event: any) => {
      if (event.type === 'friend.request.received') {
        this.handleFriendRequest(event);
      }
    });
  }
  
  addRule(rule: (fromId: string, data: any) => boolean) {
    this.autoAcceptRules.push(rule);
  }
  
  async handleFriendRequest(event: any) {
    const { fromId, data } = event;
    
    try {
      // Lấy thông tin người gửi
      const userInfo = await this.api.getUserInfo([fromId]);
      const user = userInfo.data[0];
      
      console.log(`👋 Lời mời kết bạn từ: ${user.displayName}`);
      console.log(`   Lời nhắn: ${data.message || 'Không có'}`);
      
      // Kiểm tra rules
      const shouldAccept = this.autoAcceptRules.some(rule => rule(fromId, data));
      
      if (shouldAccept) {
        await this.api.acceptFriendRequest(fromId);
        console.log(`✅ Đã tự động chấp nhận kết bạn với ${user.displayName}`);
        
        // Gửi tin nhắn welcome
        await this.api.sendMessage(
          `🎉 Xin chào ${user.displayName}! Rất vui được kết bạn với bạn.`,
          fromId,
          ThreadType.User
        );
      } else {
        console.log(`⏳ Lời mời từ ${user.displayName} cần xem xét thủ công`);
      }
      
    } catch (error) {
      console.error('❌ Lỗi xử lý lời mời kết bạn:', error.message);
    }
  }
}

// Sử dụng
const friendManager = new FriendRequestManager(api);

// Rule: Accept nếu có từ khóa trong lời nhắn
friendManager.addRule((fromId, data) => {
  const message = data.message?.toLowerCase() || '';
  return message.includes('developer') || message.includes('programmer');
});

// Rule: Accept nếu tên có từ khóa
friendManager.addRule(async (fromId, data) => {
  try {
    const userInfo = await api.getUserInfo([fromId]);
    const displayName = userInfo.data[0].displayName.toLowerCase();
    return displayName.includes('dev') || displayName.includes('tech');
  } catch {
    return false;
  }
});
```

## Sự Kiện Reaction và Typing

### 1. Reaction Events

```typescript
api.listener.on('reaction', (event) => {
  const { messageId, threadId, reactorId, emoji, action } = event;
  
  if (action === 'add') {
    console.log(`❤️ ${reactorId} đã react ${emoji} vào tin nhắn ${messageId}`);
  } else {
    console.log(`💔 ${reactorId} đã bỏ react ${emoji} khỏi tin nhắn ${messageId}`);
  }
});
```

### 2. Typing Events

```typescript
api.listener.on('typing', (event) => {
  const { threadId, userId, isTyping } = event;
  
  if (isTyping) {
    console.log(`⌨️ ${userId} đang typing trong ${threadId}`);
  } else {
    console.log(`⏸️ ${userId} đã dừng typing trong ${threadId}`);
  }
});
```

### 3. Seen/Delivered Events

```typescript
api.listener.on('seen', (event) => {
  const { messageId, threadId, userId, timestamp } = event;
  console.log(`👀 ${userId} đã seen tin nhắn ${messageId} lúc ${new Date(timestamp).toLocaleString()}`);
});

api.listener.on('delivered', (event) => {
  const { messageId, threadId, userId, timestamp } = event;
  console.log(`📩 Tin nhắn ${messageId} đã delivered đến ${userId}`);
});
```

## Sự Kiện Undo

```typescript
api.listener.on('undo', (event) => {
  const { messageId, threadId, userId, undoType } = event;
  
  switch (undoType) {
    case 'message':
      console.log(`🔄 ${userId} đã thu hồi tin nhắn ${messageId}`);
      break;
    case 'reaction':
      console.log(`🔄 ${userId} đã thu hồi reaction`);
      break;
    default:
      console.log(`🔄 ${userId} đã thu hồi: ${undoType}`);
  }
});
```

## Utility Classes

### 1. Event Logger

```typescript
import fs from 'fs/promises';

class EventLogger {
  private logFile: string;
  private buffer: any[] = [];
  private flushInterval: NodeJS.Timeout;
  
  constructor(api: any, logFile: string = './events.log') {
    this.logFile = logFile;
    
    // Log tất cả events
    const events = ['message', 'group_event', 'friend_event', 'reaction', 'typing', 'seen', 'delivered', 'undo'];
    
    events.forEach(eventName => {
      api.listener.on(eventName, (event: any) => {
        this.logEvent(eventName, event);
      });
    });
    
    // Flush buffer mỗi 30 giây
    this.flushInterval = setInterval(() => {
      this.flushBuffer();
    }, 30000);
  }
  
  private logEvent(type: string, event: any) {
    const logEntry = {
      timestamp: new Date().toISOString(),
      type,
      event: JSON.stringify(event)
    };
    
    this.buffer.push(logEntry);
    console.log(`📝 Logged ${type} event`);
    
    // Flush nếu buffer đầy
    if (this.buffer.length >= 100) {
      this.flushBuffer();
    }
  }
  
  private async flushBuffer() {
    if (this.buffer.length === 0) return;
    
    try {
      const logs = this.buffer.map(entry => 
        `[${entry.timestamp}] ${entry.type}: ${entry.event}`
      ).join('\n') + '\n';
      
      await fs.appendFile(this.logFile, logs);
      console.log(`💾 Flushed ${this.buffer.length} events to log`);
      
      this.buffer = [];
    } catch (error) {
      console.error('❌ Lỗi ghi log:', error.message);
    }
  }
  
  async close() {
    if (this.flushInterval) {
      clearInterval(this.flushInterval);
    }
    await this.flushBuffer();
  }
}

// Sử dụng
const logger = new EventLogger(api);

// Cleanup khi tắt app
process.on('SIGINT', async () => {
  await logger.close();
  await api.listener.stop();
  process.exit(0);
});
```

### 2. Event Router

```typescript
class EventRouter {
  private routes = new Map<string, Array<(event: any) => void>>();
  
  constructor(api: any) {
    // Route tất cả events qua router
    const events = ['message', 'group_event', 'friend_event', 'reaction', 'typing', 'seen', 'delivered', 'undo'];
    
    events.forEach(eventName => {
      api.listener.on(eventName, (event: any) => {
        this.routeEvent(eventName, event);
      });
    });
  }
  
  on(pattern: string, handler: (event: any) => void) {
    if (!this.routes.has(pattern)) {
      this.routes.set(pattern, []);
    }
    this.routes.get(pattern)!.push(handler);
  }
  
  private routeEvent(eventName: string, event: any) {
    // Tìm các route phù hợp
    for (const [pattern, handlers] of this.routes.entries()) {
      if (this.matchPattern(pattern, eventName, event)) {
        handlers.forEach(handler => {
          try {
            handler(event);
          } catch (error) {
            console.error(`❌ Lỗi handler cho ${pattern}:`, error.message);
          }
        });
      }
    }
  }
  
  private matchPattern(pattern: string, eventName: string, event: any): boolean {
    // Simple pattern matching
    if (pattern === eventName) return true;
    if (pattern === '*') return true;
    
    // Pattern như "message:webchat"
    if (pattern.includes(':')) {
      const [eventPattern, typePattern] = pattern.split(':');
      return eventPattern === eventName && 
             event.data?.msgType === typePattern;
    }
    
    return false;
  }
}

// Sử dụng
const router = new EventRouter(api);

// Route tin nhắn văn bản
router.on('message:webchat', (event) => {
  console.log(`📝 Text message: ${event.data.content}`);
});

// Route tin nhắn ảnh
router.on('message:chat.photo', (event) => {
  console.log(`📷 Image: ${event.data.href}`);
});

// Route tất cả sự kiện nhóm
router.on('group_event', (event) => {
  console.log(`👥 Group event: ${event.type}`);
});

// Route tất cả sự kiện
router.on('*', (event) => {
  console.log(`🎯 Any event received`);
});
```

## Reconnection và Error Handling

### 1. Auto Reconnect

```typescript
class ReliableListener {
  private api: any;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 10;
  private reconnectDelay = 5000;
  private isReconnecting = false;
  
  constructor(api: any) {
    this.api = api;
    this.setupListener();
  }
  
  private setupListener() {
    this.api.listener.on('disconnect', (reason: CloseReason) => {
      console.log(`❌ Listener disconnected: ${reason}`);
      
      if (reason === CloseReason.Error && !this.isReconnecting) {
        this.reconnect();
      }
    });
    
    this.api.listener.on('connect', () => {
      console.log('✅ Listener connected');
      this.reconnectAttempts = 0;
      this.isReconnecting = false;
    });
    
    this.api.listener.on('error', (error: any) => {
      console.error('🚨 Listener error:', error.message);
      if (!this.isReconnecting) {
        this.reconnect();
      }
    });
  }
  
  private async reconnect() {
    if (this.isReconnecting) return;
    
    this.isReconnecting = true;
    
    while (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++;
      console.log(`🔄 Reconnect attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}`);
      
      try {
        await this.api.listener.stop();
        await new Promise(resolve => setTimeout(resolve, this.reconnectDelay));
        await this.api.listener.start();
        
        console.log('✅ Reconnected successfully');
        return;
      } catch (error) {
        console.error(`❌ Reconnect attempt ${this.reconnectAttempts} failed:`, error.message);
        
        // Exponential backoff
        this.reconnectDelay *= 1.5;
      }
    }
    
    console.error('💥 Max reconnect attempts reached. Listener stopped.');
    this.isReconnecting = false;
  }
  
  async start() {
    try {
      await this.api.listener.start();
    } catch (error) {
      console.error('❌ Failed to start listener:', error.message);
      this.reconnect();
    }
  }
}

// Sử dụng
const reliableListener = new ReliableListener(api);
await reliableListener.start();
```

### 2. Health Monitor

```typescript
class ListenerHealthMonitor {
  private api: any;
  private lastEventTime = Date.now();
  private healthCheckInterval: NodeJS.Timeout;
  private isHealthy = true;
  
  constructor(api: any, checkIntervalMs: number = 60000) {
    this.api = api;
    
    // Track last event time
    const events = ['message', 'group_event', 'friend_event', 'reaction', 'typing', 'seen', 'delivered'];
    events.forEach(eventName => {
      api.listener.on(eventName, () => {
        this.lastEventTime = Date.now();
        if (!this.isHealthy) {
          console.log('💚 Listener health recovered');
          this.isHealthy = true;
        }
      });
    });
    
    // Health check
    this.healthCheckInterval = setInterval(() => {
      this.checkHealth();
    }, checkIntervalMs);
  }
  
  private checkHealth() {
    const now = Date.now();
    const timeSinceLastEvent = now - this.lastEventTime;
    
    // Coi như unhealthy nếu không có event nào trong 5 phút
    if (timeSinceLastEvent > 5 * 60 * 1000) {
      if (this.isHealthy) {
        console.log('💔 Listener appears unhealthy - no events for 5 minutes');
        this.isHealthy = false;
        
        // Send keep alive or restart listener
        this.tryRecover();
      }
    }
  }
  
  private async tryRecover() {
    try {
      // Try keep alive first
      await this.api.keepAlive();
      console.log('📡 Keep alive sent');
      
      // If still no events after 2 more minutes, restart listener
      setTimeout(() => {
        if (!this.isHealthy) {
          console.log('🔄 Restarting listener due to health issues');
          this.restartListener();
        }
      }, 2 * 60 * 1000);
      
    } catch (error) {
      console.error('❌ Keep alive failed:', error.message);
      this.restartListener();
    }
  }
  
  private async restartListener() {
    try {
      await this.api.listener.stop();
      await new Promise(resolve => setTimeout(resolve, 5000));
      await this.api.listener.start();
      console.log('✅ Listener restarted');
    } catch (error) {
      console.error('❌ Failed to restart listener:', error.message);
    }
  }
  
  stop() {
    if (this.healthCheckInterval) {
      clearInterval(this.healthCheckInterval);
    }
  }
}

// Sử dụng
const healthMonitor = new ListenerHealthMonitor(api);
```

## Best Practices

### 1. Memory Management

```typescript
// Cleanup listeners khi không cần
const messageHandler = (message: any) => {
  console.log('New message:', message.data.content);
};

api.listener.on('message', messageHandler);

// Cleanup
api.listener.off('message', messageHandler);
```

### 2. Error Boundaries

```typescript
function safeEventHandler(handler: Function) {
  return (event: any) => {
    try {
      handler(event);
    } catch (error) {
      console.error('❌ Event handler error:', error.message);
      console.error('Event data:', JSON.stringify(event, null, 2));
    }
  };
}

// Sử dụng
api.listener.on('message', safeEventHandler((message) => {
  // Handler code có thể throw error
  processMessage(message);
}));
```

### 3. Performance Monitoring

```typescript
class PerformanceMonitor {
  private eventCounts = new Map<string, number>();
  private lastReset = Date.now();
  
  constructor(api: any) {
    const events = ['message', 'group_event', 'friend_event', 'reaction'];
    
    events.forEach(eventName => {
      api.listener.on(eventName, () => {
        const count = this.eventCounts.get(eventName) || 0;
        this.eventCounts.set(eventName, count + 1);
      });
    });
    
    // Report mỗi phút
    setInterval(() => {
      this.reportStats();
    }, 60000);
  }
  
  private reportStats() {
    const now = Date.now();
    const elapsed = (now - this.lastReset) / 1000;
    
    console.log(`📊 Events per second (last ${elapsed.toFixed(0)}s):`);
    
    for (const [eventName, count] of this.eventCounts.entries()) {
      const eps = (count / elapsed).toFixed(2);
      console.log(`   ${eventName}: ${eps} eps (${count} total)`);
    }
    
    // Reset counters
    this.eventCounts.clear();
    this.lastReset = now;
  }
}
```

## Lưu Ý Quan Trọng

1. **Memory Leaks**: Cleanup listeners khi không cần thiết
2. **Rate Limiting**: Không xử lý quá nhiều events cùng lúc
3. **Error Handling**: Luôn wrap handlers trong try-catch
4. **Reconnection**: Implement auto-reconnect cho production
5. **Health Monitoring**: Monitor health của listener connection
6. **Performance**: Monitor performance và memory usage
7. **Logging**: Log events quan trọng để debug
8. **Cleanup**: Đảm bảo cleanup khi shutdown application