package sh.lajo.buddy import android.content.Context import android.util.Log import kotlinx.serialization.json.Json import okhttp3.Call import okhttp3.Callback import okhttp3.Request import okhttp3.Response import java.io.IOException object ConfigManager { private const val TAG = "ConfigManager" private const val PREFS_KEY_DISABLE_BUDDY = "config_disable_buddy" private const val PREFS_KEY_BLOCK_ADULT_SITES = "config_block_adult_sites" private const val PREFS_KEY_LAST_FETCH = "config_last_fetch" private const val FETCH_INTERVAL_MS = 5 * 60 * 1000L // 5 minutes private val json = Json { ignoreUnknownKeys = true } fun getConfig(context: Context): DeviceConfig { val prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE) return DeviceConfig( disableBuddy = prefs.getBoolean(PREFS_KEY_DISABLE_BUDDY, false), blockAdultSites = prefs.getBoolean(PREFS_KEY_BLOCK_ADULT_SITES, true) ) } fun saveConfig(context: Context, config: DeviceConfig) { val prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE) prefs.edit().apply { putBoolean(PREFS_KEY_DISABLE_BUDDY, config.disableBuddy) putBoolean(PREFS_KEY_BLOCK_ADULT_SITES, config.blockAdultSites) apply() } } fun shouldFetchConfig(context: Context): Boolean { val prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE) val lastFetch = prefs.getLong(PREFS_KEY_LAST_FETCH, 0) return System.currentTimeMillis() - lastFetch > FETCH_INTERVAL_MS } fun fetchConfig(context: Context, onComplete: ((Boolean) -> Unit)? = null) { val prefs = context.getSharedPreferences("app_prefs", Context.MODE_PRIVATE) val token = prefs.getString("auth_token", "") ?: "" if (token.isEmpty()) { Log.w(TAG, "No auth token available, skipping config fetch") onComplete?.invoke(false) return } val request = Request.Builder() .url("${ApiConfig.BASE_URL}/kid/getconfig") .addHeader("Authorization", "Bearer $token") .get() .build() HttpClient.client.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { Log.e(TAG, "Failed to fetch config: ${e.message}") onComplete?.invoke(false) } override fun onResponse(call: Call, response: Response) { try { val body = response.body?.string() if (response.isSuccessful && body != null) { val configResponse = json.decodeFromString(body) if (configResponse.success && configResponse.config != null) { saveConfig(context, configResponse.config) prefs.edit().putLong(PREFS_KEY_LAST_FETCH, System.currentTimeMillis()).apply() Log.i(TAG, "Config fetched successfully: ${configResponse.config}") onComplete?.invoke(true) } else { Log.w(TAG, "Config fetch failed: ${configResponse.reason}") onComplete?.invoke(false) } } else { Log.w(TAG, "Config fetch returned ${response.code}") onComplete?.invoke(false) } } catch (e: Exception) { Log.e(TAG, "Failed to parse config response: ${e.message}") onComplete?.invoke(false) } } }) } }