package com.servicebook.data.preferences import android.content.Context import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import com.servicebook.data.model.OdometerUnit import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map internal val Context.dataStore: DataStore by preferencesDataStore(name = "app_preferences") class AppPreferencesImpl( private val context: Context, private val store: DataStore, ) : AppPreferencesStore { private object Keys { val VAULT_URI = stringPreferencesKey("vault_uri") val ODOMETER_UNIT = stringPreferencesKey("odometer_unit") val CURRENCY = stringPreferencesKey("currency") val IS_PREMIUM_CACHED = booleanPreferencesKey("is_premium_cached") val DEBUG_BILLING_OVERRIDE_MODE = stringPreferencesKey("debug_billing_override_mode") val CRASH_REPORTING_ENABLED = booleanPreferencesKey("crash_reporting_enabled") val CRASH_REPORTING_CONSENT_PROMPT_SHOWN_VERSION = intPreferencesKey("crash_reporting_consent_prompt_shown_version") } private val sharedPrefs = context.getSharedPreferences("app_preferences_sync", Context.MODE_PRIVATE) override val preferences: Flow = store.data.map { prefs -> AppPreferences( vaultUriString = prefs[Keys.VAULT_URI], defaultOdometerUnit = prefs[Keys.ODOMETER_UNIT] ?.let { runCatching { OdometerUnit.valueOf(it) }.getOrNull() } ?: OdometerUnit.KM, defaultCurrency = prefs[Keys.CURRENCY] ?: "USD", isPremiumCached = prefs[Keys.IS_PREMIUM_CACHED] ?: false, debugBillingOverrideMode = prefs[Keys.DEBUG_BILLING_OVERRIDE_MODE] ?.let { runCatching { DebugBillingOverrideMode.valueOf(it) }.getOrNull() } ?: DebugBillingOverrideMode.NONE, crashReportingEnabled = prefs[Keys.CRASH_REPORTING_ENABLED] ?: false, crashReportingConsentPromptShownVersion = prefs[Keys.CRASH_REPORTING_CONSENT_PROMPT_SHOWN_VERSION] ?: 0, ) } override suspend fun setVaultUri(uri: String?) { store.edit { prefs -> if (uri != null) { prefs[Keys.VAULT_URI] = uri } else { prefs.remove(Keys.VAULT_URI) } } } override suspend fun setDefaultOdometerUnit(unit: OdometerUnit) { store.edit { it[Keys.ODOMETER_UNIT] = unit.name } } override suspend fun setDefaultCurrency(currency: String) { store.edit { it[Keys.CURRENCY] = currency } } override suspend fun setIsPremiumCached(value: Boolean) { store.edit { it[Keys.IS_PREMIUM_CACHED] = value } } override suspend fun setDebugBillingOverrideMode(mode: DebugBillingOverrideMode) { store.edit { it[Keys.DEBUG_BILLING_OVERRIDE_MODE] = mode.name } } override suspend fun setCrashReportingEnabled(enabled: Boolean) { // SharedPrefs is written first: it is the sync gate for isCrashReportingEnabledSync() // used in initSentry/beforeSend. DataStore (reactive UI source) can self-correct on next launch. sharedPrefs.edit().putBoolean(KEY_CRASH_REPORTING_ENABLED, enabled).apply() store.edit { it[Keys.CRASH_REPORTING_ENABLED] = enabled } } override suspend fun setCrashReportingConsentPromptShownVersion(version: Int) { store.edit { it[Keys.CRASH_REPORTING_CONSENT_PROMPT_SHOWN_VERSION] = version } } override suspend fun recordConsentDecision(enabled: Boolean) { // SharedPrefs first — see setCrashReportingEnabled for ordering rationale. sharedPrefs.edit().putBoolean(KEY_CRASH_REPORTING_ENABLED, enabled).apply() store.edit { it[Keys.CRASH_REPORTING_ENABLED] = enabled it[Keys.CRASH_REPORTING_CONSENT_PROMPT_SHOWN_VERSION] = CURRENT_CONSENT_VERSION } } override fun isCrashReportingEnabledSync(): Boolean = sharedPrefs.getBoolean(KEY_CRASH_REPORTING_ENABLED, false) private companion object { const val KEY_CRASH_REPORTING_ENABLED = "crash_reporting_enabled" } }