/**
 * WebSocket处理器
 * 负责管理WebSocket连接和信令消息处理
 */
import Offer from './offer';
import Answer from './answer';
import Candidate from './candidate';
import { log, LogLevel } from '../log';

/**
 * 是否为私有模式
 */
let isPrivate: boolean;

/**
 * 客户端连接映射
 * 键: WebSocket实例
 * 值: 该WebSocket的连接ID集合
 */
const clients: Map<WebSocket, Set<string>> = new Map<WebSocket, Set<string>>();

/**
 * 连接组结构
 * host: 主机WebSocket实例（第一个连接的客户端）
 * participants: 参与者WebSocket集合（后续连接的客户端）
 */
interface ConnectionGroup {
  host: WebSocket;
  participants: Set<WebSocket>;
}

interface UserInfo {
  id: string;
  name: string;
  avatar?: string;
}

interface AppWebSocket extends WebSocket {
  heartbeatTimer?: ReturnType<typeof setInterval>;
  lastActivity?: number;
  participantId?: string;
  socketId?: string;
  userInfo?: UserInfo;
}

interface OnlineUser {
  socketId: string;
  connectionId: string;
  participantId: string;
  role: 'host' | 'participant' | 'idle';
  userId: string;
  name: string;
  avatar: string;
}

interface RoomMemberInfo extends OnlineUser {
  joinedAt: number;
  updatedAt: number;
}

interface RoomSnapshot {
  roomId: string;
  connectionId: string;
  hostSocketId: string;
  createdAt: number;
  updatedAt: number;
  members: RoomMemberInfo[];
  userCount: number;
}

interface StoredRoom {
  roomId: string;
  connectionId: string;
  hostSocketId: string;
  createdAt: number;
  updatedAt: number;
  members: Map<string, RoomMemberInfo>;
}

/**
 * 连接组映射
 * 键: connectionId
 * 值: ConnectionGroup（1个host + 多个participants）
 */
const connectionGroup: Map<string, ConnectionGroup> = new Map<string, ConnectionGroup>();
const rooms: Map<string, StoredRoom> = new Map<string, StoredRoom>();

function asAppWebSocket(ws: WebSocket): AppWebSocket {
  return ws as AppWebSocket;
}

function ensureSocketId(ws: WebSocket): string {
  const socket = asAppWebSocket(ws);
  socket.socketId = socket.socketId || `ws_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
  return socket.socketId;
}

function ensureParticipantId(ws: WebSocket): string {
  const socket = asAppWebSocket(ws);
  socket.participantId = socket.participantId || `p_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
  return socket.participantId;
}

function getParticipantId(ws: WebSocket): string {
  return asAppWebSocket(ws).participantId || '';
}

function getSocketId(ws: WebSocket): string {
  return asAppWebSocket(ws).socketId || '';
}

function getUserInfo(ws: WebSocket): UserInfo {
  return asAppWebSocket(ws).userInfo || { id: '', name: '', avatar: '' };
}

function setUserInfo(ws: WebSocket, userInfo: UserInfo): void {
  asAppWebSocket(ws).userInfo = {
    id: userInfo.id || '',
    name: userInfo.name || '',
    avatar: userInfo.avatar || ''
  };
  updateRoomMembersForSocket(ws);
}

function safeSend(ws: WebSocket, payload: unknown): boolean {
  if (ws.readyState !== ws.OPEN) {
    log(LogLevel.warn, 'Skip send on closed WebSocket');
    return false;
  }

  ws.send(JSON.stringify(payload));
  return true;
}

function findParticipantSocket(group: ConnectionGroup, participantId: string): WebSocket | null {
  for (const participantWs of Array.from(group.participants)) {
    if (getParticipantId(participantWs) === participantId) {
      return participantWs;
    }
  }
  return null;
}

function getSocketRoleInRoom(ws: WebSocket, connectionId: string): 'host' | 'participant' | 'idle' {
  const group = connectionGroup.get(connectionId);
  if (group) {
    if (group.host === ws) {
      return 'host';
    }
    if (group.participants.has(ws)) {
      return 'participant';
    }
  }

  return isPrivate ? 'idle' : 'participant';
}

