import 'dart:async';

import 'package:connectivity_plus/connectivity_plus.dart';

/// 网络状态监听
///
/// 基于 connectivity_plus 监听平台网络变化，
/// 提供 [isConnected] 查询和 [onStatusChanged] 事件流。
///
/// 非单例，由 Riverpod Provider 构造注入。
///
/// ## 数据流位置
///
/// ```
/// connectivity_plus（平台网络事件）
///   → ★ NetworkMonitor ★                ← 你在这里
///     → SocketManager.handleNetworkStatusChanged()
///       → SocketClient.connect / disconnect
/// ```
///
/// ## 使用
///
/// ```dart
/// final monitor = ref.read(networkMonitorProvider);
/// monitor.onStatusChanged.listen((isAvailable) {
///   // 网络状态变化
/// });
/// ```
class NetworkMonitor {
  final Connectivity _connectivity = Connectivity();
  StreamSubscription<List<ConnectivityResult>>? _subscription;

  List<ConnectivityResult> _results = [];

  final _statusController = StreamController<bool>.broadcast();

  /// 日志输出回调
  final void Function(String message, {String? tag})? onLog;

  NetworkMonitor({this.onLog});

  /// 当前是否有网络连接
  ///
  /// 排除无连接和仅蓝牙连接的情况。
  bool get isConnected {
    if (_results.isEmpty) return false;
    return !_results.contains(ConnectivityResult.none) &&
        !_results.every((r) => r == ConnectivityResult.bluetooth);
  }

  /// 网络状态变化流
  ///
  /// 只在连接状态真正改变时发送事件（connected ↔ disconnected），
  /// 同类型切换（WiFi → 4G）不会触发。
  Stream<bool> get onStatusChanged => _statusController.stream;

  /// 初始化监听
  ///
  /// App 启动时调用一次。获取当前状态并开始监听变化。
  Future<void> initialize() async {
    try {
      _results = await _connectivity.checkConnectivity();
      _log('Network status: $_connectionDescription');
    } catch (e) {
      _log('Failed to check connectivity: $e');
      _results = [ConnectivityResult.none];
    }

    _subscription = _connectivity.onConnectivityChanged.listen(
      _onChanged,
      onError: (Object error) {
        _log('Connectivity listener error: $error');
      },
    );
  }

  /// 释放资源
  void dispose() {
    _subscription?.cancel();
    _statusController.close();
  }

  // ── 内部 ──────────────────────────────────────────────────────────────────

  void _onChanged(List<ConnectivityResult> results) {
    final wasConnected = isConnected;
    _results = results;
    final nowConnected = isConnected;

    _log('Network changed: $_connectionDescription');

    // 只在真正切换时通知
    if (wasConnected != nowConnected) {
      _statusController.add(nowConnected);
      _log(nowConnected ? 'Network restored' : 'Network lost');
    }
  }

  String get _connectionDescription {
    if (_results.contains(ConnectivityResult.wifi)) return 'WiFi';
    if (_results.contains(ConnectivityResult.mobile)) return 'Mobile';
    if (_results.contains(ConnectivityResult.ethernet)) return 'Ethernet';
    if (_results.contains(ConnectivityResult.none)) return 'None';
    return 'Unknown';
  }

  void _log(String message) {
    onLog?.call(message, tag: 'Network');
  }
}
