/// 自然写互动课堂手机端应用软件 V1.0
/// WebSocket实时通信服务 - 接收云端实时推送通知
///
/// 功能说明：
/// 1. WebSocket长连接管理（建立、维持、重连）
/// 2. 心跳机制（30秒间隔，检测连接存活性）
/// 3. 消息类型分发（新作业、批改完成、课堂互动、家校消息）
/// 4. 指数退避重连策略（断线后自动重连，逐步增加间隔）
/// 5. 消息ACK确认（确保重要消息不丢失）
/// 6. 离线消息补发（重连后请求离线期间的消息）

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

/* ========== 消息类型定义 ========== */

/// WebSocket消息类型枚举
enum WsMessageType {
  heartbeat,           // 心跳包
  heartbeatAck,        // 心跳响应
  newAssignment,       // 新作业通知
  gradeComplete,       // 批改完成通知
  classroomEvent,      // 课堂互动事件（发题/收卷等）
  parentMessage,       // 家校沟通消息
  systemNotice,        // 系统公告
  strokeRealtime,      // 实时笔迹数据（课堂模式）
  offlineSync,         // 离线消息同步
  ack,                 // 消息确认
}

/// WebSocket消息模型
class WsMessage {
  final String id;                   // 消息唯一ID
  final WsMessageType type;         // 消息类型
  final Map<String, dynamic> data;  // 消息内容
  final int timestamp;              // 服务端时间戳
  final bool requireAck;            // 是否需要ACK确认

  WsMessage({
    required this.id,
    required this.type,
    required this.data,
    required this.timestamp,
    this.requireAck = false,
  });

  /// 从JSON反序列化
  factory WsMessage.fromJson(Map<String, dynamic> json) {
    return WsMessage(
      id: json['id'] ?? '',
      type: _parseMessageType(json['type'] ?? ''),
      data: Map<String, dynamic>.from(json['data'] ?? {}),
      timestamp: json['timestamp'] ?? 0,
      requireAck: json['require_ack'] ?? false,
    );
  }

  /// 序列化为JSON
  Map<String, dynamic> toJson() => {
    'id': id,
    'type': type.name,
    'data': data,
    'timestamp': timestamp,
  };

  /// 解析消息类型字符串
  static WsMessageType _parseMessageType(String typeStr) {
    switch (typeStr) {
      case 'heartbeat': return WsMessageType.heartbeat;
      case 'heartbeat_ack': return WsMessageType.heartbeatAck;
      case 'new_assignment': return WsMessageType.newAssignment;
      case 'grade_complete': return WsMessageType.gradeComplete;
      case 'classroom_event': return WsMessageType.classroomEvent;
      case 'parent_message': return WsMessageType.parentMessage;
      case 'system_notice': return WsMessageType.systemNotice;
      case 'stroke_realtime': return WsMessageType.strokeRealtime;
      case 'offline_sync': return WsMessageType.offlineSync;
      case 'ack': return WsMessageType.ack;
      default: return WsMessageType.systemNotice;
    }
  }
}

/* ========== WebSocket连接状态 ========== */

/// 连接状态枚举
enum WsConnectionState {
  disconnected,     // 未连接
  connecting,       // 正在连接
  connected,        // 已连接
  reconnecting,     // 重连中
}

/* ========== WebSocket服务实现 ========== */

/// WebSocket实时通信服务
/// 维护与云平台的长连接，接收实时推送通知
class WebSocketService {
  /// WebSocket服务器地址
  static const String _wsUrl = 'wss://ws.writech.com/v1/notify';

  /// 心跳间隔（秒）
  static const int heartbeatIntervalSec = 30;

  /// 心跳超时时间（秒，超过此时间未收到心跳响应则认为连接断开）
  static const int heartbeatTimeoutSec = 45;

  /// 最大重连间隔（秒，指数退避上限）
  static const int maxReconnectIntervalSec = 60;

  /// WebSocket实例
  dynamic _webSocket;  // WebSocket

  /// 连接状态
  WsConnectionState _state = WsConnectionState.disconnected;

  /// 当前认证Token
  String _authToken = '';

  /// 心跳定时器
  Timer? _heartbeatTimer;

