package com.adealink.weparty.push

import android.Manifest
import android.annotation.SuppressLint
import android.app.ActivityOptions
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.fragment.app.FragmentActivity
import com.adealink.frame.aab.util.getCompatColor
import com.adealink.frame.aab.util.getCompatDrawable
import com.adealink.frame.aab.util.getCompatString
import com.adealink.frame.coroutine.dispatcher.Dispatcher
import com.adealink.frame.image.imageService
import com.adealink.frame.image.listener.IImageLoadResultListener
import com.adealink.frame.push.data.KEY_PUSH_DEEPLINK
import com.adealink.frame.push.data.KEY_PUSH_ID
import com.adealink.frame.push.data.KEY_PUSH_MESSAGE_TYPE
import com.adealink.frame.router.Router
import com.adealink.frame.router.RouterDeepLinkActivity
import com.adealink.frame.util.AppUtil
import com.adealink.frame.util.DisplayUtil
import com.adealink.frame.util.ImageUtil
import com.adealink.frame.util.PackageUtil
import com.adealink.weparty.AppModule
import com.adealink.weparty.R
import com.adealink.weparty.commonui.imageview.CircleDrawable
import com.adealink.weparty.commonui.widget.CommonDialog
import com.adealink.weparty.permission.PermissionUtils
import com.adealink.weparty.push.data.JiehePushMessage
import com.adealink.weparty.push.data.PushMessageType
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.adealink.weparty.R as APP_R

object NotificationUtil {
    private fun forwardIntent(pushMessage: JiehePushMessage): Intent {
        var deeplink = pushMessage.deeplink
        if (deeplink.isNullOrEmpty()) {
            deeplink = Router.getDeepLink(AppModule.Main.PATH)
        }
        return Intent().apply {
            addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            setPackage(PackageUtil.getPackageName())
            setClass(AppUtil.appContext, RouterDeepLinkActivity::class.java)
            putExtra(KEY_PUSH_ID, pushMessage.pushId)
            putExtra(KEY_PUSH_MESSAGE_TYPE, pushMessage.messageType)
            putExtra(KEY_PUSH_DEEPLINK, pushMessage.deeplink)
            action = Intent.ACTION_VIEW
            data = Uri.parse(deeplink)
        }
    }

