// Lightweight ws shim for CF Workers — uses native WebSocket
// Avoids bundling the full 128KB ws package (pulled by ethers)

class WebSocketShim {
  static CONNECTING = 0;
  static OPEN = 1;
  static CLOSING = 2;
  static CLOSED = 3;

  CONNECTING = 0;
  OPEN = 1;
  CLOSING = 2;
  CLOSED = 3;

  _ws: WebSocket | null = null;
  readyState = 0;

  onopen: ((ev: any) => void) | null = null;
  onclose: ((ev: any) => void) | null = null;
  onmessage: ((ev: any) => void) | null = null;
  onerror: ((ev: any) => void) | null = null;

  constructor(url: string, protocols?: string | string[]) {
    try {
      this._ws = new WebSocket(url, protocols);
      this._ws.addEventListener('open', (ev) => {
        this.readyState = 1;
        this.onopen?.(ev);
      });
      this._ws.addEventListener('close', (ev) => {
        this.readyState = 3;
        this.onclose?.(ev);
      });
      this._ws.addEventListener('message', (ev) => {
        this.onmessage?.(ev);
      });
      this._ws.addEventListener('error', (ev) => {
        this.onerror?.(ev);
      });
    } catch (e) {
      this.readyState = 3;
    }
  }

  send(data: any) {
    this._ws?.send(data);
  }

  close(code?: number, reason?: string) {
    this.readyState = 2;
    this._ws?.close(code, reason);
  }

  addEventListener(type: string, listener: any) {
    this._ws?.addEventListener(type, listener);
  }

  removeEventListener(type: string, listener: any) {
    this._ws?.removeEventListener(type, listener);
  }

  on(event: string, listener: any) {
    if (event === 'open') this.onopen = listener;
    else if (event === 'close') this.onclose = listener;
    else if (event === 'message') this.onmessage = listener;
    else if (event === 'error') this.onerror = listener;
    return this;
  }

  off(_event: string, _listener: any) {
    return this;
  }

  once(event: string, listener: any) {
    const wrapped = (...args: any[]) => {
      this.off(event, wrapped);
      listener(...args);
    };
    return this.on(event, wrapped);
  }

  terminate() {
    this.close();
  }

  ping() {}
  pong() {}
}

// WebSocket.Server stub — not used in CF Workers
class ServerStub {
  constructor(_opts?: any) {}
  on() { return this; }
  close() {}
  address() { return { port: 0 }; }
}

(WebSocketShim as any).Server = ServerStub;
(WebSocketShim as any).WebSocket = WebSocketShim;
(WebSocketShim as any).WebSocketServer = ServerStub;
(WebSocketShim as any).createWebSocketStream = () => { throw new Error('Not supported in CF Workers'); };

export = WebSocketShim;