function toRoomMember(ws: WebSocket, connectionId: string, existing?: RoomMemberInfo): RoomMemberInfo {
  const userInfo = getUserInfo(ws);
  const now = Date.now();
  return {
    socketId: ensureSocketId(ws),
    connectionId,
    participantId: ensureParticipantId(ws),
    role: getSocketRoleInRoom(ws, connectionId),
    userId: userInfo.id || '',
    name: userInfo.name || '',
    avatar: userInfo.avatar || '',
    joinedAt: existing ? existing.joinedAt : now,
    updatedAt: now
  };
}

function getOrCreateRoom(connectionId: string, ws: WebSocket): StoredRoom {
  let room = rooms.get(connectionId);
  const now = Date.now();
  const socketId = ensureSocketId(ws);
  if (!room) {
    room = {
      roomId: connectionId,
      connectionId,
      hostSocketId: '',
      createdAt: now,
      updatedAt: now,
      members: new Map<string, RoomMemberInfo>()
    };
    rooms.set(connectionId, room);
  }

  if (!room.hostSocketId || getSocketRoleInRoom(ws, connectionId) === 'host') {
    room.hostSocketId = socketId;
  }
  room.updatedAt = now;
  return room;
}

function saveRoomMember(ws: WebSocket, connectionId: string): void {
  const room = getOrCreateRoom(connectionId, ws);
  const socketId = ensureSocketId(ws);
  const existing = room.members.get(socketId);
  room.members.set(socketId, toRoomMember(ws, connectionId, existing));
  room.updatedAt = Date.now();
}

function updateRoomMembersForSocket(ws: WebSocket): void {
  const connectionIds = clients.get(ws);
  if (!connectionIds) {
    return;
  }

  connectionIds.forEach(connectionId => {
    if (rooms.has(connectionId)) {
      saveRoomMember(ws, connectionId);
    }
  });
}

function removeRoomMember(ws: WebSocket, connectionId: string): void {
  const room = rooms.get(connectionId);
  if (!room) {
    return;
  }

  room.members.delete(getSocketId(ws));
  room.updatedAt = Date.now();
  if (room.members.size === 0 || room.hostSocketId === getSocketId(ws)) {
    rooms.delete(connectionId);
  }
}

function toRoomSnapshot(room: StoredRoom): RoomSnapshot {
  const members = Array.from(room.members.values());
  return {
    roomId: room.roomId,
    connectionId: room.connectionId,
    hostSocketId: room.hostSocketId,
    createdAt: room.createdAt,
    updatedAt: room.updatedAt,
    members,
    userCount: members.length
  };
}

/**
 * 获取或创建WebSocket会话的连接ID集合
 * @param session WebSocket会话实例
 * @returns 连接ID的Set集合
 */
function getOrCreateConnectionIds(session: WebSocket): Set<string> {
  let connectionIds = null;
  // 检查客户端是否已存在
  if (!clients.has(session)) {
    // 如果不存在，创建新的连接ID集合
    connectionIds = new Set<string>();
    // 将新的连接ID集合与客户端关联
    clients.set(session, connectionIds);
  }
  // 获取客户端的连接ID集合
  connectionIds = clients.get(session);
  // 返回连接ID集合
  return connectionIds;
}

/**
 * 重置处理器状态
 * @param mode 通信模式（public或private）
 */
function reset(mode: string): void {
  // 设置是否为私有模式
  isPrivate = mode == "private";
  clients.clear();
  connectionGroup.clear();
  rooms.clear();
}

/**
 * 添加新的WebSocket连接
 * @param ws WebSocket连接实例
 */
function add(ws: WebSocket): void {
  // 为新连接创建空的连接ID集合
  const id = new Set<string>();
  clients.set(ws, id);
  const socketId = ensureSocketId(ws);
  // 记录添加WebSocket连接的日志
  log(LogLevel.log, `Add WebSocket: ${socketId}`);
}

