package com.rosetta.messenger.biometric

import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.withContext

/**
 * Безопасное хранилище настроек биометрической аутентификации
 * Использует EncryptedSharedPreferences с MasterKey из Android Keystore
 *
 * Биометрия привязана к конкретному аккаунту (per-account), не глобальная.
 */
class BiometricPreferences(private val context: Context) {

    companion object {
        private const val TAG = "BiometricPreferences"
        private const val PREFS_FILE_NAME = "rosetta_secure_biometric_prefs"
        private const val KEY_BIOMETRIC_ENABLED_PREFIX = "biometric_enabled_"
        private const val ENCRYPTED_PASSWORD_PREFIX = "encrypted_password_"
        // Legacy key (global) — for migration
        private const val KEY_BIOMETRIC_ENABLED_LEGACY = "biometric_enabled"
        // Shared state for reactive UI updates
        private val biometricEnabledState = MutableStateFlow(false)
    }

    private val appContext = context.applicationContext
    private val _isBiometricEnabled = biometricEnabledState

    private val encryptedPrefs: SharedPreferences by lazy {
        createEncryptedPreferences()
    }

    private fun createEncryptedPreferences(): SharedPreferences {
        try {
            val masterKey = MasterKey.Builder(appContext)
                .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
                .setUserAuthenticationRequired(false)
                .build()

            return EncryptedSharedPreferences.create(
                appContext,
                PREFS_FILE_NAME,
                masterKey,
                EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
            )
        } catch (e: Exception) {
            return appContext.getSharedPreferences(PREFS_FILE_NAME + "_fallback", Context.MODE_PRIVATE)
        }
    }

    val isBiometricEnabled: Flow<Boolean> = _isBiometricEnabled.asStateFlow()

    /**
     * Загрузить состояние биометрии для конкретного аккаунта
     */
    fun loadForAccount(publicKey: String) {
        try {
            val key = "$KEY_BIOMETRIC_ENABLED_PREFIX$publicKey"
            val perAccount = encryptedPrefs.getBoolean(key, false)
            // Migration: если per-account нет, проверяем legacy глобальный ключ
            if (!perAccount && encryptedPrefs.getBoolean(KEY_BIOMETRIC_ENABLED_LEGACY, false)) {
                // Мигрируем: копируем глобальное значение в per-account
                encryptedPrefs.edit().putBoolean(key, true).apply()
                _isBiometricEnabled.value = true
            } else {
                _isBiometricEnabled.value = perAccount
            }
        } catch (e: Exception) {
            _isBiometricEnabled.value = false
        }
    }

    /**
     * Включить биометрическую аутентификацию для аккаунта
     */
    suspend fun enableBiometric(publicKey: String) = withContext(Dispatchers.IO) {
        val key = "$KEY_BIOMETRIC_ENABLED_PREFIX$publicKey"
        encryptedPrefs.edit().putBoolean(key, true).commit()
        _isBiometricEnabled.value = true
    }

    /**
     * Отключить биометрическую аутентификацию для аккаунта
     */
    suspend fun disableBiometric(publicKey: String) = withContext(Dispatchers.IO) {
        val key = "$KEY_BIOMETRIC_ENABLED_PREFIX$publicKey"
        encryptedPrefs.edit().putBoolean(key, false).commit()
        _isBiometricEnabled.value = false
    }

    /**
     * Проверить включена ли биометрия для аккаунта (синхронно)
     */
    fun isBiometricEnabledForAccount(publicKey: String): Boolean {
        return try {
            encryptedPrefs.getBoolean("$KEY_BIOMETRIC_ENABLED_PREFIX$publicKey", false)
        } catch (_: Exception) { false }
    }

    // --- Legacy compat: old callers without publicKey ---

    @Deprecated("Use enableBiometric(publicKey) instead")
    suspend fun enableBiometric() = withContext(Dispatchers.IO) {
        encryptedPrefs.edit().putBoolean(KEY_BIOMETRIC_ENABLED_LEGACY, true).commit()
        _isBiometricEnabled.value = true
    }

    @Deprecated("Use disableBiometric(publicKey) instead")
    suspend fun disableBiometric() = withContext(Dispatchers.IO) {
        encryptedPrefs.edit().putBoolean(KEY_BIOMETRIC_ENABLED_LEGACY, false).commit()
        _isBiometricEnabled.value = false
    }

    suspend fun saveEncryptedPassword(publicKey: String, encryptedPassword: String) = withContext(Dispatchers.IO) {
        val key = "$ENCRYPTED_PASSWORD_PREFIX$publicKey"
        encryptedPrefs.edit().putString(key, encryptedPassword).apply()
    }

    suspend fun getEncryptedPassword(publicKey: String): String? = withContext(Dispatchers.IO) {
        val key = "$ENCRYPTED_PASSWORD_PREFIX$publicKey"
        encryptedPrefs.getString(key, null)
    }

    suspend fun removeEncryptedPassword(publicKey: String) = withContext(Dispatchers.IO) {
        val key = "$ENCRYPTED_PASSWORD_PREFIX$publicKey"
        encryptedPrefs.edit().remove(key).apply()
    }

    suspend fun clearAll() = withContext(Dispatchers.IO) {
        encryptedPrefs.edit().clear().commit()
        _isBiometricEnabled.value = false
    }

    suspend fun hasEncryptedPassword(publicKey: String): Boolean {
        return getEncryptedPassword(publicKey) != null
    }
}
