package com.fabledsword.minstrel

import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.compose.rememberNavController
import com.fabledsword.minstrel.auth.ui.AuthGateViewModel
import com.fabledsword.minstrel.cache.CachedTrackIds
import com.fabledsword.minstrel.connectivity.LocalServerHealth
import com.fabledsword.minstrel.connectivity.ServerHealth
import com.fabledsword.minstrel.connectivity.NetworkStatusController
import com.fabledsword.minstrel.nav.DetailSeedCache
import com.fabledsword.minstrel.nav.LocalDetailSeedCache
import com.fabledsword.minstrel.nav.MinstrelNavGraph
import com.fabledsword.minstrel.nav.NowPlaying
import com.fabledsword.minstrel.shared.widgets.LocalCachedTrackIds
import com.fabledsword.minstrel.theme.MinstrelTheme
import com.fabledsword.minstrel.theme.ThemePreferenceViewModel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import javax.inject.Inject

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    @Inject lateinit var seedCache: DetailSeedCache
    @Inject lateinit var cachedTrackIds: CachedTrackIds
    @Inject lateinit var serverHealth: NetworkStatusController

    // Flipped to true when the user taps the media notification (or
    // any other entry point that asks for the full player). The App
    // composable observes this, navigates to NowPlaying once the
    // NavHost is ready, then calls back to reset the flag so the
    // navigation doesn't re-fire on the next recomposition.
    private val pendingOpenNowPlaying = MutableStateFlow(false)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        consumeOpenNowPlayingIntent(intent)
        setContent {
            App(
                seedCache = seedCache,
                cachedTrackIds = cachedTrackIds,
                serverHealth = serverHealth,
                pendingOpenNowPlaying = pendingOpenNowPlaying.asStateFlow(),
                onOpenedNowPlaying = { pendingOpenNowPlaying.value = false },
            )
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        consumeOpenNowPlayingIntent(intent)
    }

    private fun consumeOpenNowPlayingIntent(intent: Intent?) {
        if (intent?.getBooleanExtra(EXTRA_OPEN_NOW_PLAYING, false) == true) {
            pendingOpenNowPlaying.value = true
            // Strip the extra so a subsequent config-change recreation
            // doesn't re-trigger the navigation.
            intent.removeExtra(EXTRA_OPEN_NOW_PLAYING)
        }
    }

    companion object {
        /** PendingIntent extra set by [com.fabledsword.minstrel.player.MinstrelPlayerService]
         *  so a media-notification tap lands on the full NowPlaying screen
         *  instead of whatever shell route MainActivity last rendered. */
        const val EXTRA_OPEN_NOW_PLAYING = "com.fabledsword.minstrel.action.OPEN_NOW_PLAYING"
    }
}

@Composable
private fun App(
    seedCache: DetailSeedCache,
    cachedTrackIds: CachedTrackIds,
    serverHealth: NetworkStatusController,
    pendingOpenNowPlaying: StateFlow<Boolean>,
    onOpenedNowPlaying: () -> Unit,
    themeVm: ThemePreferenceViewModel = hiltViewModel(),
    gate: AuthGateViewModel = hiltViewModel(),
) {
    val theme by themeVm.themeMode.collectAsStateWithLifecycle()
    val cached by cachedTrackIds.ids.collectAsStateWithLifecycle()
    val health: ServerHealth by serverHealth.state.collectAsStateWithLifecycle()
    val pending by pendingOpenNowPlaying.collectAsStateWithLifecycle()
    MinstrelTheme(darkOverride = theme.toDarkOverride()) {
        CompositionLocalProvider(
            LocalDetailSeedCache provides seedCache,
            LocalCachedTrackIds provides cached,
            LocalServerHealth provides health,
        ) {
            val startDestination by gate.startDestination.collectAsStateWithLifecycle()
            val resolved = startDestination
            if (resolved == null) {
                BootSplash()
            } else {
                // No bottom nav, no drawer — navigation is per-screen via
                // the AppBar actions row + kebab (`MainAppBarActions`). The
                // MiniPlayer is included by each in-shell route's
                // `ShellScaffold` wrap; full-screen routes (NowPlaying /
                // Queue / unauthenticated) bypass the shell entirely.
                val navController = rememberNavController()
                // Honour a pending notification-tap once the NavHost is
                // mounted. launchSingleTop avoids stacking copies of
                // NowPlaying if the user taps the notification while
                // already on it; the callback clears the flag so a later
                // recomposition (config change, theme switch) doesn't
                // re-navigate.
                LaunchedEffect(pending, navController) {
                    if (pending) {
                        navController.navigate(NowPlaying) { launchSingleTop = true }
                        onOpenedNowPlaying()
                    }
                }
                MinstrelNavGraph(
                    navController = navController,
                    startDestination = resolved,
                    modifier = Modifier.fillMaxSize(),
                )
            }
        }
    }
}

@Composable
private fun BootSplash() {
    Surface(
        modifier = Modifier.fillMaxSize(),
        color = MaterialTheme.colorScheme.background,
    ) {
        Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
            CircularProgressIndicator(color = MaterialTheme.colorScheme.primary)
        }
    }
}
