/// Created by Haoyi on 2021/7/26

part of "account_manager.dart";

extension AccountAuthExtension on AccountManager {
  Future<FirebaseAccountAuth> _loginFirebase(GuruUser guruUser,
      {bool canRefreshFirebaseToken = true}) async {
    User? firebaseUser;
    GuruUser newGuruUser = guruUser;
    firebaseUser = await _authenticateFirebase(guruUser).catchError((error) {
      Log.e("_authenticateFirebase error! $error", tag: "Account");
      return null;
    });
    if (firebaseUser == null && canRefreshFirebaseToken) {
      try {
        newGuruUser = await _refreshFirebaseToken(guruUser);
        return _loginFirebase(newGuruUser, canRefreshFirebaseToken: false);
      } catch (error, stacktrace) {
        return FirebaseAccountAuth(guruUser, firebaseUser: null);
      }
    }

    return FirebaseAccountAuth(newGuruUser, firebaseUser: firebaseUser);
  }

  Future<GuruUser> _refreshFirebaseToken(GuruUser oldSaasUser) async {
    return await GuruApi.instance
        .renewFirebaseToken()
        .then((tokenData) => oldSaasUser.copyWith(firebaseToken: tokenData.firebaseToken));
  }

  Future<User?> _authenticateFirebase(GuruUser guruUser) async {
    int retry = 0;
    dynamic lastError;
    while (retry < 1) {
      try {
        Log.i("[$retry] _authenticateFirebase:${guruUser.firebaseToken}", tag: "Account");

        return await FirebaseAuth.instance
            .signInWithCustomToken(guruUser.firebaseToken)
            .then((result) => result.user);
      } catch (error, stacktrace) {
        await Future.delayed(const Duration(milliseconds: 600));
        retry++;
        Log.i("[$retry] _authenticateFirebase error :$error, $stacktrace", tag: "Account");
        lastError = error;
      }
    }
    throw lastError ?? ("_authenticateFirebase error!");
  }

  Future<bool> authenticateFirebase() async {
    final guruUser = accountDataStore.user;
    if (guruUser == null) {
      return false;
    }
    try {
      final auth = await _loginFirebase(guruUser);
      final newGuruUser = auth.user;
      if (!guruUser.isSame(newGuruUser)) {
        _updateGuruUser(newGuruUser);
      }
      if (auth.firebaseUser != null) {
        _updateFirebaseUser(auth.firebaseUser!);
        Log.i("_updateFirebaseUser success!", tag: "Account");
      }
      return true;
    } catch (error, stacktrace) {
      GuruAnalytics.instance.logException(error, stacktrace: stacktrace);
    }
    return false;
  }
}