/**
 * 判断WebSocket是否为指定连接组的host
 * @param ws WebSocket连接实例
 * @param connectionId 连接ID
 * @returns 是否为host
 */
function isHost(ws: WebSocket, connectionId: string): boolean {
  const group = connectionGroup.get(connectionId);
  return group != null && group.host === ws;
}

/**
 * 向连接组中除发送者外的所有成员发送消息
 * @param connectionId 连接ID
 * @param senderWs 发送者WebSocket实例
 * @param message 要发送的消息对象
 */
function broadcastToGroup(connectionId: string, senderWs: WebSocket, message: any): void {
  const group = connectionGroup.get(connectionId);
  if (!group) return;
  // 如果发送者是host，转发给所有participants
  if (senderWs === group.host) {
    group.participants.forEach(participantWs => {
      safeSend(participantWs, message);
    });
  } else {
    // 如果发送者是participant，转发给host
    safeSend(group.host, message);
  }
}

/**
 * 移除WebSocket连接
 * @param ws WebSocket连接实例
 */
function remove(ws: WebSocket): void {
  const connectionIds = clients.get(ws);
  if (!connectionIds) return;

  connectionIds.forEach(connectionId => {
    const group = connectionGroup.get(connectionId);
    if (group) {
      if (group.host === ws) {
        group.participants.forEach(participantWs => {
          safeSend(participantWs, { type: "disconnect", connectionId: connectionId, reason: "host-left" });
        });
        rooms.delete(connectionId);
        connectionGroup.delete(connectionId);
      } else {
        group.participants.delete(ws);
        removeRoomMember(ws, connectionId);
        // 包含participantId，让host能识别是哪个participant离开
        safeSend(group.host, { type: "participant-left", connectionId: connectionId, participantId: getParticipantId(ws) });
      }
    } else {
      removeRoomMember(ws, connectionId);
    }
    log(LogLevel.log, `Remove connectionId: ${connectionId}`);
  });

  clients.delete(ws);
}

/**
 * 处理连接请求（1对多模式）
 * 第一个连接的客户端成为host，后续连接的客户端成为participants
 * @param ws WebSocket连接实例
 * @param connectionId 连接ID
 */
function onConnect(ws: WebSocket, connectionId: string): void {
  let polite = true;
  // 为每个WebSocket生成唯一的participantId
  const participantId = ensureParticipantId(ws);

  if (isPrivate) {
    if (connectionGroup.has(connectionId)) {
      const group = connectionGroup.get(connectionId);
      group.participants.add(ws);
      log(LogLevel.log, `Participant ${participantId} joined connectionId: ${connectionId}, total participants: ${group.participants.size}`);
      // 通知host有新participant加入
      safeSend(group.host, { type: "participant-joined", connectionId: connectionId, participantId: participantId });
    } else {
      connectionGroup.set(connectionId, { host: ws, participants: new Set<WebSocket>() });
      polite = false;
      log(LogLevel.log, `Host created connectionId: ${connectionId}`);
    }
  }

  const connectionIds = getOrCreateConnectionIds(ws);
  connectionIds.add(connectionId);
  const role = polite ? 'participant' : 'host';
  saveRoomMember(ws, connectionId);
  safeSend(ws, { type: "connect", connectionId: connectionId, polite: polite, role: role, participantId: participantId });
}

/**
 * 处理断开连接请求（1对多模式）
 * @param ws WebSocket连接实例
 * @param connectionId 连接ID
 */
