package com.tencent.qcloud.tuikit.tuicallkit.view.component.incomingbanner

import android.app.Notification
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import com.adealink.frame.log.Log
import com.adealink.weparty.MainActivity
import com.adealink.weparty.call.R
import com.adealink.weparty.commonui.ext.dp
import com.adealink.weparty.module.call.data.ACCEPT_CALL_ACTION
import com.adealink.weparty.module.call.data.REJECT_CALL_ACTION
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition
import com.tencent.qcloud.tuicore.util.TUIBuild
import com.tencent.qcloud.tuikit.tuicallkit.common.data.Constants
import com.tencent.qcloud.tuikit.tuicallkit.common.metrics.KeyMetrics
import com.tencent.qcloud.tuikit.tuicallkit.manager.feature.NotificationFeature
import io.trtc.tuikit.atomicxcore.api.call.CallParticipantInfo
import io.trtc.tuikit.atomicxcore.api.call.CallParticipantStatus
import io.trtc.tuikit.atomicxcore.api.call.CallStore
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import com.adealink.weparty.R as APP_R

class IncomingNotificationBanner(context: Context) {
    private val context: Context = context.applicationContext
    private val scope = MainScope()
    private var notificationManager: NotificationManager =
        context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

    private val notificationId = 9909
    private var remoteViews: RemoteViews? = null
    private var notification: Notification? = null
    private var callStatus = CallParticipantStatus.None

    private fun registerObserver() {
        scope.launch {
            CallStore.shared.observerState.selfInfo.collect { selfInfo ->
                if (callStatus == selfInfo.status) {
                    return@collect
                }
                callStatus = selfInfo.status
                if (callStatus == CallParticipantStatus.None || callStatus == CallParticipantStatus.Accept) {
                    cancelNotification()
                }
            }
        }
    }

    fun showNotification(participant: CallParticipantInfo) {
        Log.i(TAG, "showNotification, user: $participant")
        val callId = CallStore.shared.observerState.activeCall.value.callId
        KeyMetrics.countUV(KeyMetrics.EventId.WAKEUP, callId)
        registerObserver()
        notification = createNotification()

        if (participant.name.isNullOrEmpty()) {
            remoteViews?.setTextViewText(R.id.tv_incoming_title, participant.id)
        } else {
            remoteViews?.setTextViewText(R.id.tv_incoming_title, participant.name)
        }

        remoteViews?.setTextViewText(
            R.id.tv_desc,
            context.getString(R.string.call_invite_audio_call)
        )
        remoteViews?.setImageViewResource(R.id.btn_accept, R.drawable.call_accept_ic)

        if (participant.avatarUrl.isNullOrEmpty()) {
            remoteViews?.setImageViewResource(
                R.id.img_incoming_avatar,
                APP_R.drawable.common_default_avatar_ic
            )
            notificationManager.notify(notificationId, notification)
        } else {
            val uri = Uri.parse(participant.avatarUrl)
            Glide.with(context).asBitmap().load(uri)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .placeholder(APP_R.drawable.common_default_avatar_ic)
                .apply(RequestOptions.bitmapTransform(RoundedCorners(40.dp())))
                .into(object : SimpleTarget<Bitmap>() {
                    override fun onResourceReady(
                        resource: Bitmap,
                        transition: Transition<in Bitmap>?
                    ) {
                        remoteViews?.setImageViewBitmap(R.id.img_incoming_avatar, resource)
                        notificationManager.notify(notificationId, notification)
                    }

                    override fun onLoadFailed(errorDrawable: Drawable?) {
                        remoteViews?.setImageViewResource(
                            R.id.img_incoming_avatar,
                            APP_R.drawable.common_default_avatar_ic
                        )
                        notificationManager.notify(notificationId, notification)
                    }
                })
        }
    }

    private fun cancelNotification() {
        Log.i(TAG, "cancelNotification")
        notificationManager.cancel(notificationId)
        scope.cancel()
    }

    private fun createNotification(): Notification {
        val channelId = NotificationFeature.CHANNEL_ID
        val builder = NotificationCompat.Builder(context)
            .setOngoing(true)
            .setAutoCancel(true)
            .setWhen(System.currentTimeMillis())
            .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
            .setTimeoutAfter(Constants.CALL_WAITING_MAX_TIME * 1000L)

        if (TUIBuild.getVersionInt() >= Build.VERSION_CODES.LOLLIPOP) {
            builder.setCategory(NotificationCompat.CATEGORY_CALL)
            builder.priority = NotificationCompat.PRIORITY_MAX
        }

        builder.setChannelId(channelId)
        builder.setSmallIcon(APP_R.drawable.notification_ic)
        builder.setSound(null)

        builder.setContentIntent(getPendingIntent())
        builder.setFullScreenIntent(getPendingIntent(), true)

        remoteViews =
            RemoteViews(context.packageName, R.layout.tuicallkit_incoming_notification_view)
        remoteViews?.setOnClickPendingIntent(R.id.btn_decline, getDeclineIntent())
        remoteViews?.setOnClickPendingIntent(R.id.btn_accept, getAcceptIntent())

        builder.setCustomContentView(remoteViews)
        builder.setCustomBigContentView(remoteViews)
        return builder.build()
    }

    private fun getPendingIntent(): PendingIntent {
        val intent = Intent(context, MainActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.action == ACCEPT_CALL_ACTION
        return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
    }

    private fun getDeclineIntent(): PendingIntent {
        val intent = Intent(context, IncomingCallReceiver::class.java)
        intent.action = REJECT_CALL_ACTION
        return PendingIntent.getBroadcast(context, 1, intent, PendingIntent.FLAG_IMMUTABLE)
    }

    private fun getAcceptIntent(): PendingIntent {
        val intent = Intent(context, MainActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.action = ACCEPT_CALL_ACTION
        return PendingIntent.getActivity(context, 2, intent, PendingIntent.FLAG_IMMUTABLE)
    }

    companion object {
        private const val TAG = "IncomingViewNotification"
    }
}