package com.radiola

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.lifecycle.lifecycleScope
import com.radiola.data.local.TokenDataStore
import com.radiola.ui.auth.AuthScreen
import com.radiola.ui.charts.ChartsScreen
import com.radiola.ui.components.MiniPlayer
import com.radiola.ui.favorites.FavoritesScreen
import com.radiola.ui.favorites.FavoritesViewModel
import com.radiola.ui.history.HistoryScreen
import com.radiola.ui.navigation.BottomNavBar
import com.radiola.ui.navigation.NavDestinations
import com.radiola.ui.player.PlayerBottomSheet
import com.radiola.ui.player.PlayerViewModel
import com.radiola.ui.recordings.RecordingsScreen
import com.radiola.ui.settings.SettingsScreen
import com.radiola.ui.stations.StationsScreen
import com.radiola.ui.alarms.AlarmsScreen
import com.radiola.ui.stations.StationsViewModel
import com.radiola.service.PlayerService
import com.radiola.ui.theme.RadiolaTheme
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import javax.inject.Inject

@OptIn(ExperimentalMaterial3Api::class)
@AndroidEntryPoint
class MainActivity : ComponentActivity() {

    @Inject
    lateinit var tokenDataStore: TokenDataStore

    @Inject
    lateinit var settingsRepository: com.radiola.domain.repository.SettingsRepository

    @Inject
    lateinit var launcherIconManager: com.radiola.util.LauncherIconManager

    // После ответа на запрос уведомлений — просим исключение из оптимизации батареи.
    private val notifPermLauncher = registerForActivityResult(
        androidx.activity.result.contract.ActivityResultContracts.RequestPermission()
    ) { maybeRequestBatteryExemption() }

