/**
 * WebSocket聊天管理工具类
 * 实现了心跳机制、断线重连、消息队列等功能
 */

class WebSocketManager {
  constructor() {
    this.socket = null;
    this.isConnected = false;
    this.userId = null;
    this.url = '';
    
    // 心跳相关
    this.heartbeatTimer = null;
    this.heartbeatInterval = 30000; // 30秒
    
    // 重连相关
    this.reconnectTimer = null;
    this.reconnectCount = 0;
    this.maxReconnectCount = 10;
    this.reconnectDelay = 1000; // 初始1秒
    
    // 消息队列（断线时暂存）
    this.messageQueue = [];
    this.maxQueueSize = 100;
    
    // 回调函数
    this.onMessageCallback = null;
    this.onConnectCallback = null;
    this.onDisconnectCallback = null;
    this.onErrorCallback = null;
  }

  /**
   * 连接WebSocket
   * @param {Number} userId 用户ID
   * @param {String} baseUrl WebSocket服务地址
   */
  connect(userId, baseUrl = 'ws://localhost:1004') {
    if (this.isConnected) {
      console.log('WebSocket已连接');
      return;
    }

    this.userId = userId;
    this.url = `${baseUrl}/ws/chat?userId=${userId}`;
    
    console.log('正在连接WebSocket...', this.url);

    this.socket = uni.connectSocket({
      url: this.url,
      success: () => {
        console.log('WebSocket连接请求已发送');
      },
      fail: (err) => {
        console.error('WebSocket连接失败', err);
        this.onError(err);
      }
    });

    // 监听连接打开
    uni.onSocketOpen((res) => {
      console.log('WebSocket连接成功');
      this.isConnected = true;
      this.reconnectCount = 0;
      
      // 启动心跳
      this.startHeartbeat();
      
      // 发送队列中的消息
      this.flushMessageQueue();
      
      // 触发连接回调
      if (this.onConnectCallback) {
        this.onConnectCallback();
      }
    });

    // 监听消息接收
    uni.onSocketMessage((res) => {
      try {
        console.log('🔵 收到原始WebSocket消息:', res.data);
        const message = JSON.parse(res.data);
        console.log('🔵 解析后的消息对象:', JSON.stringify(message, null, 2));
        this.handleMessage(message);
      } catch (e) {
        console.error('❌ 解析消息失败', e);
        console.error('   原始数据:', res.data);
      }
    });

    // 监听连接关闭
    uni.onSocketClose((res) => {
      console.log('WebSocket连接关闭', res);
      this.isConnected = false;
      this.stopHeartbeat();
      
      // 触发断开回调
      if (this.onDisconnectCallback) {
        this.onDisconnectCallback();
      }
      
      // 尝试重连
      this.reconnect();
    });

    // 监听错误
    uni.onSocketError((err) => {
      console.error('WebSocket错误', err);
      this.isConnected = false;
      this.onError(err);
    });
  }

  /**
   * 处理接收到的消息
   */
  handleMessage(message) {
    console.log('收到消息', message);

    switch (message.type) {
      case 'pong':
        // 心跳响应
        console.log('收到pong');
        break;
        
      case 'chat':
        // 聊天消息
        if (this.onMessageCallback) {
          this.onMessageCallback(message);
        }
        // 自动发送ACK确认
        this.sendAck(message.messageId);
        break;
        
      case 'ack':
        // 消息确认
        console.log('✅ 收到ACK消息！');
        console.log('   messageId:', message.messageId);
        console.log('   完整ACK消息:', JSON.stringify(message));
        if (this.onMessageCallback) {
          console.log('   正在调用onMessageCallback...');
          this.onMessageCallback(message);
        } else {
          console.warn('   ⚠️ onMessageCallback未设置！');
        }
        break;
        
      case 'recall':
        // 消息撤回
        if (this.onMessageCallback) {
          this.onMessageCallback(message);
        }
        break;
        
      case 'typing':
        // 正在输入
        if (this.onMessageCallback) {
          this.onMessageCallback(message);
        }
        break;
        
      case 'read':
        // 已读回执
        if (this.onMessageCallback) {
          this.onMessageCallback(message);
        }
        break;
        
      case 'online':
        // 上线通知
        console.log('用户上线', message.fromUserId);
        break;
        
      case 'error':
        // 错误消息
        console.error('服务器错误', message.errorMessage);
        uni.showToast({
          title: message.errorMessage,
          icon: 'none'
        });
        break;
        
      default:
        console.log('未知消息类型', message.type);
    }
  }

  /**
   * 发送聊天消息
   */
  sendMessage(toUserId, content, messageType = 1, extraData = {}) {
    const message = {
      type: 'chat',
      messageId: this.generateMessageId(),
      fromUserId: this.userId,
      toUserId: toUserId,
      messageType: messageType,
      content: content,
      timestamp: Date.now(),
      extraData: extraData
    };

    if (messageType === 2) {
      // 图片消息
      message.mediaUrl = extraData.mediaUrl;
      message.thumbnailUrl = extraData.thumbnailUrl;
    } else if (messageType === 3 || messageType === 4) {
      // 语音或视频消息
      message.mediaUrl = extraData.mediaUrl;
      message.duration = extraData.duration;
      message.mediaSize = extraData.mediaSize;
    }

    this.send(message);
    return message.messageId;
  }