  /// 心跳超时定时器
  Timer? _heartbeatTimeoutTimer;

  /// 重连定时器
  Timer? _reconnectTimer;

  /// 当前重连尝试次数（用于指数退避计算）
  int _reconnectAttempts = 0;

  /// 最后收到消息的时间戳（用于离线消息补发）
  int _lastMessageTimestamp = 0;

  /// 消息分发回调注册表
  final Map<WsMessageType, List<Function(WsMessage)>> _handlers = {};

  /// 连接状态变化回调
  final List<Function(WsConnectionState)> _stateListeners = [];

  /// 待ACK的消息队列（消息ID -> 超时Timer）
  final Map<String, Timer> _pendingAcks = {};

  /// 获取当前连接状态
  WsConnectionState get state => _state;

  /// 设置认证Token（登录成功后调用）
  void setAuthToken(String token) {
    _authToken = token;
  }

  /// 注册消息处理器
  /// 同一类型可注册多个处理器，按注册顺序依次执行
  void on(WsMessageType type, Function(WsMessage) handler) {
    _handlers.putIfAbsent(type, () => []);
    _handlers[type]!.add(handler);
  }

  /// 移除消息处理器
  void off(WsMessageType type, Function(WsMessage) handler) {
    _handlers[type]?.remove(handler);
  }

  /// 监听连接状态变化
  void onStateChange(Function(WsConnectionState) listener) {
    _stateListeners.add(listener);
  }

  /// 建立WebSocket连接
  /// 附带认证Token和最后消息时间戳（用于离线消息补发）
  Future<void> connect() async {
    if (_state == WsConnectionState.connected || _state == WsConnectionState.connecting) {
      return;
    }

    _updateState(WsConnectionState.connecting);

    try {
      // 构造带认证参数的WebSocket URL
      final url = '$_wsUrl?token=$_authToken&last_ts=$_lastMessageTimestamp';

      // 建立WebSocket连接
      // 实际实现: _webSocket = await WebSocket.connect(url);
      print('[WebSocket] 正在连接: $_wsUrl');

      // 模拟连接成功
      await Future.delayed(const Duration(milliseconds: 300));

      _updateState(WsConnectionState.connected);
      _reconnectAttempts = 0; // 重置重连计数

      // 启动心跳机制
      _startHeartbeat();

      // 监听消息流
      // _webSocket.listen(_onMessage, onDone: _onDisconnected, onError: _onError);

      print('[WebSocket] 连接成功');
    } catch (e) {
      print('[WebSocket] 连接失败: $e');
      _updateState(WsConnectionState.disconnected);
      _scheduleReconnect();
    }
  }

  /// 处理接收到的WebSocket消息
  void _onMessage(dynamic rawData) {
    try {
      final json = jsonDecode(rawData as String) as Map<String, dynamic>;
      final message = WsMessage.fromJson(json);

      // 更新最后消息时间戳
      if (message.timestamp > _lastMessageTimestamp) {
        _lastMessageTimestamp = message.timestamp;
      }

      // 处理心跳响应
      if (message.type == WsMessageType.heartbeatAck) {
        _onHeartbeatAck();
        return;
      }

      // 处理ACK确认
      if (message.type == WsMessageType.ack) {
        _onAckReceived(message.data['ack_id'] ?? '');
        return;
      }

      // 如果消息需要ACK，发送确认
      if (message.requireAck) {
        _sendAck(message.id);
      }

      // 分发消息到注册的处理器
      _dispatchMessage(message);
    } catch (e) {
      print('[WebSocket] 消息解析失败: $e');
    }
  }

  /// 分发消息到对应类型的处理器
  void _dispatchMessage(WsMessage message) {
    final handlers = _handlers[message.type];
    if (handlers != null && handlers.isNotEmpty) {
      for (final handler in handlers) {
        try {
          handler(message);
        } catch (e) {
          print('[WebSocket] 消息处理器异常: $e');
        }
      }
    } else {
      print('[WebSocket] 未注册的消息类型: ${message.type}');
    }
  }

  /// 发送消息确认（ACK）
  void _sendAck(String messageId) {
    _send({
      'type': 'ack',
      'data': {'ack_id': messageId},
      'timestamp': DateTime.now().millisecondsSinceEpoch,
    });
  }