    override fun onCreate(savedInstanceState: Bundle?) {
        installSplashScreen()
        super.onCreate(savedInstanceState)
        lifecycleScope.launch {
            tokenDataStore.preload()
            // Старт плеер-сервиса уводим с критического пути запуска — ускоряет
            // появление первого кадра (сплэша).
            startService(Intent(this@MainActivity, PlayerService::class.java))
        }
        ensureBackgroundPlaybackAllowed()
        enableEdgeToEdge()
        // Тему берём из быстрого SharedPreferences (его пишет LauncherIconManager при
        // смене темы) — синхронно и МГНОВЕННО, без блокировки первого кадра. Так сплэш
        // и приложение сразу нужного цвета, и тёмный системный сплэш не висит лишнее.
        val initialPaletteId = getSharedPreferences("radiola_prefs", MODE_PRIVATE)
            .getString("icon_alias", "forest") ?: "forest"
        setContent {
            // Выбранная цветовая тема (мгновенно перекрашивает всё приложение).
            val paletteId by settingsRepository.getThemePalette().collectAsState(initial = initialPaletteId)
            // Иконка лаунчера следует теме (срабатывает на старте и при смене темы).
            LaunchedEffect(paletteId) {
                launcherIconManager.applyIfNeeded(com.radiola.ui.theme.ThemePalette.fromId(paletteId))
            }
            RadiolaTheme(palette = com.radiola.ui.theme.ThemePalette.fromId(paletteId)) {
                // Сплэш рисуем на ПЕРВОМ (дешёвом) кадре; тяжёлый контент (ViewModels,
                // плеер) композим следующим кадром ПОД сплэшем — так логотип появляется
                // почти сразу, без долгого тёмного ожидания холодного старта.
                var showSplash by remember { mutableStateOf(true) }
                var contentReady by remember { mutableStateOf(false) }
                LaunchedEffect(Unit) { contentReady = true }
                LaunchedEffect(Unit) {
                    kotlinx.coroutines.delay(1600)
                    showSplash = false
                }

                if (contentReady) {
                val navController = rememberNavController()
                val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
                var showPlayer by remember { mutableStateOf(false) }
                val playerViewModel: PlayerViewModel = hiltViewModel()
                val stationsViewModel: StationsViewModel = hiltViewModel()
                val favoritesViewModel: FavoritesViewModel = hiltViewModel()
                val isPlaying by playerViewModel.isPlaying.collectAsState()
                val currentStation by playerViewModel.currentStation.collectAsState()
                val currentTrack by playerViewModel.currentTrack.collectAsState()
                val favoriteIds by favoritesViewModel.favoriteIds.collectAsState()
                val stations by stationsViewModel.stations.collectAsState()
                val favorites by favoritesViewModel.favorites.collectAsState()
                val isRecording by playerViewModel.isRecording.collectAsState()
                val isLoggedIn by tokenDataStore.isLoggedIn.collectAsState(initial = false)

                // --- Авто-обновление: проверяем версию на старте, показываем диалог ---
                var pendingUpdate by remember { mutableStateOf<com.radiola.update.VersionInfo?>(null) }
                var updateState by remember { mutableStateOf(com.radiola.ui.update.UpdateState.IDLE) }
                var updateProgress by remember { mutableIntStateOf(0) }
                var updateError by remember { mutableStateOf<String?>(null) }
                var downloadedApk by remember { mutableStateOf<java.io.File?>(null) }
                val updateScope = rememberCoroutineScope()
                LaunchedEffect(Unit) {
                    val info = com.radiola.update.UpdateManager.checkUpdate() ?: return@LaunchedEffect
                    if (info.versionCode > BuildConfig.VERSION_CODE) pendingUpdate = info
                }

                // Авторизация необязательна — всегда стартуем со станций.
                // Вход доступен из Настроек.
                val startDestination = NavDestinations.Stations.route

                val currentRoute = navController
                    .currentBackStackEntryAsState().value?.destination?.route
                val showChrome = currentRoute != NavDestinations.Auth.route

                // Альбомная ориентация: вместо нижнего бара — боковой рейл слева,
                // мини-плеер уезжает под контент. Портрет — прежняя раскладка.
                val landscape = com.radiola.ui.util.isLandscape()

                Scaffold(
                    bottomBar = {
                        if (showChrome && !landscape) {
                            Column(Modifier.navigationBarsPadding()) {
                                if (currentStation != null) {
                                    MiniPlayer(
                                        stationName = currentStation!!.name,
                                        track = currentTrack,
                                        isPlaying = isPlaying,
                                        onClick = { showPlayer = true },
                                        onPlayPause = { playerViewModel.togglePlayPause() }
                                    )
                                    Spacer(Modifier.height(8.dp))
                                }
                                // Навигация доступна и без входа — приложением можно
                                // пользоваться анонимно.
                                BottomNavBar(navController)
                            }
                        }
                    }
                ) { paddingValues ->
                  Row(
                    modifier = Modifier
                        .padding(paddingValues)
                        .fillMaxSize()
                        .then(if (landscape) Modifier.displayCutoutPadding() else Modifier)
                  ) {
                    if (showChrome && landscape) {
                        com.radiola.ui.navigation.SideNavRail(navController)
                    }
                    Column(modifier = Modifier.weight(1f).fillMaxHeight()) {
                    NavHost(
                        navController = navController,
                        startDestination = startDestination,
                        modifier = Modifier.weight(1f).fillMaxWidth(),
                        enterTransition = {
                            androidx.compose.animation.fadeIn(androidx.compose.animation.core.tween(220)) +
                                androidx.compose.animation.slideInVertically(
                                    androidx.compose.animation.core.tween(220)
                                ) { it / 24 }
                        },
                        exitTransition = { androidx.compose.animation.fadeOut(androidx.compose.animation.core.tween(160)) },
                        popEnterTransition = { androidx.compose.animation.fadeIn(androidx.compose.animation.core.tween(220)) },
                        popExitTransition = { androidx.compose.animation.fadeOut(androidx.compose.animation.core.tween(160)) }
                    ) {
                        composable(NavDestinations.Stations.route) {
                            StationsScreen(
                                onStationClick = { station ->
                                    playerViewModel.play(station, stations)
                                    showPlayer = true
                                }
                            )
                        }
                        composable(NavDestinations.Charts.route) {
                            ChartsScreen()
                        }
                        composable(NavDestinations.Favorites.route) {
                            FavoritesScreen(
                                onStationClick = { station ->
                                    playerViewModel.play(station, favorites)
                                    showPlayer = true
                                }
                            )
                        }
                        composable(NavDestinations.History.route) {
                            HistoryScreen()
                        }
                        composable(NavDestinations.Recordings.route) {
                            RecordingsScreen()
                        }
                        composable(NavDestinations.Settings.route) {
                            SettingsScreen(
                                onNavigateToAuth = {
                                    navController.navigate(NavDestinations.Auth.route)
                                },
                                onNavigateToAlarms = {
                                    navController.navigate(NavDestinations.Alarms.route)
                                },
                                onNavigateToEqualizer = {
                                    navController.navigate(NavDestinations.Equalizer.route)
                                }
                            )
                        }
                        composable(NavDestinations.Alarms.route) {
                            AlarmsScreen(
                                onNavigateBack = { navController.popBackStack() }
                            )
                        }
                        composable(NavDestinations.Equalizer.route) {
                            com.radiola.ui.equalizer.EqualizerScreen(
                                onNavigateBack = { navController.popBackStack() }
                            )
                        }
                        composable(NavDestinations.Auth.route) {
                            AuthScreen(
                                onAuthSuccess = {
                                    navController.navigate(NavDestinations.Stations.route) {
                                        popUpTo(NavDestinations.Auth.route) { inclusive = true }
                                    }
                                },
                                onSkip = {
                                    navController.navigate(NavDestinations.Stations.route) {
                                        popUpTo(NavDestinations.Auth.route) { inclusive = true }
                                    }
                                }
                            )
                        }
                    }
                    if (showChrome && landscape && currentStation != null) {
                        MiniPlayer(
                            stationName = currentStation!!.name,
                            track = currentTrack,
                            isPlaying = isPlaying,
                            onClick = { showPlayer = true },
                            onPlayPause = { playerViewModel.togglePlayPause() }
                        )
                        Spacer(Modifier.height(12.dp))
                    }
                    } // конец контентной колонки
                  } // конец Row (рейл + контент)
                }

                if (showPlayer) {
                    ModalBottomSheet(
                        onDismissRequest = { showPlayer = false },
                        sheetState = sheetState,
                        containerColor = MaterialTheme.colorScheme.background
                    ) {
                        PlayerBottomSheet(
                            station = currentStation,
                            track = currentTrack,
                            isPlaying = isPlaying,
                            onPlayPause = { playerViewModel.togglePlayPause() },
                            onNext = { playerViewModel.playNext() },
                            onPrevious = { playerViewModel.playPrevious() },
                            isFavorite = currentStation?.let { favoriteIds.contains(it.id) } ?: false,
                            onToggleFavorite = { currentStation?.let { favoritesViewModel.toggleFavorite(it) } },
                            isRecording = isRecording,
                            onToggleRecording = { playerViewModel.toggleRecording() }
                        )
                    }
                }

                pendingUpdate?.let { update ->
                    com.radiola.ui.update.UpdateDialog(
                        versionName = update.versionName,
                        notes = update.notes,
                        isForce = update.forceUpdate,
                        state = updateState,
                        progress = updateProgress,
                        errorMsg = updateError,
                        onPrimary = {
                            when (updateState) {
                                com.radiola.ui.update.UpdateState.DOWNLOADED ->
                                    downloadedApk?.let {
                                        com.radiola.update.UpdateManager.installApk(this@MainActivity, it)
                                    }
                                com.radiola.ui.update.UpdateState.DOWNLOADING -> {}
                                else -> {
                                    updateState = com.radiola.ui.update.UpdateState.DOWNLOADING
                                    updateProgress = 0
                                    updateError = null
                                    updateScope.launch {
                                        val f = com.radiola.update.UpdateManager.downloadApk(
                                            this@MainActivity, update.downloadUrl
                                        ) { updateProgress = it }
                                        if (f != null &&
                                            com.radiola.update.UpdateManager.verifySha256(f, update.sha256)
                                        ) {
                                            downloadedApk = f
                                            updateState = com.radiola.ui.update.UpdateState.DOWNLOADED
                                            com.radiola.update.UpdateManager.installApk(this@MainActivity, f)
                                        } else {
                                            updateError = if (f == null) "Не удалось загрузить обновление"
                                                else "Контрольная сумма не совпала"
                                            updateState = com.radiola.ui.update.UpdateState.ERROR
                                        }
                                    }
                                }
                            }
                        },
                        onDismiss = { if (!update.forceUpdate) pendingUpdate = null }
                    )
                }

                } // конец if (contentReady): тяжёлый контент композится под сплэшем

                // Тематический экран загрузки поверх всего (рисуем сами — системный
                // сплэш Android 12+ нельзя перекрасить под выбранную тему).
                androidx.compose.animation.AnimatedVisibility(
                    visible = showSplash,
                    enter = androidx.compose.animation.EnterTransition.None,
                    exit = androidx.compose.animation.fadeOut(androidx.compose.animation.core.tween(450))
                ) {
                    com.radiola.ui.components.SplashOverlay(
                        com.radiola.ui.theme.ThemePalette.fromId(paletteId)
                    )
                }
            }
        }
    }