  /**
   * 发送消息ACK确认
   */
  sendAck(messageId) {
    this.send({
      type: 'ack',
      messageId: messageId,
      timestamp: Date.now()
    });
  }

  /**
   * 撤回消息
   */
  recallMessage(messageId) {
    this.send({
      type: 'recall',
      messageId: messageId,
      timestamp: Date.now()
    });
  }

  /**
   * 发送正在输入状态
   */
  sendTyping(toUserId) {
    this.send({
      type: 'typing',
      toUserId: toUserId,
      timestamp: Date.now()
    });
  }

  /**
   * 发送已读回执
   */
  sendReadReceipt(toUserId) {
    this.send({
      type: 'read',
      fromUserId: this.userId,
      toUserId: toUserId,
      timestamp: Date.now()
    });
  }

  /**
   * 发送数据到WebSocket
   */
  send(data) {
    console.log('🔷 准备发送WebSocket消息');
    console.log('   消息类型:', data.type);
    console.log('   isConnected:', this.isConnected);
    console.log('   完整数据:', JSON.stringify(data, null, 2));
    
    if (!this.isConnected) {
      console.log('❌ WebSocket未连接，消息加入队列');
      // 加入消息队列
      if (this.messageQueue.length < this.maxQueueSize) {
        this.messageQueue.push(data);
      }
      return false;
    }

    try {
      const jsonStr = JSON.stringify(data);
      console.log('🔷 JSON字符串长度:', jsonStr.length);
      
      uni.sendSocketMessage({
        data: jsonStr,
        success: () => {
          console.log('✅ WebSocket消息已发送到服务器');
          console.log('   消息类型:', data.type);
          console.log('   messageId:', data.messageId || 'N/A');
        },
        fail: (err) => {
          console.error('❌ WebSocket消息发送失败', err);
          console.error('   错误详情:', JSON.stringify(err));
          // 发送失败，加入队列
          if (this.messageQueue.length < this.maxQueueSize) {
            this.messageQueue.push(data);
          }
        }
      });
      return true;
    } catch (e) {
      console.error('❌ 发送消息异常', e);
      console.error('   异常详情:', e.message);
      return false;
    }
  }

  /**
   * 发送队列中的消息
   */
  flushMessageQueue() {
    if (this.messageQueue.length === 0) {
      return;
    }

    console.log(`发送队列中的 ${this.messageQueue.length} 条消息`);
    
    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift();
      this.send(message);
    }
  }

  /**
   * 启动心跳
   */
  startHeartbeat() {
    this.stopHeartbeat();
    
    this.heartbeatTimer = setInterval(() => {
      if (this.isConnected) {
        this.send({
          type: 'ping',
          timestamp: Date.now()
        });
      }
    }, this.heartbeatInterval);
  }

  /**
   * 停止心跳
   */
  stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  /**
   * 断线重连
   */
  reconnect() {
    if (this.reconnectCount >= this.maxReconnectCount) {
      console.log('达到最大重连次数，停止重连');
      uni.showToast({
        title: '连接失败，请检查网络',
        icon: 'none'
      });
      return;
    }

    // 指数退避算法
    const delay = Math.min(
      this.reconnectDelay * Math.pow(2, this.reconnectCount),
      30000  // 最大30秒
    );

    console.log(`${delay}ms 后进行第 ${this.reconnectCount + 1} 次重连...`);

    this.reconnectTimer = setTimeout(() => {
      this.reconnectCount++;
      this.connect(this.userId, this.url.split('/ws/chat')[0]);
    }, delay);
  }

  /**
   * 取消重连
   */
  cancelReconnect() {
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer);
      this.reconnectTimer = null;
    }
  }

  /**
   * 关闭连接
   */
  close() {
    this.cancelReconnect();
    this.stopHeartbeat();
    
    if (this.socket) {
      uni.closeSocket();
      this.socket = null;
    }
    
    this.isConnected = false;
  }

  /**
   * 错误处理
   */
  onError(error) {
    if (this.onErrorCallback) {
      this.onErrorCallback(error);
    }
  }

  /**
   * 生成消息ID
   */
  generateMessageId() {
    return `${this.userId}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  /**
   * 设置消息回调
   */
  onMessage(callback) {
    this.onMessageCallback = callback;
  }

  /**
   * 设置连接回调
   */
  onConnect(callback) {
    this.onConnectCallback = callback;
  }

  /**
   * 设置断开回调
   */
  onDisconnect(callback) {
    this.onDisconnectCallback = callback;
  }

  /**
   * 设置错误回调
   */
  onErrorHandler(callback) {
    this.onErrorCallback = callback;
  }
}

// 导出单例
export default new WebSocketManager();



