package no.naiv.meddetsamme.data import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Index import androidx.room.PrimaryKey enum class DoseStatus { PENDING, TAKEN, SKIPPED, SNOOZED } /** * One scheduled occurrence of a dose and what happened to it. Created PENDING * when the reminder fires (the escalation anchor), resolved by user action. * * SNOOZED is a *resting* state between nags — the alarm layer treats it like * PENDING (keeps nagging after the snooze interval) but the UI can distinguish * "I saw it and deferred" from "never reacted". * * [doseTimeId] is nullable and SET_NULL on delete: editing a schedule away must * not erase adherence history. [medId] CASCADE instead — deleting a med (vs. * deactivating) is an explicit "forget everything" action. */ @Entity( tableName = "dose_log", foreignKeys = [ ForeignKey( entity = Medication::class, parentColumns = ["id"], childColumns = ["medId"], onDelete = ForeignKey.CASCADE, ), ForeignKey( entity = DoseTime::class, parentColumns = ["id"], childColumns = ["doseTimeId"], onDelete = ForeignKey.SET_NULL, ), ], indices = [ Index("medId"), Index("doseTimeId"), // The reminder layer's hot path: "is there already a log for this occurrence?" Index(value = ["doseTimeId", "scheduledAtMillis"]), Index("status"), ], ) data class DoseLog( @PrimaryKey(autoGenerate = true) val id: Long = 0, val medId: Long, val doseTimeId: Long?, /** The occurrence this log is for (epoch millis of the scheduled local time). */ val scheduledAtMillis: Long, /** Dose size at the time of logging — schedule edits must not rewrite history. */ val amount: Double, val status: DoseStatus = DoseStatus.PENDING, /** When the user last acted on it (Taken/Skipped/Snoozed), null while untouched. */ val actionedAtMillis: Long? = null, /** * Escalation nags already sent for this occurrence. Lives in the DB, not in * alarm extras, so the ~6-nag cap survives a reboot mid-escalation. */ val nagCount: Int = 0, )