import 'package:flutter/cupertino.dart';
import 'package:injectable/injectable.dart';
import 'package:location/data/api/atmob_api.dart';
import 'package:location/di/get_it.dart';
import 'package:location/utils/async_util.dart';
import 'package:location/utils/date_util.dart';
import 'package:mobile_use_statistics/flutter_mobile_statistics.dart';
import 'package:battery_plus/battery_plus.dart';
import '../../utils/atmob_log.dart';
import '../../utils/http_handler.dart';
import '../api/request/electric_request.dart';
import '../api/request/location_phone_event_request.dart';
import '../bean/phone_event_bean.dart';
import 'account_repository.dart';
import 'dart:async';

@lazySingleton
class PhoneEventRepository {
  final AtmobApi atmobApi;

  static final String tag = 'PhoneEventRepository';

  Duration _taskIntervalTime = Duration(minutes: 5);
  Timer? _reportTimer;

  CancelableFuture? lockScreenCancelableFuture;
  CancelableFuture? batteryCancelableFuture;

  final battery = Battery();

  PhoneEventRepository(this.atmobApi) {
    startReportPhoneEvent();
  }

  static PhoneEventRepository getInstance() {
    return getIt.get<PhoneEventRepository>();
  }

  static Future<bool> hasUseStatisticsPermission() {
    return MobileUseStatistics.hasUseStatisticsPermission();
  }

  static Future<bool> requestUseStatisticsPermission() async {
    final hasPermission =
        await MobileUseStatistics.requestUseStatisticsPermission();
    if (hasPermission) {
      PhoneEventRepository.getInstance().startReportPhoneEvent();
    }
    return hasPermission;
  }

  void setTaskIntervalTime(Duration duration) {
    _taskIntervalTime = duration;
    if (_reportTimer != null && _reportTimer!.isActive) {
      _reportTimer!.cancel();
      _schedulePeriodicReport();
    }
  }

  //开始事件上报 ，锁屏事件以及手机电量等
  void startReportPhoneEvent() {
    if (AccountRepository.token == null ||
        AccountRepository.token?.isEmpty == true) {
      return;
    }
    _runReportTasks();
    _schedulePeriodicReport();
  }

  void _schedulePeriodicReport() {
    AtmobLog.d(tag, '_schedulePeriodicReport');
    _reportTimer?.cancel();
    _reportTimer = Timer.periodic(_taskIntervalTime, (_) => _runReportTasks());
  }

  void _runReportTasks() {
    //上报手机锁屏事件上报
    _startLockScreenEvent();
    //上报手机电量
    _startPhoneElectricEvent();
  }

  void _startPhoneElectricEvent() {
    AtmobLog.d(tag, '_startPhoneElectricEvent');
    batteryCancelableFuture?.cancel();
    batteryCancelableFuture = AsyncUtil.retryWithExponentialBackoff(
        () => _commitBatteryEvent(), 4,
        initialInterval: Duration(seconds: 3));
    batteryCancelableFuture!.catchError((error) {
      AtmobLog.d(tag, ' startPhoneElectricEvent 重试最大次数 异常 error:$error');
      _startPhoneElectricEvent();
    });
  }

  Future<void> _commitBatteryEvent() async {
    int batteryValue = await getBatteryLevel();
    return _electricReport(batteryValue);
  }

  ///停止事件上报
  ///
  void stopReportPhoneEvent() {
    AtmobLog.d(tag, 'stopReportPhoneEvent');
    _reportTimer?.cancel();
    lockScreenCancelableFuture?.cancel();
    batteryCancelableFuture?.cancel();
  }

  void _startLockScreenEvent() async {
    //判断是否有事件上报权限
    if (!await hasUseStatisticsPermission()) {
      return;
    }
    AtmobLog.d(tag, '_startLockScreenEvent');
    lockScreenCancelableFuture?.cancel();
    lockScreenCancelableFuture = AsyncUtil.retryWithExponentialBackoff(
        () => _commitLockScreenEvent(), 4,
        initialInterval: Duration(seconds: 3));
    lockScreenCancelableFuture!.catchError((error) {
      AtmobLog.d(tag, 'startLockScreenEvent 重试最大次数 异常 error:$error');
      startReportPhoneEvent();
    });
  }

  Future<void> _commitLockScreenEvent() async {
    //收集手机事件数据上报
    DateTime now = DateUtil.getNow();
    final startTime =
        DateUtil.getStartOfDayTimestamp(now).millisecondsSinceEpoch;
    final endTime = DateUtil.getEndOfDayTimestamp(now).millisecondsSinceEpoch;
    final eventList = await MobileUseStatistics.getLockScreenStatistics(
        startTime: startTime, endTime: endTime);
    final events = eventList
        ?.map((event) =>
            PhoneEventBean(startTime: event.startTime, endTime: event.endTime))
        .toList();

    if (events == null || events.isEmpty) {
      return;
    }
    return _locationPhoneEvent(events);
  }

  // 获取电量百分比
  Future<int> getBatteryLevel() async {
    final level = await battery.batteryLevel;
    debugPrint('Battery level: $level%');
    return level;
  }

  Future<void> _locationPhoneEvent(List<PhoneEventBean> events) {
    return atmobApi
        .locationPhoneEvent(LocationPhoneEventRequest(events))
        .then(HttpHandler.handle(true));
  }

  Future<void> _electricReport(int electric) {
    return atmobApi
        .electricReport(ElectricRequest(electric))
        .then(HttpHandler.handle(true));
  }
}
