// 信令客户端：对应 Android 端 WebSocketClient / Flutter signaling_client.dart。
//
// 鉴权方式：浏览器原生 WebSocket 无法在握手阶段自定义请求头，
// 因此将 accessToken 通过子协议（Sec-WebSocket-Protocol）传递：
//   new WebSocket(url, ['signal.v1', 'auth.' + token])
// 服务端从首子协议取出 auth.<token> 进行 Bearer 校验。
//
// 不再发送 REGISTER —— 连接由服务端根据令牌身份自动完成，并下发 REGISTER_SUCCESS。
import { getAccessToken, refresh } from './ApiClient';

export class SignalingClient {
  constructor({ serverUrl, onConnected, onDisconnected, onError, onMessage, onTokenExpired, onForceLogout }) {
    this.serverUrl = serverUrl;
    this.onConnected = onConnected;
    this.onDisconnected = onDisconnected;
    this.onError = onError;
    this.onMessage = onMessage;
    // 令牌过期（4001）：调用方应刷新令牌后重连。
    this.onTokenExpired = onTokenExpired;
    // 强制下线（4003）：调用方应停止重连并跳回登录。
    this.onForceLogout = onForceLogout;
    this.ws = null;
    this.deviceId = '';
  }

  connect() {
    try {
      const token = getAccessToken();
      // 子协议携带版本标识与 Bearer token。
      const protocols = ['signal.v1'];
      if (token) protocols.push('auth.' + token);
      this.ws = new WebSocket(this.serverUrl, protocols);
      this.ws.onopen = () => {
        this._startHeartbeat();
        this.onConnected && this.onConnected();
      };
      this.ws.onmessage = (ev) => {
        let msg;
        try {
          msg = JSON.parse(ev.data);
        } catch {
          return;
        }
        // 记录服务端下发的本机 fromDeviceId（REGISTER_SUCCESS）。
        if (msg.type === 'REGISTER_SUCCESS' && msg.fromDeviceId) {
          this.deviceId = msg.fromDeviceId;
        }
        this.onMessage && this.onMessage(msg);
      };
      this.ws.onclose = (ev) => {
        this._stopHeartbeat();
        console.warn('[信令] WebSocket 已关闭 code=%d reason=%s wasClean=%s',
          ev.code, ev.reason || '(无)', ev.wasClean);
        if (ev.code === 4001) {
          // 令牌失效：先尝试刷新，刷新成功由调用方重连；失败则跳登录。
          (this.onTokenExpired || this.onDisconnected)?.(ev.reason);
          return;
        }
        if (ev.code === 4003) {
          // 强制下线：停止重连，跳回登录。
          (this.onForceLogout || this.onDisconnected)?.(ev.reason);
          return;
        }
        this.onDisconnected && this.onDisconnected(ev.code, ev.reason);
      };
      this.ws.onerror = (e) => {
        console.error('[信令] WebSocket 错误', e);
        this.onError && this.onError(e?.message || 'WebSocket 错误');
      };
    } catch (e) {
      this.onError && this.onError(e.message);
    }
  }

  _startHeartbeat() {
    this._stopHeartbeat();
    // 每 25 秒发送 PING，保持连接活跃（服务端忽略未知类型）。
    this._heartbeatTimer = setInterval(() => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        try { this.ws.send(JSON.stringify({ type: 'PING' })); } catch { /* ignore */ }
      }
    }, 25000);
  }

  _stopHeartbeat() {
    if (this._heartbeatTimer) { clearInterval(this._heartbeatTimer); this._heartbeatTimer = null; }
  }

  requestDeviceList() {
    // 服务端不再接受 DEVICE_LIST 枚举；控制端改用 HTTP /api/client/bindings 拉取绑定设备。
    this.send({ type: 'DEVICE_LIST' });
  }

  sendOffer(sdp, toDeviceId, authType = null, authValue = null) {
    const msg = {
      type: 'OFFER',
      toDeviceId,
      deviceType: 'CONTROLLER',
      payload: JSON.stringify({ sdp }),
    };
    if (authType) msg.authType = authType;
    if (authValue != null) msg.authValue = authValue;
    this.send(msg);
  }

  sendIceCandidate(candidate, toDeviceId) {
    const payload = {
      sdpMid: candidate.sdpMid,
      sdpMLineIndex: candidate.sdpMLineIndex,
      candidate: candidate.candidate,
    };
    this.send({
      type: 'ICE_CANDIDATE',
      toDeviceId,
      deviceType: 'CONTROLLER',
      payload: JSON.stringify(payload),
    });
  }

  send(msg) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(msg));
    }
  }

  disconnect() {
    this._stopHeartbeat();
    if (this.ws) {
      try { this.ws.close(1000, 'Disconnecting'); } catch { /* ignore */ }
      this.ws = null;
    }
  }

  get isConnected() {
    return this.ws && this.ws.readyState === WebSocket.OPEN;
  }
}
