import 'dart:async';

import 'package:electronic_assistant/data/repositories/account_repository.dart';
import 'package:electronic_assistant/device/atmob_platform_info.dart';
import 'package:electronic_assistant/utils/async_util.dart';
import 'package:electronic_assistant/utils/mmkv_util.dart';
import 'package:flutter/widgets.dart';
import 'package:gravity_engine/gravity_engine.dart';
import 'package:gravity_engine/gravity_engine_method_channel.dart';

import '../../data/api/response/user_info_response.dart';
import '../../data/consts/Constants.dart';
import '../../data/consts/build_config.dart';

typedef GravitySuccessCallback = void Function();

class GravityHelper {
  static const String _keyCurrentSsid = "current_ssid";
  static CancelableFuture<bool>? _initFuture;
  static String? _currentClientId;

  static bool? _isFromPromote;

  static init() async {
    _initialize(false);
  }

  static _initialize(bool refreshSSID,
      {GravitySuccessCallback? callback}) async {
    if (_initFuture != null) {
      _initFuture?.cancel();
    }
    _initFuture = AsyncUtil.retryWithExponentialBackoff<bool>(() async {
      String ssid = await _getSSID(refreshSSID);
      CancelableFuture<bool> initFuture = _gravityInitialize(ssid);
      _initFuture = initFuture;
      return await initFuture;
    }, 5);
    _initFuture?.then((isPromote) {
      _isFromPromote = isPromote;
      callback?.call();
    }).catchError((error) {
      _initialize(refreshSSID, callback: callback);
    });
  }

  static Future<String> _getSSID(bool refreshSSID) async {
    String? currentSSID = _getCurrentSSID();
    if (currentSSID == null || refreshSSID) {
      UserInfoResponse userInfo = await accountRepository.getUserInfo();
      KVUtil.putString(_keyCurrentSsid, userInfo.ssid);
      return userInfo.ssid;
    }
    return currentSSID;
  }

  static String? _getCurrentSSID() {
    return KVUtil.getString(_keyCurrentSsid, null);
  }

  static CancelableFuture<bool> _gravityInitialize(String ssid) {
    return AsyncUtil.retryWithExponentialBackoff<bool>(() {
      return GravityEngine.initialize(
              GravityConfig.gravityAppId,
              GravityConfig.gravityAccessToken,
              ssid,
              atmobPlatformInfo.channelName ?? '',
              BuildConfig.isDebug)
          .then((data) {
        debugPrint('gravity initialize($ssid) success');
        GravityHelper._currentClientId = ssid;
        return data;
      });
    }, 5);
  }

  static void onLogin() {
    _clearCurrentSSID();
    _initialize(true, callback: () {
      if (_currentClientId != null) {
        GravityEngine.login(_currentClientId!);
      }
    });
  }

  static void onLogout() async {
    _currentClientId = null;
    await GravityEngine.logout();
    _initialize(false, callback: null);
  }

  static void _clearCurrentSSID() {
    KVUtil.putString(_keyCurrentSsid, null);
  }

  static bool? getIsFromPromote() {
    return _isFromPromote;
  }

  static void report(String eventId, {Map<String, dynamic>? params}) {
    GravityEngine.trackEvent(eventId, eventProperties: params);
  }

  static void reportPay(
      int payAmount, String orderNo, String productName, int payWay) {
    PayType payType;
    if (payWay == PayMethod.alipay) {
      payType = PayType.alipay;
    } else if (payWay == PayMethod.wechat) {
      payType = PayType.wechat;
    } else if (payWay == PayMethod.apple) {
      payType = PayType.apple;
    } else {
      payType = PayType.unknown;
    }
    GravityEngine.trackPay(
        orderNo, productName, payAmount, Currency.cny, payType);
  }
}