  /// 处理收到的ACK确认
  void _onAckReceived(String messageId) {
    _pendingAcks[messageId]?.cancel();
    _pendingAcks.remove(messageId);
  }

  /// 启动心跳机制
  /// 每30秒发送一次心跳包，45秒内未收到响应则断开重连
  void _startHeartbeat() {
    _stopHeartbeat();
    _heartbeatTimer = Timer.periodic(
      Duration(seconds: heartbeatIntervalSec),
      (_) => _sendHeartbeat(),
    );
  }

  /// 发送心跳包
  void _sendHeartbeat() {
    _send({
      'type': 'heartbeat',
      'timestamp': DateTime.now().millisecondsSinceEpoch,
    });

    // 设置心跳超时检测
    _heartbeatTimeoutTimer?.cancel();
    _heartbeatTimeoutTimer = Timer(
      Duration(seconds: heartbeatTimeoutSec),
      () {
        print('[WebSocket] 心跳超时，断开连接');
        _onDisconnected();
      },
    );
  }

  /// 收到心跳响应，取消超时计时器
  void _onHeartbeatAck() {
    _heartbeatTimeoutTimer?.cancel();
  }

  /// 停止心跳
  void _stopHeartbeat() {
    _heartbeatTimer?.cancel();
    _heartbeatTimer = null;
    _heartbeatTimeoutTimer?.cancel();
    _heartbeatTimeoutTimer = null;
  }

  /// 发送JSON数据
  void _send(Map<String, dynamic> data) {
    if (_state != WsConnectionState.connected) return;
    try {
      final jsonStr = jsonEncode(data);
      // 实际调用: _webSocket.add(jsonStr);
      print('[WebSocket] 发送: ${data['type']}');
    } catch (e) {
      print('[WebSocket] 发送失败: $e');
    }
  }

  /// 连接断开处理
  void _onDisconnected() {
    _stopHeartbeat();
    _updateState(WsConnectionState.disconnected);
    print('[WebSocket] 连接已断开');
    _scheduleReconnect();
  }

  /// 连接错误处理
  void _onError(dynamic error) {
    print('[WebSocket] 连接错误: $error');
    _onDisconnected();
  }

  /// 安排自动重连（指数退避策略）
  /// 间隔: 1s, 2s, 4s, 8s, 16s, 32s, 60s(上限)
  void _scheduleReconnect() {
    _reconnectTimer?.cancel();

    final interval = _calculateReconnectInterval();
    _updateState(WsConnectionState.reconnecting);
    print('[WebSocket] ${interval}秒后尝试重连 (第${_reconnectAttempts + 1}次)');

    _reconnectTimer = Timer(Duration(seconds: interval), () {
      _reconnectAttempts++;
      connect();
    });
  }

  /// 计算重连间隔（指数退避，上限60秒）
  int _calculateReconnectInterval() {
    final interval = 1 << _reconnectAttempts; // 2^n
    return interval > maxReconnectIntervalSec ? maxReconnectIntervalSec : interval;
  }

  /// 更新连接状态并通知监听器
  void _updateState(WsConnectionState newState) {
    if (_state == newState) return;
    _state = newState;
    for (final listener in _stateListeners) {
      try {
        listener(newState);
      } catch (e) {
        print('[WebSocket] 状态监听器异常: $e');
      }
    }
  }

  /// 主动重连（应用前台恢复时调用）
  void reconnect() {
    if (_state == WsConnectionState.connected) return;
    _reconnectAttempts = 0;
    connect();
  }

  /// 断开连接并释放资源
  void disconnect() {
    _reconnectTimer?.cancel();
    _reconnectTimer = null;
    _stopHeartbeat();

    // 取消所有待ACK的超时计时器
    for (final timer in _pendingAcks.values) {
      timer.cancel();
    }
    _pendingAcks.clear();

    // 关闭WebSocket连接
    // 实际调用: _webSocket?.close();
    _webSocket = null;

    _updateState(WsConnectionState.disconnected);
    print('[WebSocket] 已主动断开连接');
  }

  /// 销毁服务（释放所有资源和回调）
  void dispose() {
    disconnect();
    _handlers.clear();
    _stateListeners.clear();
  }
}
