package com.bytelyst.platform

import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

/**
 * Biometric authentication wrapper (Face / Fingerprint).
 *
 * Uses AndroidX BiometricPrompt for hardware-backed authentication.
 * Mirrors the Swift BLBiometricAuth API.
 */
object BLBiometricAuth {

    enum class BiometricResult {
        SUCCESS,
        CANCELLED,
        NOT_AVAILABLE,
        ERROR,
    }

    /**
     * Check if biometric authentication is available on this device.
     */
    fun isAvailable(activity: FragmentActivity): Boolean {
        val manager = BiometricManager.from(activity)
        return manager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG) ==
            BiometricManager.BIOMETRIC_SUCCESS
    }

    /**
     * Show a biometric prompt and return the result.
     *
     * Must be called from a FragmentActivity (Compose activities extend this).
     */
    suspend fun authenticate(
        activity: FragmentActivity,
        title: String = "Authenticate",
        subtitle: String? = null,
        negativeButtonText: String = "Cancel",
    ): BiometricResult {
        if (!isAvailable(activity)) return BiometricResult.NOT_AVAILABLE

        return suspendCoroutine { continuation ->
            val executor = ContextCompat.getMainExecutor(activity)

            val callback = object : BiometricPrompt.AuthenticationCallback() {
                override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                    continuation.resume(BiometricResult.SUCCESS)
                }

                override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                    val result = if (
                        errorCode == BiometricPrompt.ERROR_USER_CANCELED ||
                        errorCode == BiometricPrompt.ERROR_NEGATIVE_BUTTON ||
                        errorCode == BiometricPrompt.ERROR_CANCELED
                    ) {
                        BiometricResult.CANCELLED
                    } else {
                        BiometricResult.ERROR
                    }
                    continuation.resume(result)
                }

                override fun onAuthenticationFailed() {
                    // Individual attempt failed, prompt stays open — don't resume yet
                }
            }

            val prompt = BiometricPrompt(activity, executor, callback)
            val info = BiometricPrompt.PromptInfo.Builder()
                .setTitle(title)
                .apply { subtitle?.let { setSubtitle(it) } }
                .setNegativeButtonText(negativeButtonText)
                .build()

            prompt.authenticate(info)
        }
    }
}
