/// Created by Haoyi on 6/3/21
part of "../app_property.dart";

extension AccountPropertyExtension on AppProperty {
  Future setAccountGuruUser(GuruUser guruUser) async {
    final data = jsonEncode(guruUser);
    await setString(PropertyKeys.accountGuruUser, data);
  }

  Future setAccountDevice(DeviceInfo deviceInfo) async {
    final data = jsonEncode(deviceInfo);
    await setString(PropertyKeys.accountDevice, data);
  }

  Future setAccountProfile(AccountProfile accountProfile) async {
    final data = jsonEncode(accountProfile);
    await setString(PropertyKeys.accountProfile, data);
  }

  // refer updateLocalProfile
  Future setDirtyAccountProfile(AccountProfile accountProfile) async {
    final data = jsonEncode(accountProfile.copyWith(dirty: true));
    await setString(PropertyKeys.accountProfile, data);
  }

  Future<DeviceInfo?> getAccountDevice() async {
    final deviceString = await getString(PropertyKeys.accountDevice, defValue: '');
    if (deviceString == "") {
      return null;
    }
    final map = jsonDecode(deviceString);
    return DeviceInfo.fromJson(map);
  }

  Future<Account> loadAccount() async {
    final accountBundle = await loadValuesByTag(PropertyTags.account).catchError((error) {
      Log.v("loadValuesByTag is empty, $error");
      return PropertyBundle.empty();
    });
    GuruUser? guruUser;
    DeviceInfo? device;
    AccountProfile? accountProfile;

    final saasUserString = accountBundle.getString(PropertyKeys.accountGuruUser);
    if (DartExt.isNotBlank(saasUserString)) {
      final map = jsonDecode(saasUserString!);
      guruUser = GuruUser.fromJson(map);
    }

    final accountDeviceString = accountBundle.getString(PropertyKeys.accountDevice);
    if (DartExt.isNotBlank(accountDeviceString)) {
      final map = jsonDecode(accountDeviceString!);
      device = DeviceInfo.fromJson(map);
    }

    final accountProfileString = accountBundle.getString(PropertyKeys.accountProfile);
    if (DartExt.isNotBlank(accountProfileString)) {
      final map = jsonDecode(accountProfileString!);
      accountProfile = AccountProfile.fromJson(map);
    }

    final Map<AuthType, Credential> credentials = {};
    for (final authType in AuthCredentialManager.instance.supportedAuthType) {
      final credentialString =
          accountBundle.getString(PropertyKeys.buildAuthCredentialKey(authType));
      if (DartExt.isNotBlank(credentialString)) {
        final credential =
            AuthCredentialManager.instance.deserializeCredential(authType, credentialString!);
        if (credential != null) {
          credentials[authType] = credential;
        }
      }
    }
    final anonymousSecretKey = accountBundle.getString(PropertyKeys.anonymousSecretKey);
    if (DartExt.isNotBlank(anonymousSecretKey)) {
      credentials[AuthType.anonymous] = AnonymousCredential(anonymousSecretKey!);
    }

    return Account.restore(
        guruUser: guruUser,
        device: device,
        accountProfile: accountProfile,
        credentials: credentials);
  }

  Future<int> getLatestReportDeviceTimestamp() async {
    return await getInt(PropertyKeys.latestReportDeviceTimestamp, defValue: 0);
  }

  void setLatestReportDeviceTimestamp(int timestamp) async {
    setInt(PropertyKeys.latestReportDeviceTimestamp, timestamp);
  }

  Future<String> getAnonymousSecretKey() async {
    String? secret = await getString(PropertyKeys.anonymousSecretKey, defValue: "");
    if (secret == '') {
      secret = IdUtils.uuidV4();
      await setString(PropertyKeys.anonymousSecretKey, secret);
    }
    return secret;
  }

  Future clearAnonymousSecretKey() async {
    await remove(PropertyKeys.anonymousSecretKey);
  }

  Future saveCredential(Credential credential) async {
    final data = jsonEncode(credential);
    await setString(PropertyKeys.buildAuthCredentialKey(credential.authType), data);
    final historicalSocialAuths = await getHistoricalSocialAuths();
    final authName = getAuthName(credential.authType);
    if (!historicalSocialAuths.contains(authName)) {
      historicalSocialAuths.add(authName);
      setHistoricalSocialAuths(historicalSocialAuths);
    }
  }

  Future deleteCredential(AuthType authType) async {
    await remove(PropertyKeys.buildAuthCredentialKey(authType));
  }

  Future<Set<String>> getHistoricalSocialAuths() async {
    final data = await getString(PropertyKeys.historicalSocialAuths, defValue: "");
    return data.isNotEmpty ? (data.split("|").toSet()..remove("")) : {};
  }

  Future<bool> setHistoricalSocialAuths(Set<String> historicalSocialAuths) async {
    historicalSocialAuths.remove("");
    await setString(PropertyKeys.historicalSocialAuths, historicalSocialAuths.join("|"));
    return true;
  }
}
