package com.humand.demo.modules.IncomingCallMessagingService

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.KeyguardManager
import android.app.Person
import android.content.*
import android.graphics.drawable.Icon
import android.media.AudioAttributes
import android.net.Uri
import android.os.Build
import androidx.core.graphics.drawable.IconCompat
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.humand.demo.R
import com.humand.demo.modules.CallService.NativeCallsEventObserver
import com.humand.demo.modules.IncomingCallMessagingService.activity.AcceptCallActivity
import com.humand.demo.modules.IncomingCallMessagingService.activity.FullScreenCallActivity
import com.humand.demo.modules.IncomingCallMessagingService.common.*
import com.humand.demo.modules.IncomingCallMessagingService.player.RingtonePlayer
import com.humand.demo.modules.IncomingCallMessagingService.receiver.CallActionReceiver

fun cancelNotification(ctx: Context) {
    RingtonePlayer.stop()
    val nm = ctx.getSystemService(NotificationManager::class.java)
    nm?.cancel(Constants.NOTIFICATION_ID)
}


fun isHonorDevice(): Boolean {
    try {
        val manufacturer = Build.MANUFACTURER.lowercase()
        val brand = Build.BRAND.lowercase()
        return manufacturer.contains("huawei") || brand.contains("huawei") ||
                manufacturer.contains("honor") || brand.contains("honor")
    } catch (e: Exception) {
        return false
    }
}

class IncomingCallMessagingService : FirebaseMessagingService() {

