package com.rosetta.messenger

import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.*
import com.rosetta.messenger.data.AccountManager
import com.rosetta.messenger.database.RosettaDatabase
import com.rosetta.messenger.network.CallForegroundService
import com.rosetta.messenger.network.CallManager
import com.rosetta.messenger.network.CallPhase
import com.rosetta.messenger.repository.AvatarRepository
import com.rosetta.messenger.ui.chats.calls.CallOverlay
import com.rosetta.messenger.ui.theme.RosettaAndroidTheme
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

/**
 * Лёгкая Activity для показа входящего звонка на lock screen.
 * Показывается поверх экрана блокировки, без auth/splash.
 * При Accept → переходит в MainActivity. При Decline → закрывается.
 */
@AndroidEntryPoint
class IncomingCallActivity : ComponentActivity() {

    @Inject lateinit var accountManager: AccountManager

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

    override fun onCreate(savedInstanceState: Bundle?) {
        try {
            super.onCreate(savedInstanceState)
        } catch (e: Throwable) {
            Log.e(TAG, "super.onCreate CRASHED", e)
            callLog("super.onCreate CRASHED: ${e.message}")
            finish()
            return
        }
        callLog("onCreate START")

        // Показываем поверх lock screen и включаем экран
        callLog("setting lock screen flags, SDK=${Build.VERSION.SDK_INT}")
        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 or
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
            )
        }

        // Важно: не снимаем keyguard автоматически.
        // Экран звонка может отображаться поверх lockscreen, но разблокировку делает только пользователь.

        try {
            CallManager.initialize(applicationContext)
            callLog("CallManager initialized, phase=${CallManager.state.value.phase}")
        } catch (e: Throwable) {
            callLog("CallManager.initialize CRASHED: ${e.message}")
            Log.e(TAG, "CallManager init failed", e)
        }

        callLog("calling setContent")
        setContent {
            val callState by CallManager.state.collectAsState()

            // Ждём до 10 сек пока WebSocket доставит сигнал (CallManager перейдёт из IDLE)
            var wasIncoming by remember { mutableStateOf(false) }
            var lastPeerIdentity by remember { mutableStateOf(Triple("", "", "")) }

            LaunchedEffect(callState.phase) {
                callLog("phase changed: ${callState.phase}")
                if (callState.phase == CallPhase.INCOMING) wasIncoming = true
                // Закрываем только когда звонок завершился
                if (callState.phase == CallPhase.IDLE && wasIncoming) {
                    callLog("IDLE after INCOMING → finish()")
                    finish()
                }
                // НЕ закрываемся при CONNECTING/ACTIVE — остаёмся на экране звонка
                // IncomingCallActivity показывает полный CallOverlay, не нужно переходить в MainActivity
            }

            LaunchedEffect(callState.peerPublicKey, callState.peerTitle, callState.peerUsername) {
                val hasIdentity =
                    callState.peerPublicKey.isNotBlank() ||
                        callState.peerTitle.isNotBlank() ||
                        callState.peerUsername.isNotBlank()
                if (hasIdentity) {
                    lastPeerIdentity =
                        Triple(callState.peerPublicKey, callState.peerTitle, callState.peerUsername)
                }
            }

            // Показываем INCOMING в IDLE только до первого реального входящего состояния.
            // Иначе после Decline/END на мгновение мелькает "Unknown".
            val shouldShowProvisionalIncoming =
                callState.phase == CallPhase.IDLE &&
                    !wasIncoming &&
                    (callState.peerPublicKey.isNotBlank() ||
                        callState.peerTitle.isNotBlank() ||
                        callState.peerUsername.isNotBlank())

            val displayState = if (shouldShowProvisionalIncoming) {
                callState.copy(phase = CallPhase.INCOMING, statusText = "Incoming call...")
            } else if (callState.phase == CallPhase.IDLE && wasIncoming) {
                // Во время закрытия Activity сохраняем последнее известное имя/peer, чтобы не мигал Unknown.
                callState.copy(
                    peerPublicKey = lastPeerIdentity.first,
                    peerTitle = lastPeerIdentity.second,
                    peerUsername = lastPeerIdentity.third
                )
            } else {
                callState
            }

            val avatarRepository = remember {
                val accountKey = accountManager.getLastLoggedPublicKey().orEmpty()
                if (accountKey.isNotBlank()) {
                    val db = RosettaDatabase.getDatabase(applicationContext)
                    AvatarRepository(
                        context = applicationContext,
                        avatarDao = db.avatarDao(),
                        currentPublicKey = accountKey
                    )
                } else null
            }

            RosettaAndroidTheme(darkTheme = true) {
                CallOverlay(
                    state = displayState,
                    isDarkTheme = true,
                    avatarRepository = avatarRepository,
                    isExpanded = true,
                    onAccept = {
                        callLog("onAccept tapped, phase=${callState.phase}")
                        if (callState.phase == CallPhase.INCOMING) {
                            val result = CallManager.acceptIncomingCall()
                            callLog("acceptIncomingCall result=$result")
                            // Остаёмся на IncomingCallActivity — она покажет CONNECTING → ACTIVE
                        } else {
                            callLog("onAccept: phase=${callState.phase}, trying accept anyway")
                            CallManager.acceptIncomingCall()
                        }
                    },
                    onDecline = {
                        callLog("onDecline tapped")
                        CallManager.declineIncomingCall()
                        finish()
                    },
                    onEnd = {
                        callLog("onEnd tapped")
                        CallManager.endCall()
                        finish()
                    },
                    onToggleMute = { CallManager.toggleMute() },
                    onToggleSpeaker = { CallManager.toggleSpeaker() }
                )
            }
        }
    }

    private fun openMainActivity() {
        callLog("openMainActivity")
        val intent = Intent(this, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or
                Intent.FLAG_ACTIVITY_SINGLE_TOP or
                Intent.FLAG_ACTIVITY_CLEAR_TOP
            putExtra(CallForegroundService.EXTRA_OPEN_CALL_FROM_NOTIFICATION, true)
        }
        startActivity(intent)
    }

    private fun callLog(msg: String) {
        Log.d(TAG, msg)
        try {
            val ctx = applicationContext ?: return
            val dir = java.io.File(ctx.filesDir, "crash_reports")
            if (!dir.exists()) dir.mkdirs()
            val f = java.io.File(dir, "call_notification_log.txt")
            val ts = java.text.SimpleDateFormat("HH:mm:ss.SSS", java.util.Locale.getDefault()).format(java.util.Date())
            f.appendText("$ts [IncomingCallActivity] $msg\n")
        } catch (e: Throwable) {
            Log.e(TAG, "callLog write failed: ${e.message}")
        }
    }
}
