import 'package:networks_sdk/src/presentation/wiring/network_callbacks.dart';

/// WebSocket 配置
/// 非单例，由 App 层构造并注入到 SocketClient
///
/// 与 [ApiConfig] 设计一致：SDK 不依赖 Flutter，
/// 网络检测、生命周期等业务逻辑通过回调注入。
class SocketConfig {
  // ── 心跳 ──

  /// 应用层心跳间隔（定时发送 "ping" 字符串）
  final Duration heartbeatInterval;

  /// 底层 WebSocket ping 间隔（Dart WebSocket 自动管理）
  final Duration pingInterval;

  /// Pong 超时（超过此时间未收到 pong 则判定连接断开）
  final Duration pongTimeout;

  // ── 连接 ──

  /// 连接超时
  final Duration connectTimeout;

  /// 是否启用 WebSocket 压缩（permessage-deflate）
  final bool enableCompression;

  // ── 重连 ──

  /// 最大重连次数（0 = 不重连）
  ///
  /// 当 [unlimitedReconnect] 为 true 时此字段无效。
  final int maxReconnectAttempts;

  /// 最大重连延迟（指数退避上限）
  final Duration maxReconnectDelay;

  /// 是否自动重连
  final bool autoReconnect;

  /// 无限重连模式
  ///
  /// IM 场景建议开启：连接断开后始终尝试重连，不受
  /// [maxReconnectAttempts] 限制。退避延迟仍受
  /// [maxReconnectDelay] 约束。
  final bool unlimitedReconnect;

  // ── 回调 ──

  /// 日志输出回调（与 ApiConfig.onLog 同签名）
  final OnLog? onLog;

  /// 网络可用性查询（App 层注入，SDK 在重连前调用）
  /// 返回 true 表示网络可用，可以尝试重连
  final OnCheckNetworkAvailable? onCheckNetworkAvailable;

  /// 重连前回调
  ///
  /// 每次自动重连前调用（心跳超时、连接断开等触发的内部重连）。
  /// App 层用于：
  /// - 检查并刷新即将过期的 token（通过 [SocketClient.updateToken]）
  /// - 其他重连前准备工作
  ///
  /// 回调完成后才发起实际连接。如果回调抛出异常，本次重连跳过，
  /// 等下一轮退避定时器触发。
  final Future<void> Function()? onBeforeReconnect;

  // ── 加密回调（预留给 cipher_guard_sdk）──

  /// 连接 URL 构建回调
  ///
  /// 建立连接前调用，接收原始 URL 和 token，返回最终连接 URL 字符串。
  /// null 时使用默认行为（URL 后追加 `?token=xxx`）。
  ///
  /// App 层注入 cipher_guard_sdk 的加密逻辑：路径/token 加密、
  /// 添加 `cipher=true` 参数等。
  final OnBuildConnectUrl? onBuildConnectUrl;

  /// 发送前加密回调，null 时不加密
  final OnEncryptMessage? onEncryptMessage;

  /// 收到后解密回调，null 时不解密
  final OnDecryptMessage? onDecryptMessage;

  SocketConfig({
    this.heartbeatInterval = const Duration(seconds: 10),
    this.pingInterval = const Duration(seconds: 5),
    this.pongTimeout = const Duration(seconds: 10),
    this.connectTimeout = const Duration(seconds: 15),
    this.enableCompression = false,
    this.maxReconnectAttempts = 5,
    this.maxReconnectDelay = const Duration(seconds: 30),
    this.autoReconnect = true,
    this.unlimitedReconnect = false,
    this.onLog,
    this.onCheckNetworkAvailable,
    this.onBeforeReconnect,
    this.onBuildConnectUrl,
    this.onEncryptMessage,
    this.onDecryptMessage,
  });
}
