package com.seven.ikar.kotlin.feature.call

import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.compose.setContent
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.content.ContextCompat
import androidx.compose.runtime.LaunchedEffect
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.seven.ikar.kotlin.app.IkarNativeApp
import com.seven.ikar.kotlin.core.model.CallMediaType
import com.seven.ikar.kotlin.core.push.AndroidAppVisibilityState
import com.seven.ikar.kotlin.core.push.PendingIncomingCallInvite
import com.seven.ikar.kotlin.core.push.applyToIntent
import com.seven.ikar.kotlin.core.push.pendingIncomingCallInviteFromIntent
import com.seven.ikar.kotlin.ui.theme.IkarKotlinTheme

class IncomingCallActivity : ComponentActivity() {
    private val applicationContainer
        get() = (application as IkarNativeApp).container
    private var shouldAutoAccept: Boolean = false
    private val incomingCallPermissionsLauncher = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) {
        if (hasPermissionsForCurrentCall()) {
            applicationContainer.callManager.acceptCurrentCall()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        configureWindow()
        syncCallFromIntent(intent)
        syncAutoAcceptFromIntent(intent)
        setContent {
            IkarKotlinTheme {
                val activeCall = applicationContainer.callManager.currentCall.collectAsStateWithLifecycle().value
                LaunchedEffect(activeCall?.callId, activeCall?.stage) {
                    if (activeCall == null) {
                        finish()
                    }
                }
                if (activeCall != null) {
                    CallScreen(
                        state = activeCall,
                        onAccept = applicationContainer.callManager::acceptCurrentCall,
                        onDecline = applicationContainer.callManager::declineCurrentCall,
                        onEnd = applicationContainer.callManager::endCurrentCall
                    )
                }
            }
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        syncCallFromIntent(intent)
        syncAutoAcceptFromIntent(intent)
    }

    override fun onStart() {
        super.onStart()
        AndroidAppVisibilityState.setVisible(true)
        if (shouldAutoAccept) {
            shouldAutoAccept = false
            window.decorView.post {
                acceptCurrentCallWithPermissions()
            }
        }
    }

    override fun onStop() {
        AndroidAppVisibilityState.setVisible(false)
        super.onStop()
    }

    private fun configureWindow() {
        WindowCompat.setDecorFitsSystemWindows(window, false)
        window.statusBarColor = Color.TRANSPARENT
        window.navigationBarColor = Color.TRANSPARENT
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setShowWhenLocked(true)
            setTurnScreenOn(true)
        } else {
            @Suppress("DEPRECATION")
            window.addFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
                    WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
            )
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            window.isNavigationBarContrastEnforced = false
            window.isStatusBarContrastEnforced = false
        }

        WindowInsetsControllerCompat(window, window.decorView).apply {
            isAppearanceLightStatusBars = false
            isAppearanceLightNavigationBars = false
        }
    }

    private fun syncCallFromIntent(intent: Intent?) {
        val invite = intent?.let(::pendingIncomingCallInviteFromIntent) ?: return
        if (applicationContainer.sessionStore.read() == null) {
            return
        }

        applicationContainer.callManager.presentIncomingCallInvite(
            callId = invite.callId,
            chatId = invite.chatId,
            callerId = invite.callerId,
            callerDisplayName = invite.callerDisplayName,
            callerPhoneNumber = invite.callerPhoneNumber,
            mediaType = invite.mediaType
        )
    }

    private fun syncAutoAcceptFromIntent(intent: Intent?) {
        if (intent?.getBooleanExtra(AutoAcceptExtra, false) != true) {
            return
        }

        intent.putExtra(AutoAcceptExtra, false)
        shouldAutoAccept = true
    }

    private fun acceptCurrentCallWithPermissions() {
        val requiredPermissions = buildList {
            if (ContextCompat.checkSelfPermission(this@IncomingCallActivity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
                add(Manifest.permission.RECORD_AUDIO)
            }
            if (
                applicationContainer.callManager.currentCall.value?.mediaType == CallMediaType.Video &&
                ContextCompat.checkSelfPermission(this@IncomingCallActivity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
            ) {
                add(Manifest.permission.CAMERA)
            }
        }

        if (requiredPermissions.isEmpty()) {
            applicationContainer.callManager.acceptCurrentCall()
        } else {
            incomingCallPermissionsLauncher.launch(requiredPermissions.toTypedArray())
        }
    }

    private fun hasPermissionsForCurrentCall(): Boolean {
        val hasMicrophone = ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.RECORD_AUDIO
        ) == PackageManager.PERMISSION_GRANTED
        val hasCamera = applicationContainer.callManager.currentCall.value?.mediaType != CallMediaType.Video ||
            ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.CAMERA
            ) == PackageManager.PERMISSION_GRANTED
        return hasMicrophone && hasCamera
    }

    companion object {
        private const val AutoAcceptExtra = "autoAcceptIncomingCall"

        fun createLaunchIntent(
            context: Context,
            invite: PendingIncomingCallInvite,
            autoAccept: Boolean = false
        ): Intent =
            invite.applyToIntent(
                Intent(context, IncomingCallActivity::class.java).apply {
                    addFlags(
                        Intent.FLAG_ACTIVITY_NEW_TASK or
                            Intent.FLAG_ACTIVITY_SINGLE_TOP or
                            Intent.FLAG_ACTIVITY_CLEAR_TOP
                    )
                    putExtra(AutoAcceptExtra, autoAccept)
                }
            )
    }
}
