import { ChatMessage, WebSocketMessage } from '@/types/chat';

export class WebSocketService {
  private socket: WebSocket | null = null;
  private messageListeners: ((message: ChatMessage) => void)[] = [];
  private connectionListeners: ((connected: boolean) => void)[] = [];
  private reconnectInterval: NodeJS.Timeout | null = null;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;
  private reconnectDelay = 3000; // 3 seconds
  private receivedMessageIds = new Set<string>();
  private roomCode: string | null = null;
  private appId: string | null = null;
  private userCode: string | null = null;
  private deleteMessageListeners: ((messageId: string) => void)[] = [];

  constructor(private url: string) {}

  connect(roomCode: string, appId: string, userCode: string = 'anonymous'): Promise<boolean> {
    if (this.socket) {
      this.disconnect();
    }

    this.receivedMessageIds.clear();

    const fullUrl = `${this.url}?room_code=${roomCode}&app_id=${appId}&user_code=${userCode}`;
    this.socket = new WebSocket(fullUrl);
    this.roomCode = roomCode;
    this.appId = appId;
    this.userCode = userCode;

    return new Promise((resolve) => {
      if (this.socket) {
        this.socket.onopen = () => {
          console.log('WebSocket connection established');
          this.reconnectAttempts = 0;
          this.notifyConnectionListeners(true);
          resolve(true);
        };

        this.socket.onmessage = (event) => {
          try {
            const data: WebSocketMessage = JSON.parse(event.data);
            
            // ตรวจสอบประเภทของข้อความ
            if (data.type === 'chat' && data.payload) {
              // ตรวจสอบว่า payload มีรูปแบบ snake_case
              const payload = data.payload as ChatMessage;
              
              // ตรวจสอบว่ามี user_info หรือไม่
              if (!payload.user_info) {
                payload.user_info = {
                  username: 'Unknown User',
                  profile_image: '/image/profile.png'
                };
              }
              
              // ตรวจสอบว่ามี created_at หรือไม่
              if (!payload.created_at) {
                payload.created_at = new Date().toISOString();
              }
              // สร้าง id ถ้าไม่มี
              if (!payload.id) {
                payload.id = `${payload.user_code}_${new Date(payload.created_at).getTime()}`;
              }
              
              // ตรวจสอบว่าข้อความซ้ำกันหรือไม่
              if (!this.receivedMessageIds.has(payload.id)) {
                this.receivedMessageIds.add(payload.id);
                this.notifyMessageListeners(payload);
              } else {
                console.log('Duplicate message received, ignoring:', payload.id);
              }
            } else if (data.type === 'message_deleted' && data.payload) {
              // รับการแจ้งเตือนการลบข้อความ
              const deletePayload = data.payload as {
                room_code: string;
                app_id: string;
                message_id: string;
              };
              
              // console.log('Message deleted notification received:', deletePayload);
              
              // แจ้งเตือนผู้ฟังเกี่ยวกับการลบข้อความ
              this.notifyDeleteMessageListeners(deletePayload.message_id);
            }
          } catch (error) {
            console.error('Error parsing WebSocket message:', error);
          }
        };

        this.socket.onclose = (event) => {
          console.log('WebSocket connection closed:', event.code, event.reason);
          this.notifyConnectionListeners(false);
          this.socket = null;

          // Attempt to reconnect
          if (this.reconnectAttempts < this.maxReconnectAttempts) {
            this.reconnectInterval = setTimeout(() => {
              this.reconnectAttempts++;
              this.connect(this.roomCode!, this.appId!, this.userCode || 'anonymous').then((connected) => {
                if (!connected) {
                  resolve(false);
                }
              });
            }, this.reconnectDelay);
          } else {
            resolve(false);
          }
        };

        this.socket.onerror = (error) => {
          console.error('WebSocket error:', error);
          resolve(false);
        };
      } else {
        resolve(false);
      }
    });
  }

  disconnect(): void {
    if (this.socket) {
      this.socket.close();
      this.socket = null;
    }
    
    // ล้าง receivedMessageIds เมื่อตัดการเชื่อมต่อ
    this.receivedMessageIds.clear();
    
    if (this.reconnectInterval) {
      clearTimeout(this.reconnectInterval);
      this.reconnectInterval = null;
    }
  }

  sendMessage(message: ChatMessage): void {
    if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
      console.error('WebSocket is not connected');
      
      // ลองเชื่อมต่อใหม่ถ้าไม่มีการเชื่อมต่อ
      if (!this.socket) {
        console.log('Attempting to reconnect before sending message...');
        // ใช้ roomCode และ appId ที่เก็บไว้ในตัวแปรระดับคลาส
        const roomCode = this.roomCode;
        const appId = this.appId;
        const userCode = this.userCode;
        
        if (roomCode && appId && userCode) {
          this.connect(roomCode, appId, userCode).then(connected => {
            if (connected) {
              console.log('Reconnected successfully, sending message...');
              this.sendMessage(message);
            } else {
              console.error('Failed to reconnect, message not sent');
            }
          });
        } else {
          console.error('Cannot reconnect: missing roomCode, appId or userCode');
        }
      }
      return;
    }

    // ตรวจสอบว่า message มี user_info หรือไม่
    if (!message.user_info) {
      message.user_info = {
        username: 'Unknown User',
        profile_image: '/image/profile.png'
      };
    }

    const wsMessage: WebSocketMessage = {
      type: 'chat',
      payload: message,
    };

    this.socket.send(JSON.stringify(wsMessage));
  }

  addMessageListener(listener: (message: ChatMessage) => void): void {
    this.messageListeners.push(listener);
  }

  removeMessageListener(listener: (message: ChatMessage) => void): void {
    this.messageListeners = this.messageListeners.filter((l) => l !== listener);
  }

  addConnectionListener(listener: (connected: boolean) => void): void {
    this.connectionListeners.push(listener);
  }

  removeConnectionListener(listener: (connected: boolean) => void): void {
    this.connectionListeners = this.connectionListeners.filter((l) => l !== listener);
  }

  addDeleteMessageListener(listener: (messageId: string) => void): void {
    this.deleteMessageListeners.push(listener);
  }

  removeDeleteMessageListener(listener: (messageId: string) => void): void {
    this.deleteMessageListeners = this.deleteMessageListeners.filter(l => l !== listener);
  }

  private notifyMessageListeners(message: ChatMessage): void {
    this.messageListeners.forEach((listener) => listener(message));
  }

  private notifyConnectionListeners(connected: boolean): void {
    this.connectionListeners.forEach((listener) => listener(connected));
  }

  private notifyDeleteMessageListeners(messageId: string): void {
    this.deleteMessageListeners.forEach((listener) => listener(messageId));
  }

  isConnected(): boolean {
    return this.socket !== null && this.socket.readyState === WebSocket.OPEN;
  }
}

// สร้าง instance ใหม่ทุกครั้ง
let defaultWsUrl = '';
let wsServiceInstance: WebSocketService | null = null;

// เพิ่มฟังก์ชันสำหรับกำหนด WebSocket URL
export function setWebSocketUrl(url: string): void {
  defaultWsUrl = url;
  wsServiceInstance = null; // Reset instance when URL changes
}

// ฟังก์ชันสำหรับดึง WebSocketService
export function getWebSocketService(url?: string): WebSocketService {
  if (!wsServiceInstance) {
    wsServiceInstance = new WebSocketService(url || defaultWsUrl);
  }
  return wsServiceInstance;
}