function onDisconnect(ws: WebSocket, connectionId: string): void {
  // 获取连接的连接ID集合
  const connectionIds = clients.get(ws);
  if (connectionIds) {
    // 从集合中删除连接ID
    connectionIds.delete(connectionId);
  }

  // 处理连接组
  const group = connectionGroup.get(connectionId);
  if (group) {
    if (group.host === ws) {
      // host断开连接，通知所有participants房间已关闭，并删除连接组
      group.participants.forEach(participantWs => {
        safeSend(participantWs, { type: "disconnect", connectionId: connectionId, reason: "host-left" });
      });
      rooms.delete(connectionId);
      connectionGroup.delete(connectionId);
      log(LogLevel.log, `Host disconnected, room ${connectionId} deleted, notified ${group.participants.size} participants`);
    } else {
      // participant断开连接，从组中移除并通知host（使用participant-left类型，host不会关闭房间）
      group.participants.delete(ws);
      removeRoomMember(ws, connectionId);
      safeSend(group.host, { type: "participant-left", connectionId: connectionId, participantId: getParticipantId(ws) });
      log(LogLevel.log, `Participant left connectionId: ${connectionId}, remaining participants: ${group.participants.size}`);
    }
  } else {
    removeRoomMember(ws, connectionId);
  }

  // 向当前连接发送断开连接消息
  safeSend(ws, { type: "disconnect", connectionId: connectionId });
  //RemoveHeartbeat(ws);
  // 记录断开连接的日志
  log(LogLevel.log, `Disconnect connectionId: ${connectionId}`);
}

/**
 * 处理offer信令（1对多模式）
 * host的offer转发给所有participants，participant的offer转发给host
 * @param ws WebSocket连接实例
 * @param message 消息数据
 */
function onOffer(ws: WebSocket, message: any): void {
  const connectionId = message.connectionId as string;
  const newOffer = new Offer(message.sdp, Date.now(), false);

  if (isPrivate) {
    if (connectionGroup.has(connectionId)) {
      const group = connectionGroup.get(connectionId);
      const senderParticipantId = getParticipantId(ws);
      const targetParticipantId = message.participantId;
      if (group.host === ws) {
        // host发送offer给特定participant（多peer模式下按participantId路由）
        newOffer.polite = true;
        if (targetParticipantId) {
          // 路由到指定participant
          const participantWs = findParticipantSocket(group, targetParticipantId);
          if (participantWs) {
            safeSend(participantWs, { from: connectionId, to: "", type: "offer", data: newOffer, participantId: targetParticipantId });
          }
        } else {
          // 兼容：无目标时广播给所有participants
          group.participants.forEach(participantWs => {
            const pid = getParticipantId(participantWs);
            safeSend(participantWs, { from: connectionId, to: "", type: "offer", data: newOffer, participantId: pid });
          });
        }
      } else {
        // participant发送offer给host，携带该participant的participantId
        // host端应为impolite（polite=false），确保perfect negotiation中host优先
        newOffer.polite = false;
        safeSend(group.host, { from: connectionId, to: "", type: "offer", data: newOffer, participantId: senderParticipantId });
      }
    }
    return;
  }

  // 公共模式：创建新的连接组（如果不存在）
  if (!connectionGroup.has(connectionId)) {
    connectionGroup.set(connectionId, { host: ws, participants: new Set<WebSocket>() });
  }
  saveRoomMember(ws, connectionId);
  // 向所有其他客户端广播offer
  clients.forEach((_v, k) => {
    if (k == ws) {
      return;
    }
    safeSend(k, { from: connectionId, to: "", type: "offer", data: newOffer });
  });
}

/**
 * 处理answer信令（1对多模式）
 * participant的answer转发给host
 * @param ws WebSocket连接实例
 * @param message 消息数据
 */
