package app.closer

import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.activity.result.contract.ActivityResultContracts
import androidx.lifecycle.lifecycleScope
import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import app.closer.BuildConfig
import app.closer.core.navigation.AppNavigation
import app.closer.core.notifications.TokenRegistrar
import app.closer.domain.model.AuthState
import app.closer.notifications.PartnerNotificationPayload
import app.closer.notifications.PartnerNotificationType
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import app.closer.domain.repository.AppSettings
import app.closer.domain.repository.AuthRepository
import app.closer.domain.repository.SettingsRepository
import app.closer.domain.repository.ThemeMode
import app.closer.ui.theme.CloserTheme
import com.google.firebase.auth.FirebaseAuth
import dagger.hilt.android.AndroidEntryPoint
import java.io.File
import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
    @Inject lateinit var settingsRepository: SettingsRepository
    @Inject lateinit var authRepository: AuthRepository
    @Inject lateinit var tokenRegistrar: TokenRegistrar

    private val notificationPermissionLauncher =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { }

    // Route to navigate to after a notification tap (set from the launch intent). Backed by state
    // so a tap while the app is already running (onNewIntent) also re-triggers navigation.
    private val pendingDeepLink = mutableStateOf<String?>(null)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        maybeRequestNotificationPermission()
        registerFcmToken()
        pendingDeepLink.value = deepLinkRouteFromIntent(intent)
        if (BuildConfig.DEBUG) attemptDebugAutoLogin()
        setContent {
            val settings by settingsRepository.settings.collectAsState(initial = AppSettings())
            val systemInDarkTheme = isSystemInDarkTheme()
            val useDarkTheme = when (settings.themeMode) {
                ThemeMode.DEVICE -> systemInDarkTheme
                ThemeMode.LIGHT -> false
                ThemeMode.DARK -> true
            }

            var sessionVerified by remember { mutableStateOf(false) }
            val needsBiometricLock = settings.biometricLoginEnabled
                && authRepository.currentUserId != null
                && !sessionVerified

            CloserTheme(darkTheme = useDarkTheme) {
                SideEffect {
                    WindowCompat.getInsetsController(window, window.decorView).apply {
                        isAppearanceLightStatusBars = !useDarkTheme
                        isAppearanceLightNavigationBars = !useDarkTheme
                    }
                }
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    if (needsBiometricLock) {
                        BiometricLockScreen(
                            activity = this@MainActivity,
                            onUnlocked = { sessionVerified = true }
                        )
                    } else {
                        AppNavigation(
                            pendingDeepLink = pendingDeepLink.value,
                            onDeepLinkConsumed = { pendingDeepLink.value = null }
                        )
                    }
                }
            }
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        deepLinkRouteFromIntent(intent)?.let { pendingDeepLink.value = it }
    }

    /**
     * Resolves a navigation route from a notification tap. When the app is backgrounded/closed the
     * OS shows the FCM `notification` block and, on tap, launches us with the message `data` as
     * plain intent extras (no deep-link Uri) — so we rebuild the route here. A real deep-link Uri
     * (from our own foreground-posted PendingIntent) is left for the NavHost to handle.
     */
    private fun deepLinkRouteFromIntent(intent: Intent?): String? {
        intent ?: return null
        if (intent.data != null) return null
        val type = intent.getStringExtra("type") ?: return null
        val coupleId = intent.getStringExtra("couple_id") ?: ""
        val payload = PartnerNotificationPayload(
            questionId = intent.getStringExtra("question_id"),
            conversationId = intent.getStringExtra("conversation_id"),
            gameSessionId = intent.getStringExtra("game_session_id"),
            gameType = intent.getStringExtra("game_type"),
            capsuleId = intent.getStringExtra("capsule_id"),
            challengeId = intent.getStringExtra("challenge_id"),
            avatarUrl = intent.getStringExtra("sender_avatar_url")
        )
        return PartnerNotificationType.fromRemoteType(type)?.routeFor(payload, coupleId)
    }

    /**
     * Ensure the server always has this device's FCM token while a user is signed in. The token is
     * generated at install (before sign-in), so onNewToken alone never stored it — this fixes the
     * root cause of no push notifications being delivered.
     */
    private fun registerFcmToken() {
        lifecycleScope.launch {
            authRepository.authState
                .filterIsInstance<AuthState.Authenticated>()
                .map { it.userId }
                .distinctUntilChanged()
                .collect {
                    runCatching { tokenRegistrar.register() }
                }
        }
    }

    private fun maybeRequestNotificationPermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
            ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
            != PackageManager.PERMISSION_GRANTED
        ) {
            notificationPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
        }
    }

    private fun attemptDebugAutoLogin() {
        val tokenFile = File(filesDir, "closer_debug_token.txt")
        if (!tokenFile.exists()) return
        val token = tokenFile.readText().trim()
        tokenFile.delete()
        if (token.isBlank()) return
        Log.d("CloserDebug", "Signing in with debug custom token")
        FirebaseAuth.getInstance().signInWithCustomToken(token)
            .addOnSuccessListener { Log.d("CloserDebug", "Debug sign-in succeeded") }
            .addOnFailureListener { e -> Log.e("CloserDebug", "Debug sign-in failed", e) }
    }
}

@Composable
private fun BiometricLockScreen(activity: AppCompatActivity, onUnlocked: () -> Unit) {
    LaunchedEffect(Unit) {
        BiometricPrompt(
            activity,
            ContextCompat.getMainExecutor(activity),
            object : BiometricPrompt.AuthenticationCallback() {
                override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                    onUnlocked()
                }
            }
        ).authenticate(
            BiometricPrompt.PromptInfo.Builder()
                .setTitle("Unlock Closer")
                .setSubtitle("Verify it's you to continue")
                .setAllowedAuthenticators(
                    BiometricManager.Authenticators.BIOMETRIC_STRONG or
                            BiometricManager.Authenticators.DEVICE_CREDENTIAL
                )
                .build()
        )
    }
    Box(modifier = Modifier.fillMaxSize())
}
