package com.iscs.bozzys.utils

import android.app.Activity
import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.os.Build
import android.os.CancellationSignal
import android.provider.OpenableColumns
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.fragment.app.FragmentActivity
import com.iscs.bozzys.R
import java.io.File
import java.security.KeyStore
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKey
import javax.crypto.spec.IvParameterSpec

/**
 * 用于系统相关操作的功能
 */
object SystemUtil {

    /**
     * 获取App版本信息
     */
    fun Context.getAppVersionInfo(): Pair<Long, String> {
        val pm = this.packageManager
        val pi = pm.getPackageInfo(this.packageName, 0)
        val code = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            pi.longVersionCode
        } else {
            @Suppress("DEPRECATION")
            pi.versionCode.toLong()
        }
        val name = pi.versionName ?: ""
        return code to name
    }

    /**
     * 指纹组件是否可用
     */
    fun Context.isBiometricCanUse(): Boolean {
        val bm = BiometricManager.from(this)
        val canAuth = bm.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)
        return when (canAuth) {
            // 可以使用指纹
            BiometricManager.BIOMETRIC_SUCCESS -> true
            // 设备不支持
            BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE -> false
            // 硬件不可用
            BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE -> false
            // 用户未录入
            BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED -> false
            // 其他认为不可用
            else -> false
        }
    }

    /**
     * 显示指纹验证
     *
     * @param act
     */
    @OptIn(ExperimentalStdlibApi::class)
    fun showFingerAuth(act: Activity, cipher: Cipher, value: ByteArray, done: (doFinalValue: ByteArray) -> Unit) {
        if (act is FragmentActivity) {
            val bp = BiometricPrompt(act, act.mainExecutor, object : BiometricPrompt.AuthenticationCallback() {

            })
        } else {
            val bp = android.hardware.biometrics.BiometricPrompt.Builder(act)
                .setTitle("请验证")
                .setNegativeButton("取消", act.mainExecutor) { _, _ ->
                    // onError("用户取消")
                }
                .build()
            bp.authenticate(
                android.hardware.biometrics.BiometricPrompt.CryptoObject(cipher),
                CancellationSignal(),
                act.mainExecutor,
                object : android.hardware.biometrics.BiometricPrompt.AuthenticationCallback() {

                    override fun onAuthenticationSucceeded(result: android.hardware.biometrics.BiometricPrompt.AuthenticationResult) {
                        LogUtil.i("SystemUtil -> showFingerAuth", "Auth succeeded")
                        val cipher = result.cryptoObject?.cipher
                        cipher?.doFinal(value)?.let { done(it) }
                    }

                    override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                        LogUtil.i("SystemUtil -> showFingerAuth", "Auth error code : $errorCode msg : $errString")
                    }
                }
            )
        }
    }

    /**
     * 获取Uri文件的原始名称
     */
    fun Context.getUriFileName(uri: Uri): String? {
        if (uri.scheme != ContentResolver.SCHEME_CONTENT) return null
        contentResolver.query(
            uri,
            arrayOf(OpenableColumns.DISPLAY_NAME),
            null,
            null,
            null
        )?.use { cursor ->
            if (cursor.moveToFirst()) {
                val index = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
                if (index != -1) {
                    return cursor.getString(index)
                }
            }
        }
        return null
    }


    /**
     * Uri转文件
     */
    fun Context.uriToFile(uri: Uri?): File? {
        if (uri == null) return null
        val input = contentResolver.openInputStream(uri)!!
        val suffix = ".${contentResolver.getType(uri)!!.split("/")[1]}"
        val fileName = getUriFileName(uri) ?: suffix
        LogUtil.i("SystemUtil", "uriToFile -> 文件：$fileName")
        val file = File(cacheDir, "${System.currentTimeMillis()}_$fileName")
        file.outputStream().use { output ->
            input.copyTo(output)
        }
        return file
    }

    /**
     * 通过文件后缀名获取指定图片资源
     *
     * @param url 文件地址
     */
    fun getFileTypeIconBySuffix(url: String): Pair<Int, String> {
        val spl = url.split("/")
        val splPoint = spl[spl.size - 1].split(".")
        val type = splPoint[splPoint.size - 1].lowercase()
        LogUtil.i("SystemUtil", "解析的文件格式：${type}")
        return when (type) {
            "png" -> R.drawable.file_png to type
            "jpeg",
            "jpg" -> R.drawable.file_jpg to type

            "pdf" -> R.drawable.file_pdf to type
            "xls",
            "xlsx" -> R.drawable.file_xls to type
            // 其余识别为未知文件
            else -> R.drawable.file_unknown to type
        }
    }

    /**
     * 通过Url地址获取文件名
     */
    fun getUrlFileName(url: String): String {
        val spl = url.split("/")
        return spl[spl.size - 1]
    }

}

/**
 * 指纹签名校验操作
 */
object BiometricKeyStore {

    private const val KEY_ALIAS = "biometric_key"
    private const val ANDROID_KEYSTORE = "AndroidKeyStore"

    fun createKeyIfNeeded() {
        val ks = KeyStore.getInstance(ANDROID_KEYSTORE).apply { load(null) }
        if (ks.containsAlias(KEY_ALIAS)) return

        val generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYSTORE)

        val spec = KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
            .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
            .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
            .setUserAuthenticationRequired(true)
            .apply {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                    setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG)
                } else {
                    setUserAuthenticationValidityDurationSeconds(-1)
                }
            }
            .build()

        generator.init(spec)
        generator.generateKey()
    }

    private fun getKey(): SecretKey {
        val ks = KeyStore.getInstance(ANDROID_KEYSTORE).apply { load(null) }
        return ks.getKey(KEY_ALIAS, null) as SecretKey
    }

    fun encryptCipher(): Cipher =
        Cipher.getInstance("AES/CBC/PKCS7Padding").apply {
            init(Cipher.ENCRYPT_MODE, getKey())
        }

    fun decryptCipher(iv: ByteArray): Cipher =
        Cipher.getInstance("AES/CBC/PKCS7Padding").apply {
            init(Cipher.DECRYPT_MODE, getKey(), IvParameterSpec(iv))
        }
}
