package ru.forbion.f7cloud.core.auth

import android.content.Context
import java.security.MessageDigest

class AppLockStore(context: Context) {
    private val prefs = context.applicationContext.getSharedPreferences(PREFS, Context.MODE_PRIVATE)

    fun isEnabled(): Boolean = prefs.getBoolean(KEY_ENABLED, false)

    fun useBiometric(): Boolean = prefs.getBoolean(KEY_BIOMETRIC, false)

    fun shouldOfferSetup(): Boolean =
        !prefs.getBoolean(KEY_SETUP_OFFERED, false) && !isEnabled()

    fun markSetupOffered() {
        prefs.edit().putBoolean(KEY_SETUP_OFFERED, true).apply()
    }

    fun markBackgrounded(at: Long = System.currentTimeMillis()) {
        prefs.edit().putLong(KEY_BACKGROUND_AT, at).apply()
    }

    fun clearBackgroundMarker() {
        prefs.edit().remove(KEY_BACKGROUND_AT).apply()
    }

    /** Lock after the app stayed in background (process still alive) for at least [lockDelayMs]. */
    fun shouldRequireUnlock(
        now: Long = System.currentTimeMillis(),
        lockDelayMs: Long = DEFAULT_LOCK_DELAY_MS,
    ): Boolean {
        if (!isEnabled()) return false
        val backgroundAt = prefs.getLong(KEY_BACKGROUND_AT, 0L)
        if (backgroundAt <= 0L) return false
        return now - backgroundAt >= lockDelayMs
    }

    /**
     * True once per process start (app was killed / fully closed and opened again).
     * Always requires lock even if background timeout has not elapsed.
     */
    fun consumeColdStart(): Boolean {
        if (!coldStartPending) return false
        coldStartPending = false
        return isEnabled()
    }

    fun enable(pin: String, biometric: Boolean) {
        prefs.edit()
            .putBoolean(KEY_ENABLED, true)
            .putString(KEY_PIN_HASH, hashPin(pin))
            .putBoolean(KEY_BIOMETRIC, biometric)
            .putBoolean(KEY_BIOMETRIC_ONLY, false)
            .apply()
    }

    fun enableBiometricOnly() {
        prefs.edit()
            .putBoolean(KEY_ENABLED, true)
            .putBoolean(KEY_BIOMETRIC, true)
            .putBoolean(KEY_BIOMETRIC_ONLY, true)
            .remove(KEY_PIN_HASH)
            .apply()
    }

    fun isBiometricOnly(): Boolean = prefs.getBoolean(KEY_BIOMETRIC_ONLY, false)

    fun disable() {
        prefs.edit()
            .putBoolean(KEY_ENABLED, false)
            .remove(KEY_PIN_HASH)
            .putBoolean(KEY_BIOMETRIC, false)
            .putBoolean(KEY_BIOMETRIC_ONLY, false)
            .apply()
    }

    fun verifyPin(pin: String): Boolean {
        val stored = prefs.getString(KEY_PIN_HASH, null) ?: return false
        return stored == hashPin(pin)
    }

    private fun hashPin(pin: String): String {
        val digest = MessageDigest.getInstance("SHA-256")
        val bytes = digest.digest(pin.toByteArray(Charsets.UTF_8))
        return bytes.joinToString("") { "%02x".format(it) }
    }

    companion object {
        private const val PREFS = "f7_app_lock"
        const val DEFAULT_LOCK_DELAY_MS = 60_000L
        private const val KEY_ENABLED = "enabled"
        private const val KEY_BACKGROUND_AT = "background_at"
        private const val KEY_BIOMETRIC = "biometric"
        private const val KEY_BIOMETRIC_ONLY = "biometric_only"
        private const val KEY_PIN_HASH = "pin_hash"
        private const val KEY_SETUP_OFFERED = "setup_offered"

        @Volatile
        private var coldStartPending = true
    }
}
