package com.tomhempel.rbarometer.session

import android.content.Context
import com.google.gson.Gson
import com.google.gson.annotations.SerializedName
import com.tomhempel.rbarometer.security.SensitiveDataCrypto
import java.io.File

/** Encrypted on-device session pause state so coaches can resume a program session. */
object SessionPauseStore {
    private const val FILE_NAME = "session_pause_states.json"
    private val gson = Gson()

    data class PauseState(
        @SerializedName("clientCode") val clientCode: String,
        @SerializedName("sessionId") val sessionId: String,
        @SerializedName("cycleNumber") val cycleNumber: Int,
        @SerializedName("cycleStartedAt") val cycleStartedAt: Long,
        @SerializedName("measureIndex") val measureIndex: Int,
        @SerializedName("updatedAt") val updatedAt: Long = System.currentTimeMillis(),
    )

    private data class Store(
        @SerializedName("byClient") val byClient: Map<String, PauseState> = emptyMap(),
    )

    fun save(context: Context, state: PauseState) {
        val current = loadStore(context)
        writeStore(context, current.copy(byClient = current.byClient + (state.clientCode.lowercase() to state)))
    }

    fun load(context: Context, clientCode: String): PauseState? =
        loadStore(context).byClient[clientCode.lowercase()]

    fun matchesCurrentProgram(
        context: Context,
        clientCode: String,
        sessionId: String?,
        cycleNumber: Int,
        cycleStartedAt: Long,
    ): Boolean {
        val paused = load(context, clientCode) ?: return false
        if (sessionId.isNullOrBlank()) return false
        return paused.sessionId == sessionId &&
            paused.cycleNumber == cycleNumber &&
            paused.cycleStartedAt == cycleStartedAt
    }

    fun clear(context: Context, clientCode: String) {
        val key = clientCode.lowercase()
        val current = loadStore(context).byClient
        if (!current.containsKey(key)) return
        writeStore(context, Store(byClient = current - key))
    }

    private fun storeFile(context: Context): File = File(context.filesDir, FILE_NAME)

    private fun loadStore(context: Context): Store {
        val file = storeFile(context)
        if (!file.exists()) return Store()
        val raw = file.readText()
        val plain = if (raw.startsWith("v1:")) SensitiveDataCrypto.decrypt(raw) else raw
        return runCatching { gson.fromJson(plain, Store::class.java) }.getOrDefault(Store())
    }

    private fun writeStore(context: Context, store: Store) {
        storeFile(context).writeText(SensitiveDataCrypto.encrypt(gson.toJson(store)))
    }
}
