import 'dart:async';
import 'dart:convert';

import 'package:web_socket_channel/web_socket_channel.dart';

import '../domain/signal_message.dart';

/// 信令客户端，封装 WebSocket 连接与消息收发。
///
/// 鉴权方式：浏览器/移动端原生 WebSocket 均可在握手阶段通过子协议
/// （Sec-WebSocket-Protocol）传递 Bearer token：
///   WebSocketChannel.connect(uri, protocols: ['signal.v1', 'auth.`<token>`'])
/// 服务端从首子协议取出 auth.`<token>` 进行校验。
///
/// 不再发送 REGISTER —— 连接由服务端根据令牌身份自动完成，并下发 REGISTER_SUCCESS。
class SignalingClient {
  final String serverUrl;
  final String? token;

  WebSocketChannel? _channel;
  Timer? _heartbeatTimer;

  /// 收到信令消息回调（已解析为 SignalMessage）。
  void Function(SignalMessage message)? onMessage;

  /// 连接成功回调。
  void Function()? onConnected;

  /// 连接断开回调。
  void Function()? onDisconnected;

  /// 连接错误回调。
  void Function(String error)? onError;

  /// 令牌失效（关闭码 4001）：调用方应刷新令牌后重连。
  void Function()? onTokenExpired;

  /// 强制下线（关闭码 4003）：调用方应停止重连并跳登录。
  void Function()? onForceLogout;

  SignalingClient({required this.serverUrl, this.token});

  /// 建立 WebSocket 连接（携带 Bearer 子协议，不再发送 REGISTER）。
  void connect() {
    try {
      final uri = Uri.parse(serverUrl);
      final protocols = ['signal.v1'];
      if (token != null && token!.isNotEmpty) {
        protocols.add('auth.$token');
      }
      _channel = WebSocketChannel.connect(uri, protocols: protocols);

      _channel!.stream.listen(
        _onData,
        onDone: _onDone,
        onError: (Object e) => onError?.call(e.toString()),
        cancelOnError: false,
      );

      _startHeartbeat();
      onConnected?.call();
    } catch (e) {
      onError?.call(e.toString());
    }
  }

  void _onData(dynamic data) {
    if (data is! String) return;
    try {
      final map = jsonDecode(data) as Map<String, dynamic>;
      final message = SignalMessage.fromJson(map);
      onMessage?.call(message);
    } catch (_) {
      // 忽略无法解析的消息。
    }
  }

  void _onDone() {
    _stopHeartbeat();
    final code = _channel?.closeCode;
    if (code == 4001) {
      onTokenExpired?.call();
      return;
    }
    if (code == 4003) {
      onForceLogout?.call();
      return;
    }
    onDisconnected?.call();
  }

  void _startHeartbeat() {
    _stopHeartbeat();
    _heartbeatTimer = Timer.periodic(const Duration(seconds: 25), (_) {
      if (_channel != null) {
        try {
          _channel!.sink.add(jsonEncode({'type': 'PING'}));
        } catch (_) {}
      }
    });
  }

  void _stopHeartbeat() {
    _heartbeatTimer?.cancel();
    _heartbeatTimer = null;
  }

  /// 发送信令消息。
  void send(SignalMessage message) => _send(message);

  void _send(SignalMessage message) {
    _channel?.sink.add(jsonEncode(message.toJson()));
  }

  /// 关闭连接。
  void disconnect() {
    _stopHeartbeat();
    _channel?.sink.close();
    _channel = null;
  }

  bool get isConnected => _channel != null;
}
