package com.adealink.weparty.call.util

import android.Manifest
import android.app.AppOpsManager
import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.fragment.app.FragmentActivity
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.base.IError
import com.adealink.frame.base.Rlt
import com.adealink.frame.coroutine.dispatcher.Dispatcher
import com.adealink.frame.log.Log
import com.adealink.frame.util.AppUtil
import com.adealink.weparty.call.R
import com.adealink.weparty.call.constant.TAG_CALL
import com.adealink.weparty.commonui.ext.getActivity
import com.adealink.weparty.permission.PermissionUtils
import com.tencent.qcloud.tuicore.TUIConfig
import com.tencent.qcloud.tuicore.permission.PermissionCallback
import com.tencent.qcloud.tuicore.permission.PermissionRequester
import io.trtc.tuikit.atomicxcore.api.call.CallMediaType
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext

object PermissionRequest {

    suspend fun requestPermission(
        mediaType: CallMediaType
    ): Rlt<Any> {
        return withContext(Dispatcher.UI) {
            suspendCancellableCoroutine { continuation ->
                requestPermissions(
                    AppUtil.appContext,
                    mediaType,
                    object : PermissionCallback() {
                        override fun onGranted() {
                            //主叫直接返回结果
                            if (continuation.isActive) {
                                continuation.resume(Rlt.Success(Any()), null)
                            }
                        }

                        override fun onDenied() {
                            if (continuation.isActive) {
                                continuation.resume(Rlt.Failed(IError()), null)
                            }
                        }
                    })
            }
        }
    }

    fun requestPermissions(
        context: Context,
        type: CallMediaType,
        callback: PermissionCallback?
    ) {
        val permissions = arrayListOf<String>()
        var tips = ""
        when (type) {
            CallMediaType.Audio -> {
                permissions.add(Manifest.permission.RECORD_AUDIO)
                tips = getCompatString(R.string.call_permission_audio_tips)
            }

            CallMediaType.Video -> {
                callback?.onDenied()
                return
            }
        }

        if (PermissionRequester.newInstance(*permissions.toTypedArray()).has()) {
            callback?.onGranted()
            return
        }

        val activity = context.getActivity() ?: AppUtil.currentActivity as? FragmentActivity
        if (activity == null || activity.isFinishing || activity.isDestroyed) {
            callback?.onDenied()
            return
        }
        PermissionUtils.requestPermissions(
            activity,
            permissions,
            tips,
            onGranted = {
                requestBluetoothPermission(context, object : PermissionCallback() {
                    override fun onGranted() {
                        callback?.onGranted()
                    }
                })
            },
            onDenied = {
                callback?.onDenied()
            }
        )
    }

    /**
     * Android S(31) need apply for Nearby devices(Bluetooth) permission to support bluetooth headsets.
     * Please refer to: https://developer.android.com/guide/topics/connectivity/bluetooth/permissions
     */
    private fun requestBluetoothPermission(context: Context, callback: PermissionCallback) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
            callback.onGranted()
            return
        }
        if (PermissionRequester.newInstance(Manifest.permission.BLUETOOTH_CONNECT).has()) {
            callback.onGranted()
            return
        }

        val activity = context.getActivity() ?: AppUtil.currentActivity as? FragmentActivity
        if (activity == null || activity.isFinishing || activity.isDestroyed) {
            callback.onDenied()
            return
        }
        PermissionUtils.requestPermissions(
            activity,
            listOf(Manifest.permission.BLUETOOTH_CONNECT),
            getCompatString(R.string.call_permission_bluetooth_reason),
            onGranted = {
                callback.onGranted()
            },
            onDenied = {
                //bluetooth is unnecessary permission, return permission granted
                callback.onGranted()
            }
        )
    }

    fun requestFloatPermission(context: Context?, callback: PermissionCallback) {
        if (PermissionRequester.newInstance(
                PermissionRequester.FLOAT_PERMISSION,
                PermissionRequester.BG_START_PERMISSION
            ).has()
        ) {
            callback.onGranted()
            return
        }

        val activity = context?.getActivity() ?: AppUtil.currentActivity as? FragmentActivity
        if (activity == null || activity.isFinishing || activity.isDestroyed) {
            callback.onDenied()
            return
        }

        PermissionUtils.showRequestPermissionDialog(
            activity,
            getCompatString(R.string.call_permission_float_window),
            onConfirm = {
                //Please open both OverlayWindows and Background pop-ups permission.
                PermissionRequester.newInstance(
                    PermissionRequester.FLOAT_PERMISSION,
                    PermissionRequester.BG_START_PERMISSION
                )
                    .request()
            },
            onCancel = {
                callback.onDenied()
            }
        )
    }

    fun isNotificationEnabled(): Boolean {
        val context = TUIConfig.getAppContext()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // For Android Oreo and above
            val manager =
                context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            return manager.areNotificationsEnabled()
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // For versions prior to Android Oreo
            var appOps: AppOpsManager? = null
            appOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
            val appInfo = context.applicationInfo
            val packageName = context.applicationContext.packageName
            val uid = appInfo.uid
            try {
                var appOpsClass: Class<*>? = null
                appOpsClass = Class.forName(AppOpsManager::class.java.name)
                val checkOpNoThrowMethod = appOpsClass.getMethod(
                    "checkOpNoThrow", Integer.TYPE, Integer.TYPE, String::class.java
                )
                val opPostNotificationValue = appOpsClass.getDeclaredField("OP_POST_NOTIFICATION")
                val value = opPostNotificationValue[Int::class.java] as Int
                return checkOpNoThrowMethod.invoke(
                    appOps,
                    value,
                    uid,
                    packageName
                ) as Int == AppOpsManager.MODE_ALLOWED
            } catch (e: Exception) {
                Log.e(TAG_CALL, "isNotificationEnabled exception, ${e.message}", e)
            }
        }
        return false
    }
}