// Implémentation par défaut du transport RawSocket, basée sur le paquet `ws` (Node).
// L'auth se fait en posant `Authorization: Bearer <token>` dans les en-têtes de l'upgrade HTTP
// (un navigateur enverrait le cookie ; un client Node passe le token ici). Isolé du cœur ws-client
// pour que celui-ci reste injectable et testable sans réseau.
import WebSocket, { type RawData } from 'ws';
import type { RawSocket, SocketFactory } from './ws-client.js';

/** Normalise un RawData (Buffer | ArrayBuffer | Buffer[]) en Uint8Array copiée (offset 0). */
function toUint8(data: RawData): Uint8Array {
  if (Array.isArray(data)) return new Uint8Array(Buffer.concat(data));
  if (data instanceof ArrayBuffer) return new Uint8Array(data);
  // Buffer (sous-classe de Uint8Array) : copie pour ne pas dépendre du buffer poolé réutilisé par ws.
  return new Uint8Array(data);
}

export const wsSocketFactory: SocketFactory = (wsUrl: string, token: string): RawSocket => {
  const socket = new WebSocket(wsUrl, { headers: { Authorization: `Bearer ${token}` } });
  return {
    send: (d) => socket.send(d),
    close: () => socket.close(),
    onOpen: (cb) => socket.on('open', cb),
    onText: (cb) =>
      socket.on('message', (data: RawData, isBinary: boolean) => {
        if (!isBinary) cb(toUint8(data).toString());
      }),
    onBinary: (cb) =>
      socket.on('message', (data: RawData, isBinary: boolean) => {
        if (isBinary) cb(toUint8(data));
      }),
    onClose: (cb) => socket.on('close', () => cb()),
    onError: (cb) => socket.on('error', (err: Error) => cb(err)),
  };
};
