package com.recordatorios.app

import android.content.Context
import android.content.SharedPreferences
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import java.security.KeyStore
import javax.crypto.Cipher

class SecurityManager private constructor(private val context: Context) {

    private val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
    
    private var encryptedPrefs: SharedPreferences? = null
    private var isUnlocked = false
    private var authCallback: ((Boolean) -> Unit)? = null

    init {
        initializeKeystoreKey()
    }

    private fun initializeKeystoreKey() {
        try {
            val masterKey = MasterKey.Builder(context)
                .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
                .setUserAuthenticationRequired(true)
                .build()

            encryptedPrefs = EncryptedSharedPreferences.create(
                context,
                PREFS_NAME,
                masterKey,
                EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
            )
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun isBiometricAvailable(): Boolean {
        val biometricManager = BiometricManager.from(context)
        return when (biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)) {
            BiometricManager.BIOMETRIC_SUCCESS -> true
            else -> false
        }
    }

    fun authenticateBiometric(activity: androidx.appcompat.app.AppCompatActivity, onResult: (Boolean) -> Unit) {
        if (isUnlocked) {
            onResult(true)
            return
        }

        authCallback = onResult

        val promptInfo = BiometricPrompt.PromptInfo.Builder()
            .setTitle("Desbloquear Recordatorios")
            .setSubtitle("Confirma tu huella o rostro para acceder a tus datos")
            .setNegativeButtonText("Cancelar")
            .build()

        val executor = ContextCompat.getMainExecutor(context)
        
        val prompt = BiometricPrompt(
            activity,
            executor,
            object : BiometricPrompt.AuthenticationCallback() {
                override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                    isUnlocked = true
                    authCallback?.invoke(true)
                    authCallback = null
                }

                override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                    if (errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON ||
                        errorCode == BiometricPrompt.ERROR_USER_CANCELED) {
                        authCallback?.invoke(false)
                    } else {
                        authCallback?.invoke(false)
                    }
                    authCallback = null
                }

                override fun onAuthenticationFailed() {
                    // Reintentar automáticamente
                }
            }
        )

        prompt.authenticate(promptInfo)
    }

    fun getEncryptedPrefs(): SharedPreferences? {
        return encryptedPrefs
    }

    fun isUnlocked(): Boolean {
        return isUnlocked
    }

    fun lock() {
        isUnlocked = false
    }

    fun migrateData() {
        val oldNotesPrefs = context.getSharedPreferences("recordatorios_prefs", Context.MODE_PRIVATE)
        val oldCategoriesPrefs = context.getSharedPreferences("categories_prefs", Context.MODE_PRIVATE)
        
        val encrypted = encryptedPrefs ?: return
        
        val notesData = oldNotesPrefs.getString("notes", null)
        if (notesData != null && !encrypted.contains("notes")) {
            encrypted.edit().putString("notes", notesData).apply()
        }
        
        val categoriesData = oldCategoriesPrefs.getString("categories", null)
        if (categoriesData != null && !encrypted.contains("categories")) {
            encrypted.edit().putString("categories", categoriesData).apply()
        }
    }

    companion object {
        private const val PREFS_NAME = "encrypted_recordatorios_prefs"

        @Volatile
        private var INSTANCE: SecurityManager? = null

        fun getInstance(context: Context): SecurityManager {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: SecurityManager(context.applicationContext).also { INSTANCE = it }
            }
        }
    }
}
