syntax = "proto3";

option java_package = "com.cashparty.rewards.app.datastore";
option java_multiple_files = true;

message SettingsProto {
  // 6 (isPro) and 7 (isRemoveAdsClicked) belonged to the removed subscription paywall. Reserved
  // rather than reused: installs upgrading from a paywall build still carry those bytes on disk,
  // and a new field on an old number would decode that stale value as its own.
  // 14 (pendingRelinkUserId) held a bare guest user id, which the server could
  // not tell apart from any other id an attacker might send. The merge now
  // proves ownership with the guest's own refresh token (21), so the old bytes
  // must not be decoded into it.
  reserved 6, 7, 14;

  bool isLoggedIn = 1;
  string token = 2;
  string userId = 3;
  string locale = 4;
  int64 last_ad_shown_timestamp = 5;
  string fcmToken = 8;
  bool isNotificationsEnabled = 9;
  bool isDarkModeEnabled = 10;
  bool isSoundEnabled = 11;
  int64 lastUnityAdShownTimestamp = 12;

  // Mobile API session, mirroring the Flutter client's TokenStore.
  // `token` (2) holds the short lived JWT access token; the refresh token is
  // exchanged at /auth/refresh when the access token expires.
  string refreshToken = 13;
  bool isGuest = 15;
  string deviceId = 16;
  string firebaseUid = 17;

  // Onboarding is shown once per install, before the first home screen.
  bool onboardingCompleted = 18;

  // Whether the user has ever chosen a theme in Settings.
  //
  // Without this there is no way to tell "dark, because they picked it" from "dark, because that
  // is the proto3 default for a bool". Following the system needs exactly that distinction: it
  // must keep tracking the OS until the switch is touched, and stop for good afterwards.
  // `isLoggedIn` was standing in for it, which never worked - a guest is signed in, so the
  // follow-system path was live only in the race window before the anonymous session landed.
  bool hasThemePreference = 20;

  // Last successful GET /config response, verbatim.
  //
  // Cached so a cold start with no network still boots into a usable app: without it the ad units,
  // the feature flags and the currency code are all absent, and every screen degrades at once.
  // Stored as raw JSON rather than as parsed fields so an additive server change does not need a
  // proto migration to survive a restart.
  string cachedConfigJson = 19;

  // The abandoned guest's refresh token, held between signing out of the guest
  // session and POST /auth/relink on the account being signed in to.
  //
  // A guest is only abandoned when Firebase refuses to link its anonymous user
  // to the credential, which is the one path where the server-side account
  // changes and the balance would otherwise be stranded. The token rather than
  // the user id: it is proof this install actually held that session, so the
  // merge cannot be pointed at a stranger's account.
  string pendingRelinkGuestToken = 21;
}