    fun createNotificationChannel(channelId: String) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(channelId,
                channelId,
                NotificationManager.IMPORTANCE_HIGH).apply {
                description = channelId
            }
            channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
            val notificationManager: NotificationManager? =
                AppUtil.getSystemService<NotificationManager>(Context.NOTIFICATION_SERVICE)
            notificationManager?.createNotificationChannel(channel)
        }
    }

    fun showNotification(pushMessage: JiehePushMessage, completeCallback: (() -> Unit)? = null) {
        if (pushMessage.pushId < 0 && pushMessage.messageType < 0) {
            return
        }
        val avatarImageWidth = DisplayUtil.dp2px(48f)
        val iconUrl = pushMessage.getLargeIconUrl()
        if (iconUrl == null) {
            showInBroadcastNotification(pushMessage, null)
            return
        }

        val url = imageService.getResizeUrl(iconUrl, avatarImageWidth, avatarImageWidth)
        imageService.fetchImage(url, object : IImageLoadResultListener {
            override fun onSuccess(bitmap: Bitmap) {
                super.onSuccess(bitmap)
                showInBroadcastNotification(pushMessage, bitmap)
                completeCallback?.invoke()
            }
            override fun onFailed() {
                super.onFailed()
                showInBroadcastNotification(pushMessage, null)
                completeCallback?.invoke()
            }
        })
    }

    private fun showInBroadcastNotification(pushMessage: JiehePushMessage, bitmap: Bitmap?) {
        CoroutineScope(Dispatcher.UI).launch {
            if(needHandleNotification(pushMessage.messageType)) {
                handleNotification(pushMessage)
                return@launch
            }
            val notifyId = pushMessage.pushId.toInt()
            val group = pushMessage.getTargetId() ?: ""
            val resultPendingIntent = if (Build.VERSION.SDK_INT == Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
                PendingIntent.getActivity(
                    AppUtil.appContext,
                    notifyId,
                    forwardIntent(pushMessage),
                    PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
                    ActivityOptions.makeBasic().setPendingIntentBackgroundActivityStartMode(
                        ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
                    ).toBundle()
                )
            } else {
                PendingIntent.getActivity(
                    AppUtil.appContext,
                    notifyId,
                    forwardIntent(pushMessage),
                    PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
                )
            }
            var title = pushMessage.pushTitle ?: getCompatString(R.string.app_name)

            val content = pushMessage.pushContent ?: ""
            val builder = NotificationCompat.Builder(AppUtil.appContext, pushMessage.channelId)
                .setSmallIcon(getNotificationSmallIcon())
                .setContentTitle(title)
                .setContentText(content)
                .setColor(getCompatColor(APP_R.color.color_app_main))
                .setContentIntent(resultPendingIntent)
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setAutoCancel(true)
                .setTicker(content)
                .setDefaults(Notification.DEFAULT_ALL)
            var roundedBitmap: Bitmap?
            withContext(Dispatcher.WENEXT_THREAD_POOL) {
                roundedBitmap = ImageUtil.getRoundedCornerBitmap(bitmap, DisplayUtil.dp2px(8f).toFloat())
                if (roundedBitmap == null) {
                    roundedBitmap = CircleDrawable.drawableToBitmap(getCompatDrawable(R.drawable.ic_launcher))
                }
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                val remoteViews = RemoteViews(PackageUtil.getPackageName(), R.layout.layout_in_broadcast_notification).apply {
                    setImageViewBitmap(R.id.iv_avatar, roundedBitmap)
                    setTextViewText(R.id.tv_title, title)
                    setTextViewText(R.id.tv_content, content)
                }
                val bigRemoteViews = RemoteViews(PackageUtil.getPackageName(), R.layout.layout_in_broadcast_notification_big).apply {
                    setImageViewBitmap(R.id.iv_avatar, roundedBitmap)
                    setTextViewText(R.id.tv_title, title)
                    setTextViewText(R.id.tv_content, content)
                }
                builder.setStyle(NotificationCompat.DecoratedCustomViewStyle())
                    .setCustomContentView(remoteViews)
                    .setCustomBigContentView(bigRemoteViews)
                    .setGroup(group)
            } else {
                builder.setLargeIcon(roundedBitmap)
            }
            NotificationManagerCompat.from(AppUtil.appContext).notify(notifyId, builder.build())
        }
    }

    fun cancelNotification(notifyId: Int) {
        NotificationManagerCompat.from(AppUtil.appContext).cancel(notifyId)
    }

    private fun needHandleNotification(messageType: Long): Boolean {
        return messageType == PushMessageType.CALL_MATCH_RESULT.type || messageType == PushMessageType.CALL_MATCH_ASK.type
    }

    private fun handleNotification(pushMessage: JiehePushMessage) {
        when(pushMessage.messageType) {
            // TODO: 封装通知能力, 做成类似socket的功能
//            PushMessageType.CALL_MATCH_ASK.type -> {
//                val data = gson.fromJson(pushMessage.pushContent, CallMatchReqAsk::class.java)
//                CallModule.getMatchNotificationView(AppUtil.appContext)?.showNotifyView(data.userInfo, data.matchTimeout, data.matchId)
//            }
//            PushMessageType.CALL_MATCH_RESULT.type -> {
//                val data = gson.fromJson(pushMessage.pushContent, CallMatchResultNotify::class.java)
//                if (data.matchResult == MatchResult.CANCEL.value || data.matchResult == MatchResult.FAILED.value || (data.matchResult == MatchResult.SUCCESS.value && data.peerUid != ProfileModule.getMyUid())) {
//                    CallModule.getMatchNotificationView(AppUtil.appContext)?.cancelNotifyView()
//                }
//            }
            else -> {
                //NTD
            }
        }
    }

    private fun showNormalNotification(pushMessage: JiehePushMessage) {
        val notifyId = pushMessage.pushId.toInt()
        val resultPendingIntent = PendingIntent.getActivity(
            AppUtil.appContext,
            notifyId,
            forwardIntent(pushMessage),
            PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        val title = pushMessage.pushTitle ?: getCompatString(R.string.app_name)
        val content = pushMessage.pushContent ?: ""
        val largeIcon = BitmapFactory.decodeResource(AppUtil.appContext.resources, R.drawable.ic_launcher)
        val builder = NotificationCompat.Builder(AppUtil.appContext, pushMessage.channelId)
            .setSmallIcon(getNotificationSmallIcon())
            .setLargeIcon(largeIcon)
            .setContentTitle(title)
            .setContentText(content)
            .setColor(getCompatColor(APP_R.color.color_app_main))
            .setContentIntent(resultPendingIntent)
            .setPriority(NotificationCompat.PRIORITY_MAX)
            .setAutoCancel(true)
            .setTicker(content)
            .setDefaults(Notification.DEFAULT_ALL)
        NotificationManagerCompat.from(AppUtil.appContext).notify(notifyId, builder.build())
    }

    private fun getNotificationSmallIcon(): Int {
        return if (Build.VERSION.SDK_INT < 21) {
            R.drawable.ic_launcher
        } else {
            R.drawable.notification_ic
        }
    }

    fun isNotificationPermissionGranted(activity: FragmentActivity): Boolean {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
            return true
        }

        if (PermissionUtils.hasPermissions(activity, Manifest.permission.POST_NOTIFICATIONS)) {
            return true
        }
        return false
    }

    @SuppressLint("CheckResult")
    fun requestPostNotificationPermission(activity: FragmentActivity) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
            return
        }

        if (PermissionUtils.hasPermissions(activity, Manifest.permission.POST_NOTIFICATIONS)) {
            return
        }

        PermissionUtils.getRxPermissions(activity)
            .request(Manifest.permission.POST_NOTIFICATIONS).subscribe { granted ->
                if (!granted) {
                    CommonDialog.Builder()
                        .message(getCompatString(R.string.common_open_notification_tip))
                        .onPositive {
                            PermissionUtils.goNotificationSettingActivity(activity)
                        }
                        .positiveText(getCompatString(R.string.common_open))
                        .setShowDefaultCancel(true)
                        .dismissAfterClick(true)
                        .build()
                        .show(activity.supportFragmentManager, "POST_NOTIFICATIONS_PERMISSION_NO_GRANT")
                }
            }
    }
}