function onAnswer(ws: WebSocket, message: any): void {
  const connectionId = message.connectionId as string;
  const connectionIds = getOrCreateConnectionIds(ws);
  connectionIds.add(connectionId);
  const newAnswer = new Answer(message.sdp, Date.now());

  if (!connectionGroup.has(connectionId)) {
    return;
  }

  const group = connectionGroup.get(connectionId);
  const senderParticipantId = getParticipantId(ws);
  // 从answer消息中获取目标participantId（host回复时指定）
  const targetParticipantId = message.participantId;

  if (group.host === ws) {
    // host发送answer给特定participant
    if (targetParticipantId) {
      const participantWs = findParticipantSocket(group, targetParticipantId);
      if (participantWs) {
        safeSend(participantWs, { from: connectionId, to: "", type: "answer", data: newAnswer, participantId: targetParticipantId });
      }
    } else {
      // 兼容：没有targetParticipantId时广播给所有participants
      group.participants.forEach(participantWs => {
        safeSend(participantWs, { from: connectionId, to: "", type: "answer", data: newAnswer });
      });
    }
  } else {
    // participant发送answer给host，携带自己的participantId
    safeSend(group.host, { from: connectionId, to: "", type: "answer", data: newAnswer, participantId: senderParticipantId });
  }
}

/**
 * 处理candidate信令（1对多模式）
 * host的candidate转发给所有participants，participant的candidate转发给host
 * @param ws WebSocket连接实例
 * @param message 消息数据
 */
function onCandidate(ws: WebSocket, message: any): void {
  const connectionId = message.connectionId;
  const candidate = new Candidate(message.candidate, message.sdpMLineIndex, message.sdpMid, Date.now());
  const senderParticipantId = getParticipantId(ws);
  const targetParticipantId = message.participantId;

  if (isPrivate) {
    if (connectionGroup.has(connectionId)) {
      const group = connectionGroup.get(connectionId);
      if (group.host === ws) {
        // host发送candidate给特定participant
        if (targetParticipantId) {
          const participantWs = findParticipantSocket(group, targetParticipantId);
          if (participantWs) {
            safeSend(participantWs, { from: connectionId, to: "", type: "candidate", data: candidate, participantId: targetParticipantId });
          }
        } else {
          group.participants.forEach(participantWs => {
            safeSend(participantWs, { from: connectionId, to: "", type: "candidate", data: candidate });
          });
        }
      } else {
        // participant发送candidate给host，携带自己的participantId
        safeSend(group.host, { from: connectionId, to: "", type: "candidate", data: candidate, participantId: senderParticipantId });
      }
    }
    return;
  }
}

function onCallConnectionId(ws: WebSocket, message: any): void {
  // 获取连接ID
  const connectionId = message.connectionId;
  const clientId = message.clientId;
  // 在1对多模式下，通知host有新的呼叫请求
  if (connectionGroup.has(connectionId)) {
    const group = connectionGroup.get(connectionId);
    if (group.host !== ws) {
      // participant发起呼叫，通知host
      safeSend(group.host, { from: connectionId, to: "", type: "call-request", data: connectionId });
    }
  } else {
    // 兼容旧的广播方式
    clients.forEach((connectionIds, k) => {
      if (k === ws) {
        return;
      }
      if (connectionIds.has(clientId)) {
        safeSend(k, { from: connectionId, to: "", type: "call-request", data: connectionId });
      }
    });
  }
}
/**
 * 处理host-userInfo消息，更新host的用户信息
 * @param ws WebSocket连接实例
 * @param message 消息数据
 */
function onHostUserInfo(ws: WebSocket, message: any): void {
  setUserInfo(ws, {
    id: message.id || '',
    name: message.name || '匿名用户',
    avatar: message.avatar || ''
  });

  log(LogLevel.log, 'Updated current ws userInfo:', getUserInfo(ws));
}
function onInviteCall(ws: WebSocket, message: any): void {
  const connectionId = message.connectionId as string;
  const targetSocketId = message.targetSocketId as string;
  const targetUserId = message.targetUserId as string;

  let targetWs: WebSocket = null;
  clients.forEach((_connectionIds, clientWs) => {
    if (targetWs || clientWs === ws) {
      return;
    }

    const userInfo = getUserInfo(clientWs);
    if ((targetSocketId && getSocketId(clientWs) === targetSocketId) ||
        (targetUserId && userInfo.id === targetUserId)) {
      targetWs = clientWs;
    }
  });

  if (!targetWs) {
    safeSend(ws, {
      type: 'invite-failed',
      data: {
        connectionId,
        reason: 'target-offline'
      }
    });
    log(LogLevel.warn, `invite-call target not found: socketId=${targetSocketId}, userId=${targetUserId}`);
    return;
  }

  const inviterInfo = getUserInfo(ws);
  safeSend(targetWs, {
    type: 'invite-call',
    data: {
      connectionId,
      inviterSocketId: getSocketId(ws),
      inviterUserId: message.inviterUserId || inviterInfo.id || '',
      inviterName: message.inviterName || getUserInfo(ws).name || '邀请方',
      inviterAvatar: message.inviterAvatar || inviterInfo.avatar || '',
      applyReason: message.applyReason || message.reason || '',
      targetSocketId: targetSocketId || '',
      targetUserId: targetUserId || ''
    }
  });

  log(LogLevel.log, `Forwarded invite-call to socketId=${targetSocketId}, userId=${targetUserId}, connectionId=${connectionId}`);
}
/**
 * 处理广播消息请求（1对多模式）
 * @param ws WebSocket连接实例
 * @param message 消息数据
 */
