package com.jttools.datacontrol.data import com.jttools.datacontrol.remote.FamilyLink import java.time.LocalDate /** * Réglages persistés de l'application, avec leurs valeurs par défaut. */ data class AppSettings( /** Tunnel WireGuard vers le serveur familyd monté en permanence (désactivation protégée par mot de passe). */ val controlEnabled: Boolean = false, val planLimitMo: Long = 1000L, val planPriceEuro: Double = 19.99, val overagePricePerMoEuro: Double = 0.01, val planStartDateEpochDay: Long = LocalDate.now().toEpochDay(), val autoResetEnabled: Boolean = true, val baselineMobileBytesAtReset: Long = 0L, val passwordHash: String? = null, val passwordSalt: String? = null, /** Règles d'usage des applications (plages horaires, limites, interdites), envoyées par le serveur. */ val rulesJson: String? = null, /** Liaison avec le serveur familyd (null tant que l'appareil n'est pas associé). */ val link: FamilyLink? = null, /** Mode réseau appliqué par le serveur : open, allowlist ou cut. */ val serverMode: String = "open", val serverModeReason: String = "", val policyVersion: Long = 0L, /** Bloque l'installation d'applications (Play Store compris) — appliqué en mode propriétaire. */ val blockInstalls: Boolean = false, /** Téléphone verrouillé à distance par le parent : un code du serveur est exigé pour le déverrouiller. */ val parentalLocked: Boolean = false ) { val isPaired: Boolean get() = link != null val planStartDate: LocalDate get() = LocalDate.ofEpochDay(planStartDateEpochDay) /** Un mot de passe de verrouillage protège la désactivation du contrôle et l'accès aux réglages. */ val hasPassword: Boolean get() = !passwordHash.isNullOrEmpty() /** Prochaine date de réinitialisation automatique (anniversaire mensuel du début de forfait). */ fun nextAutoResetDate(): LocalDate { var next = planStartDate.plusMonths(1) val today = LocalDate.now() while (!next.isAfter(today)) { next = next.plusMonths(1) } return next } } /** État calculé de la consommation, dérivé des réglages + de la mesure de données réelle. */ data class UsageState( val consumedMo: Long, val planLimitMo: Long, val overageMo: Long, val isOverPlan: Boolean, val estimatedTotalPriceEuro: Double ) { val percentOfPlan: Float get() = if (planLimitMo <= 0) 0f else (consumedMo.toFloat() / planLimitMo.toFloat()).coerceAtLeast(0f) } enum class DataState { OK, // sous le seuil d'alerte WARNING, // proche ou au-delà du forfait (>= 80 %) CUT, // le serveur coupe l'accès (mode « coupé » ou « liste blanche ») WIFI // Wi-Fi actif }