    /**
     * Условия для стабильного фонового воспроизведения:
     *  1) POST_NOTIFICATIONS (Android 13+) — без него не видно медиа-уведомление и
     *     foreground-сервис легко убивается системой;
     *  2) исключение из оптимизации батареи (Doze/ColorOS глушат фон).
     */
    private fun ensureBackgroundPlaybackAllowed() {
        if (android.os.Build.VERSION.SDK_INT >= 33 &&
            checkSelfPermission(android.Manifest.permission.POST_NOTIFICATIONS) !=
            android.content.pm.PackageManager.PERMISSION_GRANTED
        ) {
            // После ответа (в колбэке) попросим про батарею — не два диалога разом.
            notifPermLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS)
        } else {
            maybeRequestBatteryExemption()
        }
    }

    private fun maybeRequestBatteryExemption() {
        val pm = getSystemService(Context.POWER_SERVICE) as android.os.PowerManager
        if (pm.isIgnoringBatteryOptimizations(packageName)) return
        // Спрашиваем один раз на установку, чтобы не надоедать.
        val prefs = getSharedPreferences("radiola_prefs", MODE_PRIVATE)
        if (prefs.getBoolean("battery_opt_asked", false)) return
        prefs.edit().putBoolean("battery_opt_asked", true).apply()
        runCatching {
            startActivity(
                Intent(
                    android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
                    android.net.Uri.parse("package:$packageName")
                )
            )
        }
    }
}