function onBroadcast(ws: WebSocket, message: any): void {
  const broadcastMessage = message.message;
  const targetConnectionId = message.targetConnectionId;

  if (targetConnectionId) {
    // 向指定连接组广播
    if (connectionGroup.has(targetConnectionId)) {
      const group = connectionGroup.get(targetConnectionId);
      // 向组内所有成员发送消息
      safeSend(group.host, {
        type: "broadcast",
        message: broadcastMessage,
        from: "server"
      });
      group.participants.forEach(participantWs => {
        safeSend(participantWs, {
          type: "broadcast",
          message: broadcastMessage,
          from: "server"
        });
      });
    }
  } else {
    // 全局广播：向所有客户端发送消息
    clients.forEach((_v, k) => {
      safeSend(k, {
        type: "broadcast",
        message: broadcastMessage,
        from: "server"
      });
    });
  }
}

function AddHeartbeat(ws: WebSocket, connectionId: string) {
  // 初始化心跳检测
  asAppWebSocket(ws).lastActivity = Date.now();

  // 设置心跳检测定时器，每30秒发送一次ping
  asAppWebSocket(ws).heartbeatTimer = setInterval(() => {
    const now = Date.now();
    // 检查上次活动时间，如果超过60秒没有活动，关闭连接
    if (now - (asAppWebSocket(ws).lastActivity || 0) > 10000) {
      log(LogLevel.warn, 'WebSocket connection timeout, closing...');
      clearInterval(asAppWebSocket(ws).heartbeatTimer);
      //ws.close();
      onDisconnect(ws, connectionId);
    } else {
      // 发送ping消息
      safeSend(ws, { from: connectionId, to: "", type: "on-message", data: JSON.stringify({ type: "ping" }) });
      log(LogLevel.log, 'WebSocket connection heartbeat, lastActivity: ', asAppWebSocket(ws).lastActivity);
    }
  }, 3000);
}

function RemoveHeartbeat(ws: WebSocket) {
  // 清除心跳检测定时器
  if (asAppWebSocket(ws).heartbeatTimer) {
    clearInterval(asAppWebSocket(ws).heartbeatTimer);
  }
}

/**
 * 处理获取所有连接ID的请求
 * @param ws WebSocket连接实例
 */
function onGetAllConnectionIds(): string[] {
  // 获取所有connectionId
  const connectionIds = new Set<string>(Array.from(connectionGroup.keys()));
  rooms.forEach((_room, connectionId) => {
    connectionIds.add(connectionId);
  });
  return Array.from(connectionIds);
}

/**
 * 获取WebSocket连接当前角色
 * @param ws WebSocket连接实例
 * @param connectionIds 该连接关联的connectionId集合
 * @returns 用户角色
 */
function getSocketRole(ws: WebSocket, connectionIds: string[]): 'host' | 'participant' | 'idle' {
  for (const connectionId of connectionIds) {
    if (isHost(ws, connectionId)) {
      return 'host';
    }
    const group = connectionGroup.get(connectionId);
    if (group && group.participants.has(ws)) {
      return 'participant';
    }
  }
  return 'idle';
}

