/**
 * WebRTC signaling — browser device registration and WebSocket dispatch.
 *
 * This module handles ONLY the signaling side:
 * - Browser device registration/unregistration via WebSocket
 * - WS → deviceId mapping
 *
 * All WebRTC media logic (PeerConnection, RTP, transcoding, mixer wiring)
 * lives in the Rust proxy-engine. This module only tracks browser sessions.
 */

import { WebSocket } from 'ws';
import { registerBrowserDevice, unregisterBrowserDevice, shortHash } from './registrar.ts';

// ---------------------------------------------------------------------------
// Config
// ---------------------------------------------------------------------------

interface IWebRtcSignalingConfig {
  log: (msg: string) => void;
}

let config: IWebRtcSignalingConfig;

// ---------------------------------------------------------------------------
// State: WS ↔ deviceId mapping
// ---------------------------------------------------------------------------

const wsToSession = new WeakMap<WebSocket, string>();
const deviceIdToWs = new Map<string, WebSocket>();

// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------

export function initWebRtcSignaling(cfg: IWebRtcSignalingConfig): void {
  config = cfg;
}

/**
 * Handle a WebRTC signaling message from a browser client.
 * Only handles registration; offer/ice/hangup are routed through frontend.ts.
 */
export function handleWebRtcSignaling(
  ws: WebSocket,
  message: { type: string; sessionId?: string; [key: string]: any },
): void {
  const { type } = message;

  if (type === 'webrtc-register') {
    handleRegister(ws, message.sessionId!, message.userAgent, message._remoteIp);
  }
  // Other webrtc-* types (offer, ice, hangup, accept) are handled
  // by the frontend.ts WebSocket handler and forwarded to Rust.
}

/**
 * Send a message to a specific browser device by its device ID.
 */
export function sendToBrowserDevice(deviceId: string, data: unknown): boolean {
  const ws = deviceIdToWs.get(deviceId);
  if (!ws) return false;
  wsSend(ws, data);
  return true;
}

/**
 * Get all registered browser device IDs.
 */
export function getAllBrowserDeviceIds(): string[] {
  return [...deviceIdToWs.keys()];
}

// ---------------------------------------------------------------------------
// Registration
// ---------------------------------------------------------------------------

function handleRegister(ws: WebSocket, sessionId: string, userAgent?: string, remoteIp?: string): void {
  // Clean up any previous browser device from this same WS connection.
  const prevSession = wsToSession.get(ws);
  if (prevSession && prevSession !== sessionId) {
    unregisterBrowserDevice(prevSession);
  }

  unregisterBrowserDevice(sessionId);
  registerBrowserDevice(sessionId, userAgent, remoteIp);
  wsToSession.set(ws, sessionId);
  config.log(`[webrtc:${sessionId.slice(0, 8)}] browser registered as device`);

  const deviceId = `browser-${shortHash(sessionId)}`;
  deviceIdToWs.set(deviceId, ws);

  // Echo back the assigned device ID.
  wsSend(ws, { type: 'webrtc-registered', deviceId });

  // Only add close handler once per WS connection.
  if (!prevSession) {
    ws.on('close', () => {
      const sid = wsToSession.get(ws) || sessionId;
      config.log(`[webrtc:${sid.slice(0, 8)}] browser disconnected`);
      deviceIdToWs.delete(`browser-${shortHash(sid)}`);
      unregisterBrowserDevice(sid);
    });
  }
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function wsSend(ws: WebSocket, data: unknown): void {
  try {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify(data));
    }
  } catch { /* ignore */ }
}
