import 'package:firebase_auth/firebase_auth.dart';
import 'package:guru_app/account/account_manager.dart';
import 'package:guru_app/account/model/account_profile.dart';
import 'package:guru_app/account/model/user.dart';
import 'package:guru_utils/auth/auth_credential_manager.dart';
import 'package:guru_utils/device/device_info.dart';
import 'package:guru_utils/property/app_property.dart';

/// Created by Haoyi on 6/3/21

class Account {
  final GuruUser? guruUser;
  final DeviceInfo? device;
  final AccountProfile? accountProfile;
  final User? firebaseUser;
  final Map<AuthType, Credential> credentials; // facebook, google, apple, anonymous

  @Deprecated("use guruUser instead")
  SaasUser? get saasUser => guruUser;

  String? get uid => guruUser?.uid;

  String? get nickname => accountProfile?.nickname;

  Account.restore(
      {this.guruUser,
      this.device,
      this.accountProfile,
      this.firebaseUser,
      this.credentials = const {}});
}

class AccountAuth {
  final GuruUser user;
  final Credential? credential;

  AccountAuth(this.user, {this.credential});

  bool get isValid => uid != null && uid != "";

  String? get saasToken => user.token;

  String? get uid => user.uid;

  // bool get existsFirebaseUser => firebaseUser != null;

  @override
  String toString() {
    return 'AccountAuth{user: $user}';
  }
}

class FirebaseAccountAuth {
  final GuruUser user;
  final User? firebaseUser;

  FirebaseAccountAuth(this.user, {this.firebaseUser});

  bool get isValid => uid != null && uid != "";

  String? get guruToken => user.token;

  String? get uid => user.uid;

  bool get existsFirebaseUser => firebaseUser != null;

  @override
  String toString() {
    return 'AccountAuth{user: $user}';
  }
}

abstract class IAccountAuthDelegate {
  /// 支持登陆的代理,这块不管返回不返回都会支持匿名登陆
  List<AuthCredentialDelegate> get supportedAuthCredentialDelegates =>
      AccountManager.defaultSupportedAuthCredentialDelegates;

  /// 返回设备共享的用户属性,在帐号切换的时候会保证这些 KEY，会保留下来
  /// 注意，这里尽量不要把用户相关的属性设到这里面，否则会出现不必要的问题
  Set<PropertyKey> get deviceSharedProperties => {};

  /// 这个方法调用时，中台会确保当前的数据系统是切换后的数据系统
  /// 因此可以放心使用模板的数据，当 processor 返回后，对应的数据系统将会被切换
  /// 因此确保 processor 返回后，数据系统已经切换到新用户的数据系统
  Future<bool> onLogin(GuruUser loginUser, Credential credential);

  /// 这个方法调用时，中台会确保当前的数据系统是切换前的数据系统
  /// 因此可以放心使用模板的数据，当 processor返回后，对应的数据系统将会被切换
  /// 因此确保 processor 返回前，数据系统已经完成老用户数据的迁移
  Future<bool> onLogout(GuruUser logoutUser);

  /// 当出现登陆冲突时，有可能当前是匿名帐号，而这时，中台模板会静默登入到新的帐号中
  /// 与此同时，中台会调用 onAnonymousLogout
  Future<bool> onAnonymousLogout(GuruUser logoutUser) async {
    return true;
  }

  /// 当 APP首次匿名登陆时，或当登陆一个没有绑定匿名Credential的帐号时，会在登出时重新登陆一个新的匿名帐号
  /// 中台在这种情况下会调用 onAnonymousLogin
  Future<bool> onAnonymousLogin(GuruUser loginUser, Credential credential) async {
    return true;
  }

  /// 当登陆时，有可能会出现帐号冲突，因此针对冲突可以选择切换帐号或者忽略
  /// 如果你选择切换帐号，那么你需要提供 onLogout 方法，用于处理老用户的数据迁移
  /// 返回值为是否继续
  Future<bool> onConflict();
}