/**
 * 将WebSocket连接转换为在线用户信息
 * @param ws WebSocket连接实例
 * @returns 在线用户信息
 */
function toOnlineUser(ws: WebSocket): OnlineUser {
  const connectionIds = Array.from(clients.get(ws) || []);
  const userInfo = getUserInfo(ws);
  return {
    socketId: getSocketId(ws),
    connectionId: connectionIds[0] || '',
    participantId: getParticipantId(ws),
    role: getSocketRole(ws, connectionIds),
    userId: userInfo.id || '',
    name: userInfo.name || '',
    avatar: userInfo.avatar || ''
  };
}

/**
 * 获取在线WebSocket用户列表
 * @param connectionId 可选的连接ID，传入时仅返回关联该房间的在线用户
 * @returns 在线用户列表
 */
function onGetOnlineUsers(connectionId?: string): OnlineUser[] {
  const onlineUsers: OnlineUser[] = [];
  clients.forEach((connectionIds, ws) => {
    const ids = Array.from(connectionIds);
    if (connectionId && !ids.includes(connectionId)) {
      return;
    }
    onlineUsers.push(toOnlineUser(ws));
  });
  return onlineUsers;
}

function onGetRooms(connectionId?: string): RoomSnapshot[] {
  const roomSnapshots: RoomSnapshot[] = [];
  rooms.forEach((room, roomConnectionId) => {
    if (connectionId && roomConnectionId !== connectionId) {
      return;
    }
    roomSnapshots.push(toRoomSnapshot(room));
  });
  return roomSnapshots;
}

/**
 * 处理chat-message信令（1对多模式）
 * host的消息转发给所有participants，participant的消息转发给host
 * @param ws WebSocket连接实例
 * @param message 消息数据
 */
function onMessage(ws: WebSocket, message: any): void {
  // 获取连接ID
  const connectionId = message.connectionId;
  const chatMessage = message.message;
  const senderParticipantId = getParticipantId(ws);
  if (!connectionId || !chatMessage || typeof chatMessage !== 'object') {
    log(LogLevel.warn, 'Ignored malformed on-message payload:', message);
    return;
  }
  if (chatMessage && chatMessage.type === 'user-info' && chatMessage.data) {
    setUserInfo(ws, {
      id: chatMessage.data.id || '',
      name: chatMessage.data.name || '匿名用户',
      avatar: chatMessage.data.avatar || ''
    });
  }
  chatMessage.participantId = senderParticipantId;
  chatMessage.connectionId = connectionId;
  if (connectionGroup.has(connectionId)) {
    const group = connectionGroup.get(connectionId);
    if (group.host === ws) {
      // host发送消息，转发给所有participants
      group.participants.forEach(participantWs => {
        safeSend(participantWs, { from: connectionId, to: "", type: "on-message", data: JSON.stringify(chatMessage) });
      });
    } else {
      // participant发送消息，转发给host（附带participantId）和其他participants
      safeSend(group.host, { from: connectionId, to: "", type: "on-message", data: JSON.stringify(chatMessage), participantId: senderParticipantId });
      // 同时转发给其他participants（排除发送者自身）
      group.participants.forEach(participantWs => {
        if (participantWs !== ws) {
          safeSend(participantWs, { from: connectionId, to: "", type: "on-message", data: JSON.stringify(chatMessage), participantId: senderParticipantId });
        }
      });
    }
  }
}

/**
 * 导出WebSocket处理器函数
 */
export { reset, add, remove, onConnect, onDisconnect, onOffer, onAnswer, onCandidate, onCallConnectionId, 
  onBroadcast, onGetAllConnectionIds, onGetOnlineUsers, onGetRooms, AddHeartbeat, RemoveHeartbeat, onMessage, isHost, 
  broadcastToGroup, connectionGroup, onHostUserInfo, onInviteCall };