    override fun onNewToken(token: String) {
        super.onNewToken(token)
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        val data = remoteMessage.data

        val typeValue = data[Constants.CallPayloadKeys.TYPE]
        if (typeValue == null) {
            // If no type is provided, pass to default Firebase messaging service
            val reactService = io.invertase.firebase.messaging.ReactNativeFirebaseMessagingService()
            reactService.onMessageReceived(remoteMessage)
            return
        }
        
        val type = Constants.NotificationType.fromValue(typeValue)
        if (type == null) {
            // If type is not recognized, pass to default Firebase messaging service
            val reactService = io.invertase.firebase.messaging.ReactNativeFirebaseMessagingService()
            reactService.onMessageReceived(remoteMessage)
            return
        }

        when (type) {
            Constants.NotificationType.CALL_MISSED_V2,
            Constants.NotificationType.CALL_ENDED,
            Constants.NotificationType.CALL_ACCEPTED,
            Constants.NotificationType.CALL_REJECTED -> {
                val notificationCallId = data[Constants.CallPayloadKeys.ID]
                android.util.Log.d("IncomingCallService", "Call status notification: type=$typeValue, callId=$notificationCallId")

                // Always stop ringtone and cancel incoming call notification
                cancelNotification(this)
                val intent = Intent(Constants.CLOSE_FULL_SCREEN_ACTIVITY_EVENT)
                LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
                return
            }

            Constants.NotificationType.CALL_INITIALIZED_V2,
            Constants.NotificationType.CALL_JOIN_REQUESTED -> {
                val callId = data[Constants.CallPayloadKeys.ID] ?: return

                android.util.Log.d("IncomingCallService", "Processing incoming call: $callId")

                val callType = type!!
                val callerName = data[Constants.CallPayloadKeys.CALLER] ?: ""
                // When invited to join an existing call (CALL_JOIN_REQUESTED), always treat as group call
                // since there are already 2+ participants. This prevents the invited user from ending
                // the call for everyone when they leave.
                val isGroup = data[Constants.CallPayloadKeys.IS_GROUP] == "true" ||
                    type == Constants.NotificationType.CALL_JOIN_REQUESTED
                val providerCallId = data[Constants.CallPayloadKeys.PROVIDER_CALL_ID] ?: ""
                val avatarUrl = data[Constants.CallPayloadKeys.AVATAR_URL]
                val config = data[Constants.CallPayloadKeys.INITIALIZATION_CONFIG]
                val hasVideo = config.hasVideoEnabled()

                val payload = CallPayload(
                    callId,
                    callType,
                    callerName,
                    isGroup,
                    providerCallId,
                    avatarUrl,
                    config
                )

                NativeCallsEventObserver.observeCallRinging(
                    callId = callId,
                    providerCallId = providerCallId,
                    cameraEnabled = hasVideo,
                    isGroup = isGroup,
                    direction = "incoming"
                )

                val acceptIntent = Intent(this, AcceptCallActivity::class.java).apply {
                    putExtra(Constants.CALL_PAYLOAD, payload)
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    action = "ACCEPT_INTENT_${payload.id}"
                }
                val acceptPendingIntent = PendingIntent.getActivity(
                    this,
                    payload.id.hashCode(),
                    acceptIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
                )

                val declineIntent = Intent(this, CallActionReceiver::class.java).apply {
                    action = Constants.Actions.DECLINE
                    putExtra(Constants.CALL_PAYLOAD, payload)
                }
                val declinePendingIntent = PendingIntent.getBroadcast(
                    this, payload.id.hashCode() + 1, declineIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
                )

                val fullScreenIntent = Intent(this, FullScreenCallActivity::class.java).apply {
                    putExtra(Constants.CALL_PAYLOAD, payload)
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                }

                val fullScreenPendingIntent = PendingIntent.getActivity(
                    this,
                    payload.id.hashCode() + 2,
                    fullScreenIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
                )

                val notificationManager = getSystemService(NotificationManager::class.java)
                val existingChannel = notificationManager.getNotificationChannel(Constants.CHANNEL_NAME)

                if (existingChannel != null && existingChannel.importance < NotificationManager.IMPORTANCE_HIGH) {
                    notificationManager.deleteNotificationChannel(Constants.CHANNEL_NAME)
                }

                // create a channel
                val channel = NotificationChannel(
                    Constants.CHANNEL_NAME,
                    getString(R.string.app_name),
                    NotificationManager.IMPORTANCE_HIGH
                ).apply {
                    description = getString(R.string.notification_channel_calls_description)
                    setSound(null, null)
                    lockscreenVisibility = Notification.VISIBILITY_PUBLIC
                    setBypassDnd(true)
                    enableVibration(true)
                    // Use a custom vibration pattern for Honor devices
                    vibrationPattern = if (isHonorDevice()) {
                        longArrayOf(0, 700, 300, 700, 300, 900)
                    } else {
                        longArrayOf(0L)
                    }

                }
                notificationManager?.createNotificationChannel(channel)

                val icon = IconCompat.createWithResource(this, R.drawable.humand_blue_logo)

                val callerPerson = Person.Builder()
                    .setName(getString(R.string.app_name))
                    .setIcon(icon.toIcon(this))
                    .setImportant(true)
                    .build()

                val contentTextKey = if (isGroup) {
                    R.string.incoming_call_from_group
                } else {
                    R.string.incoming_call_from
                }

                val systemNotificationText = getString(contentTextKey, payload.callerName)

                val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
                val isDeviceLocked = keyguardManager.isKeyguardLocked

                val notificationBuilder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                    val builder = Notification.Builder(this, Constants.CHANNEL_NAME)
                        .setSmallIcon(R.drawable.bootsplash_logo)
                        .setLargeIcon(icon.toIcon())
                        .setContentTitle(getString(R.string.app_name))
                        .setContentText(systemNotificationText)
                        .setCategory(Notification.CATEGORY_CALL)
                        .setStyle(
                            Notification.CallStyle.forIncomingCall(
                                callerPerson,
                                declinePendingIntent,
                                acceptPendingIntent
                            )
                        )
                        .addPerson(callerPerson)
                        .setOngoing(true)
                        .setAutoCancel(false)
                        .setShowWhen(false)
                        .setVisibility(Notification.VISIBILITY_PUBLIC)
                        .setContentIntent(fullScreenPendingIntent)
                        .setFullScreenIntent(fullScreenPendingIntent, true)

                    builder
                } else {
                    val declineAction = Notification.Action.Builder(
                        Icon.createWithResource(this, R.drawable.btn_call_decline),
                        getString(R.string.incoming_call_decline),
                        declinePendingIntent
                    ).build()

                    val acceptAction = Notification.Action.Builder(
                        Icon.createWithResource(this, R.drawable.btn_call_accept),
                        getString(R.string.incoming_call_accept),
                        acceptPendingIntent
                    ).build()

                    val builder = Notification.Builder(this, Constants.CHANNEL_NAME)
                        .setSmallIcon(R.drawable.bootsplash_logo)
                        .setContentTitle(getString(R.string.app_name))
                        .setContentText(systemNotificationText)
                        .setCategory(Notification.CATEGORY_CALL)
                        .setPriority(Notification.PRIORITY_HIGH)
                        .setOngoing(true)
                        .addAction(declineAction)
                        .addAction(acceptAction)
                        .setVisibility(Notification.VISIBILITY_PUBLIC)
                        .setContentIntent(fullScreenPendingIntent)

                    if (isDeviceLocked) {
                        builder.setFullScreenIntent(fullScreenPendingIntent, true)
                    }

                    builder
                }
                val notification = notificationBuilder.build()
                notificationManager?.notify(Constants.NOTIFICATION_ID, notification)

                val soundUri = Uri.parse("android.resource://${packageName}/${R.raw.notification}")

                RingtonePlayer.start(applicationContext, soundUri)
            }

            else -> {
                val reactService =
                    io.invertase.firebase.messaging.ReactNativeFirebaseMessagingService()
                reactService.onMessageReceived(remoteMessage)
            }
        }
    }
}

