import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:dio/dio.dart';
import '../session/session_manager.dart';
import '../session/session_events.dart';
import 'presence_config.dart';

/// 心跳服务
class HeartbeatService {
  static HeartbeatService? _instance;

  HeartbeatService._();

  factory HeartbeatService() {
    _instance ??= HeartbeatService._();
    return _instance!;
  }

  PresenceConfig _config = PresenceConfig.defaultConfig;

  Timer? _heartbeatTimer;

  bool _isRunning = false;
  bool get isRunning => _isRunning;

  DateTime? _lastHeartbeatAt;
  DateTime? get lastHeartbeatAt => _lastHeartbeatAt;

  int _heartbeatCount = 0;
  int get heartbeatCount => _heartbeatCount;

  // 回调函数，用于获取运行时数据
  String Function()? getInstallId;
  String? Function()? getUserId;
  String Function()? getAppVersion;
  Map<String, String> Function()? getAuthHeaders;

  late Dio _dio;

  bool _isInitialized = false;

  void initialize({
    required String apiBaseUrl,
    PresenceConfig? config,
    required String Function() getInstallId,
    required String? Function() getUserId,
    required String Function() getAppVersion,
    Map<String, String> Function()? getAuthHeaders,
  }) {
    if (_isInitialized) return;

    _config = config ?? PresenceConfig.defaultConfig;
    this.getInstallId = getInstallId;
    this.getUserId = getUserId;
    this.getAppVersion = getAppVersion;
    this.getAuthHeaders = getAuthHeaders;

    _dio = Dio(BaseOptions(
      baseUrl: apiBaseUrl,
      connectTimeout: const Duration(seconds: 5),
      receiveTimeout: const Duration(seconds: 5),
    ));

    final sessionManager = SessionManager();
    sessionManager.onSessionStart = _onSessionStart;
    sessionManager.onSessionEnd = _onSessionEnd;

    if (sessionManager.state == SessionState.foreground) {
      _startHeartbeat();
    }

    _isInitialized = true;
    debugPrint('[Heartbeat] Initialized, interval: ${_config.heartbeatIntervalSeconds}s');
  }

  void updateConfig(PresenceConfig config) {
    final wasRunning = _isRunning;

    if (wasRunning) {
      _stopHeartbeat();
    }

    _config = config;

    if (wasRunning && _config.enabled) {
      _startHeartbeat();
    }

    debugPrint('[Heartbeat] Config updated');
  }

  void dispose() {
    _stopHeartbeat();
    _isInitialized = false;
    _instance = null;
    debugPrint('[Heartbeat] Disposed');
  }

  void _onSessionStart() {
    if (_config.enabled) {
      _startHeartbeat();
    }
  }

  void _onSessionEnd() {
    _stopHeartbeat();
  }

  void _startHeartbeat() {
    if (_isRunning) return;
    if (!_config.enabled) return;

    _isRunning = true;
    _heartbeatCount = 0;

    _sendHeartbeat();

    _heartbeatTimer = Timer.periodic(
      Duration(seconds: _config.heartbeatIntervalSeconds),
      (_) => _sendHeartbeat(),
    );

    debugPrint('[Heartbeat] Started');
  }

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

    debugPrint('[Heartbeat] Stopped (count: $_heartbeatCount)');
  }

  Future<void> _sendHeartbeat() async {
    if (_config.requiresAuth && (getUserId?.call() == null)) {
      debugPrint('[Heartbeat] Skipped: user not logged in');
      return;
    }

    try {
      final response = await _dio.post(
        '/api/v1/presence/heartbeat',
        data: {
          'installId': getInstallId?.call() ?? '',
          'appVersion': getAppVersion?.call() ?? '',
          'clientTs': DateTime.now().millisecondsSinceEpoch ~/ 1000,
        },
        options: Options(
          headers: getAuthHeaders?.call(),
        ),
      );

      if (response.statusCode == 200) {
        _lastHeartbeatAt = DateTime.now();
        _heartbeatCount++;
        debugPrint('[Heartbeat] Sent #$_heartbeatCount');
      }
    } on DioException catch (e) {
      debugPrint('[Heartbeat] Failed (DioException): ${e.message}');
    } catch (e) {
      debugPrint('[Heartbeat] Failed: $e');
    }
  }

  @visibleForTesting
  Future<void> forceHeartbeat() async {
    await _sendHeartbeat();
  }
}
