const { WebSocket } = require('ws');

function log(tag, msg) {
  const ts = new Date().toISOString().slice(11, 23);
  console.log(`[${ts}] [${tag}] ${msg}`);
}

class RelayHandler {
  constructor(roomManager) {
    this.roomManager = roomManager;
    this._packetCount = 0;
  }

  handlePacket(ws, data) {
    if (!ws.roomCode) {
      log('RELAY', `Binary from player=${ws.playerId} but no room!`);
      return;
    }

    const room = this.roomManager.getRoom(ws.roomCode);
    if (!room || room.state !== 'playing') {
      log('RELAY', `Binary from player=${ws.playerId} but room state=${room?.state || 'null'}`);
      return;
    }

    const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);

    if (buffer.length < 2) return;

    const target = buffer[0];
    const payload = buffer.slice(1);

    // Prepend sender ID so receiver knows who sent it
    const relayedPacket = Buffer.alloc(payload.length + 2);
    relayedPacket.writeUInt16LE(ws.playerId, 0);
    payload.copy(relayedPacket, 2);

    this._packetCount++;
    if (this._packetCount <= 20 || this._packetCount % 100 === 0) {
      log('RELAY', `#${this._packetCount} from=${ws.playerId} target=0x${target.toString(16)} len=${buffer.length} room=${ws.roomCode}`);
    }

    switch (target) {
      case 0x00: // Broadcast to all except sender
        this.broadcastExcept(room, ws.playerId, relayedPacket);
        break;

      case 0x01: // To host only
        this.sendToHost(room, relayedPacket);
        break;

      case 0xFF: // From host to all clients
        this.broadcastExcept(room, ws.playerId, relayedPacket);
        break;

      default: // To specific player
        this.sendToPlayer(room, target, relayedPacket);
        break;
    }
  }

  broadcastExcept(room, excludeId, data) {
    room.players.forEach(p => {
      if (p.id !== excludeId && p.ws.readyState === WebSocket.OPEN) {
        p.ws.send(data);
      }
    });
  }

  sendToHost(room, data) {
    const hostId = room.getHostId();
    if (hostId) {
      this.sendToPlayer(room, hostId, data);
    }
  }

  sendToPlayer(room, playerId, data) {
    const ws = room.getPlayerWs(playerId);
    if (ws && ws.readyState === WebSocket.OPEN) {
      ws.send(data);
    }
  }
}

module.exports = { RelayHandler };
