package com.pixelmintdrop

import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.VibrationEffect
import android.os.Vibrator
import android.os.VibratorManager
import android.view.View
import android.view.HapticFeedbackConstants
import androidx.appcompat.app.AppCompatActivity
import androidx.activity.viewModels // Added import
import androidx.lifecycle.Observer // Added import
import com.pixelmintdrop.databinding.ActivityMainBinding
import com.pixelmintdrop.game.GameHaptics
import com.pixelmintdrop.game.GameView
import com.pixelmintdrop.game.TitleScreen
import com.pixelmintdrop.model.GameBoard
import com.pixelmintdrop.audio.GameMusic
import com.pixelmintdrop.model.HighScoreManager
import com.pixelmintdrop.model.PlayerProgressionManager
import com.pixelmintdrop.model.StatsManager
import com.pixelmintdrop.ui.ProgressionScreen
import com.pixelmintdrop.ui.ThemeSelector
import com.pixelmintdrop.ui.BlockSkinSelector
import java.text.SimpleDateFormat
import java.util.*
import android.graphics.Color
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import android.graphics.Rect
import android.util.Log
import android.view.KeyEvent
import android.os.Handler
import android.os.Looper
import android.view.MotionEvent
import com.pixelmintdrop.game.GamepadController
import android.view.InputDevice
import android.widget.Toast
import android.content.BroadcastReceiver
import android.content.IntentFilter
import android.graphics.drawable.ColorDrawable
import androidx.core.content.ContextCompat
import android.widget.Button
import android.widget.ScrollView
import android.widget.ImageButton
import android.graphics.drawable.GradientDrawable
import android.widget.TextView
import android.widget.Switch
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import android.view.ViewGroup
import androidx.core.view.updatePadding
import kotlin.math.max
import kotlin.math.min
import kotlin.random.Random
// Google Play Games Services imports
import com.google.android.gms.games.PlayGames
import com.google.android.gms.games.PlayGamesSdk
import com.google.android.gms.games.GamesSignInClient
import com.google.android.gms.auth.api.signin.GoogleSignIn // Added for silent sign-in
import com.google.android.gms.auth.api.signin.GoogleSignInClient // Added for silent sign-in
import com.google.android.gms.auth.api.signin.GoogleSignInOptions // Added for silent sign-in
import com.pixelmintdrop.model.GooglePlayGamesManager // Added import for listener

class MainActivity : AppCompatActivity(), 
    GamepadController.GamepadConnectionListener,
    GamepadController.GamepadMenuListener,
    GamepadController.GamepadNavigationListener {
    
    companion object {
        private const val TAG = "MainActivity"
        private const val RC_LEADERBOARD_UI = 9004 // Request code for leaderboard UI
    }
    
    // ViewModel
    private val viewModel: MainActivityViewModel by viewModels() // Added ViewModel
    
    // Google Play Games Services
    private lateinit var gamesSignInClient: GamesSignInClient
    private lateinit var googleSignInClient: GoogleSignInClient // Added for silent sign-in
    
    // UI components
    private lateinit var binding: ActivityMainBinding
    private lateinit var gameView: GameView
    private lateinit var gameHaptics: GameHaptics
    private lateinit var gameBoard: GameBoard
    private lateinit var gameMusic: GameMusic
    private lateinit var titleScreen: TitleScreen
    private lateinit var highScoreManager: HighScoreManager
    private lateinit var statsManager: StatsManager
    private lateinit var progressionManager: PlayerProgressionManager
    private lateinit var progressionScreen: ProgressionScreen
    private lateinit var themeSelector: ThemeSelector
    private lateinit var blockSkinSelector: BlockSkinSelector
    private var pauseMenuScrollView: ScrollView? = null
    
    // Game state
    private var piecesPlaced = 0
    private var gameStartTime = 0L
    private val maxLevel = 20
    private var lastLines = 0  // Track the previous lines count
    private var lastLinesGroup = 0  // Track which 10-line group we're in (0-9, 10-19, etc.)
    private var lastRandomLevel = 0  // Track the level at which we last did a random change
    private var currentTheme = PlayerProgressionManager.THEME_CLASSIC
    private val handler = Handler(Looper.getMainLooper())
    
    // Activity result launcher for high score entry
    private lateinit var highScoreEntryLauncher: ActivityResultLauncher<Intent>

    // Gamepad controller
    private lateinit var gamepadController: GamepadController
    
    // Input device change receiver
    private val inputDeviceReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            when (intent.action) {
                Intent.ACTION_CONFIGURATION_CHANGED -> {
                    // A gamepad might have connected or disconnected
                    checkGamepadConnections()
                }
            }
        }
    }
    
    // Track connected gamepads to detect changes
    private val connectedGamepads = mutableSetOf<String>()
    
    // Track currently selected menu item in pause menu for gamepad navigation
    private var currentMenuSelection = 0
    private val pauseMenuItems = mutableListOf<View>()
    private val customizationMenuItems = mutableListOf<View>()
    
    // Add these new properties at the class level
    private var currentCustomizationMenuSelection = 0
    
    // CAPTURE session stats needed for display into MainActivity member variables
    private var lastSessionScore = 0
    private var lastSessionLines = 0
    private var lastSessionPieces = 0
    private var lastSessionTime = 0L
    private var lastSessionLevel = 0
    private var lastSessionSingles = 0
    private var lastSessionDoubles = 0
    private var lastSessionTriples = 0
    private var lastSessionQuads = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        // Register activity result launcher for high score entry
        highScoreEntryLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            // When returning from HighScoreEntryActivity:
            // 1. Hide progression screen
            progressionScreen.visibility = View.GONE
            // 2. Make game over container visible (it's already laid out)
            binding.gameOverContainer.visibility = View.VISIBLE 
            // 3. *** Call showGameOverScreenDirectly to populate the stats ***
            showGameOverScreenDirectly(lastSessionScore) // Use the captured score
            
            // Keep all game UI elements hidden
            binding.gameControlsContainer.visibility = View.GONE
            binding.holdPieceView.visibility = View.GONE
            binding.nextPieceView.visibility = View.GONE
            binding.pauseButton.visibility = View.GONE
            binding.leftControlsPanel?.visibility = View.GONE
            binding.rightControlsPanel?.visibility = View.GONE
        }
        
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        // Initialize Google Play Games Services
        PlayGamesSdk.initialize(this)
        gamesSignInClient = PlayGames.getGamesSignInClient(this)
        // Initialize GoogleSignInClient for silent sign-in
        val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN).build()
        googleSignInClient = GoogleSignIn.getClient(this, signInOptions)
        
        // Request sign-in silently
        signInToPlayGames()
        
        // Store initial padding values before applying insets
        val initialPausePadding = Rect(binding.pauseContainer.paddingLeft, binding.pauseContainer.paddingTop,
                                        binding.pauseContainer.paddingRight, binding.pauseContainer.paddingBottom)
        val initialGameOverPadding = Rect(binding.gameOverContainer.paddingLeft, binding.gameOverContainer.paddingTop,
                                          binding.gameOverContainer.paddingRight, binding.gameOverContainer.paddingBottom)
        val initialCustomizationPadding = Rect(binding.customizationContainer.paddingLeft, binding.customizationContainer.paddingTop,
                                                binding.customizationContainer.paddingRight, binding.customizationContainer.paddingBottom)
        val initialProgressionPadding = Rect(binding.progressionScreen.paddingLeft, binding.progressionScreen.paddingTop,
                                            binding.progressionScreen.paddingRight, binding.progressionScreen.paddingBottom)

        // Apply insets to the pause container
        ViewCompat.setOnApplyWindowInsetsListener(binding.pauseContainer) { view, windowInsets ->
            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
            // Apply insets by adding to initial padding
            view.updatePadding(
                left = initialPausePadding.left + insets.left,
                top = initialPausePadding.top + insets.top,
                right = initialPausePadding.right + insets.right,
                bottom = initialPausePadding.bottom + insets.bottom
            )
            WindowInsetsCompat.CONSUMED
        }

        // Apply insets to the game over container
        ViewCompat.setOnApplyWindowInsetsListener(binding.gameOverContainer) { view, windowInsets ->
            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
            view.updatePadding(
                left = initialGameOverPadding.left + insets.left,
                top = initialGameOverPadding.top + insets.top,
                right = initialGameOverPadding.right + insets.right,
                bottom = initialGameOverPadding.bottom + insets.bottom
            )
            WindowInsetsCompat.CONSUMED
        }

        // Apply insets to the customization container
        ViewCompat.setOnApplyWindowInsetsListener(binding.customizationContainer) { view, windowInsets ->
            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
            view.updatePadding(
                left = initialCustomizationPadding.left + insets.left,
                top = initialCustomizationPadding.top + insets.top,
                right = initialCustomizationPadding.right + insets.right,
                bottom = initialCustomizationPadding.bottom + insets.bottom
            )
            WindowInsetsCompat.CONSUMED
        }

        // Apply insets to the progression screen
        ViewCompat.setOnApplyWindowInsetsListener(binding.progressionScreen) { view, windowInsets ->
            val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
            view.updatePadding(
                left = initialProgressionPadding.left + insets.left,
                top = initialProgressionPadding.top + insets.top,
                right = initialProgressionPadding.right + insets.right,
                bottom = initialProgressionPadding.bottom + insets.bottom
            )
            WindowInsetsCompat.CONSUMED
        }
        
        // Disable Android back gesture to prevent accidental app exits
        disableAndroidBackGesture()
        
        // Initialize game components
        gameBoard = GameBoard()
        gameHaptics = GameHaptics(this)
        gameView = binding.gameView
        titleScreen = binding.titleScreen
        gameMusic = GameMusic(this)
        highScoreManager = HighScoreManager(this)
        statsManager = StatsManager(this)
        progressionManager = PlayerProgressionManager(this)
        themeSelector = binding.customizationThemeSelector!!
        blockSkinSelector = binding.customizationBlockSkinSelector!!
        pauseMenuScrollView = binding.pauseMenuScrollView
        
        // Observe ViewModel LiveData
        viewModel.currentScore.observe(this, Observer { newScore ->
            // Use actual ID from layout - display only the number
            binding.scoreText.text = newScore.toString()
        })

        viewModel.currentLevel.observe(this, Observer { newLevel ->
            // Use actual ID from layout - display only the number
            binding.currentLevelText.text = newLevel.toString()
        })
        
        // Observe Sound/Music state
        viewModel.isSoundEnabled.observe(this, Observer { enabled ->
            updateSoundToggleUI(enabled)
        })

        viewModel.isMusicEnabled.observe(this, Observer { enabled ->
            updateMusicToggleUI(enabled)
            // Also update GameMusic immediately
            gameMusic.setEnabled(enabled)
        })
        
        // Observe Random Mode state
        viewModel.isRandomModeEnabled.observe(this, Observer { enabled ->
            // Update the switch UI
            binding.randomModeSwitch?.isChecked = enabled
        })
        
        // Initialize gamepad controller
        gamepadController = GamepadController(gameView)
        gamepadController.setGamepadConnectionListener(this)
        gamepadController.setGamepadMenuListener(this)
        gamepadController.setGamepadNavigationListener(this)
        
        // Set up touch event forwarding
        binding.touchInterceptor?.setOnTouchListener { _, event ->
            if (gameView.visibility == View.VISIBLE && !gameView.isPaused && !gameView.isGameOver()) {
                gameView.onTouchEvent(event)
                true
            } else {
                false
            }
        }
        
        // Set up progression screen
        progressionScreen = binding.progressionScreen
        progressionScreen.visibility = View.GONE
        progressionScreen.onContinue = {
            progressionScreen.visibility = View.GONE
            binding.gameOverContainer.visibility = View.VISIBLE
            
            // Keep all game UI elements hidden
            binding.gameControlsContainer.visibility = View.GONE
            binding.holdPieceView.visibility = View.GONE
            binding.nextPieceView.visibility = View.GONE
            binding.pauseButton.visibility = View.GONE
            binding.leftControlsPanel?.visibility = View.GONE
            binding.rightControlsPanel?.visibility = View.GONE
            
            // Get all themes with "Theme" in their name
            val themeRewards = progressionManager.getUnlockedThemes().filter { 
                it.contains("Theme", ignoreCase = true) 
            }
            
            // Update theme selector if new themes were unlocked
            if (themeRewards.isNotEmpty()) {
                updateThemeSelector()
            }
        }
        
        // Load and apply theme preference
        currentTheme = progressionManager.getSelectedTheme()
        applyTheme(currentTheme)
        
        // Load and apply block skin preference
        gameView.setBlockSkin(progressionManager.getSelectedBlockSkin())
        
        // Update block skin selector with current selection
        blockSkinSelector.updateBlockSkins(
            progressionManager.getUnlockedBlocks(),
            gameView.getCurrentBlockSkin(),
            progressionManager.getPlayerLevel()
        )
        
        // Set up game view
        gameView.setGameBoard(gameBoard)
        gameView.setHaptics(gameHaptics)
        gameBoard.setStatsManager(statsManager)
        
        // Set up theme selector
        themeSelector.onThemeSelected = { themeId: String ->
            // Apply the new theme globally
            applyTheme(themeId)
            
            // Provide haptic feedback as a cue that the theme changed
            gameHaptics.vibrateForPieceLock()

            // --- Re-apply theme to the currently visible Customization Menu --- 
            val themeColor = getThemeColor(themeId)
            val backgroundColor = getThemeBackgroundColor(themeId)
            
            binding.customizationContainer.setBackgroundColor(backgroundColor)
            binding.customizationLevelBadge.setThemeColor(themeColor)
            applyThemeColorToTextViews(binding.customizationContainer, themeColor)
            // ------------------------------------------------------------------
            
            // // Refreshing pause menu here is not needed for instant update of customization menu
            // if (binding.pauseContainer.visibility == View.VISIBLE) {
            //     showPauseMenu()
            // }
        }
        
        // Set up title screen
        titleScreen.onStartGame = {
            titleScreen.visibility = View.GONE
            gameView.visibility = View.VISIBLE
            binding.gameControlsContainer.visibility = View.VISIBLE
            startGame()
        }
        
        // Initially hide the game view and show title screen
        gameView.visibility = View.GONE
        binding.gameControlsContainer.visibility = View.GONE
        titleScreen.visibility = View.VISIBLE
        
        // Hide landscape control panels if in landscape mode and title screen is visible
        if (resources.configuration.orientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE) {
            binding.leftControlsPanel?.visibility = View.GONE
            binding.rightControlsPanel?.visibility = View.GONE
        }
        
        // Set up pause button to show settings menu
        binding.pauseButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            gameView.pause()
            gameMusic.pause()
            showPauseMenu()
            binding.pauseStartButton.visibility = View.GONE
            binding.resumeButton.visibility = View.VISIBLE
        }
        
        // Set up next piece preview
        binding.nextPieceView.setGameView(gameView)
        gameBoard.onNextPieceChanged = {
            binding.nextPieceView.invalidate()
        }
        
        // Set up hold piece preview
        binding.holdPieceView.setGameView(gameView)
        gameBoard.onPieceLock = {
            binding.holdPieceView.invalidate()
        }
        gameBoard.onPieceMove = {
            binding.holdPieceView.invalidate()
        }
        gameBoard.onPiecePlaced = {
            piecesPlaced++
        }
        
        // Set up music toggle
        binding.musicToggle.setOnClickListener {
            viewModel.toggleMusic() // Use ViewModel
            // Observer will call updateMusicToggleUI and gameMusic.setEnabled
        }
        
        // Set up callbacks
        gameView.onGameStateChanged = { score, level, lines ->
            updateGameStateUI(score, level, lines)
        }
        
        gameView.onGameOver = { finalScore ->
            // Start animation & pause music & play sound
            gameView.startGameOverAnimation()
            gameMusic.pause()
            if (viewModel.isSoundEnabled.value == true) { // Play sound if enabled
                gameMusic.playGameOver()
            }
            
            // Calculate final stats, XP, and high score
            val timePlayedMs = System.currentTimeMillis() - gameStartTime
            statsManager.updateSessionStats(finalScore, gameBoard.lines, piecesPlaced, timePlayedMs, viewModel.currentLevel.value ?: 1)
            val xpGained = progressionManager.calculateGameXP(
                score = finalScore,
                linesCleared = gameBoard.lines,
                level = viewModel.currentLevel.value ?: 1,
                gameTime = timePlayedMs,
                tSpins = statsManager.getSessionTSpins(),
                combos = statsManager.getSessionMaxCombo(),
                quadCount = statsManager.getSessionQuads(),
                perfectClearCount = statsManager.getSessionPerfectClears()
            )
            val newRewards = progressionManager.addXP(xpGained)
            val newHighScore = highScoreManager.isHighScore(finalScore)
            statsManager.endSession() // End session after calculations
            
            // CAPTURE session stats needed for display into MainActivity member variables
            lastSessionScore = statsManager.getSessionScore()
            lastSessionLines = statsManager.getSessionLines()
            lastSessionPieces = statsManager.getSessionPieces()
            lastSessionTime = statsManager.getSessionTime()
            lastSessionLevel = statsManager.getSessionLevel()
            lastSessionSingles = statsManager.getSessionSingles()
            lastSessionDoubles = statsManager.getSessionDoubles()
            lastSessionTriples = statsManager.getSessionTriples()
            lastSessionQuads = statsManager.getSessionQuads()

            // *** Add detailed logging here ***
            Log.d(TAG, "[GameOverDebug] Captured Stats:")
            Log.d(TAG, "[GameOverDebug]   Score: $lastSessionScore (from manager: ${statsManager.getSessionScore()})")
            Log.d(TAG, "[GameOverDebug]   Lines: $lastSessionLines (from manager: ${statsManager.getSessionLines()})")
            Log.d(TAG, "[GameOverDebug]   Pieces: $lastSessionPieces (from manager: ${statsManager.getSessionPieces()})")
            Log.d(TAG, "[GameOverDebug]   Time: $lastSessionTime (from manager: ${statsManager.getSessionTime()})")
            Log.d(TAG, "[GameOverDebug]   Level: $lastSessionLevel (from manager: ${statsManager.getSessionLevel()})")
            Log.d(TAG, "[GameOverDebug]   Singles: $lastSessionSingles (from manager: ${statsManager.getSessionSingles()})")
            Log.d(TAG, "[GameOverDebug]   Doubles: $lastSessionDoubles (from manager: ${statsManager.getSessionDoubles()})")
            Log.d(TAG, "[GameOverDebug]   Triples: $lastSessionTriples (from manager: ${statsManager.getSessionTriples()})")
            Log.d(TAG, "[GameOverDebug]   Quads: $lastSessionQuads (from manager: ${statsManager.getSessionQuads()})")

            // End the session (updates lifetime stats)
            statsManager.endSession()

            Log.d(TAG, "Game Over. Captured Score: $lastSessionScore, Level: $lastSessionLevel, Lines: $lastSessionLines, Start Level: ${viewModel.selectedLevel.value}, New High Score: $newHighScore, XP Gained: $xpGained")

            // Show appropriate screen: Progression or Game Over directly
            if (xpGained > 0 || newHighScore) {
                // Delay showing progression slightly to let animation play
                Handler(Looper.getMainLooper()).postDelayed({
                    showProgressionScreen(xpGained, newRewards, newHighScore, finalScore)
                }, 1500) // Delay can be adjusted
            } else {
                // No XP, no high score -> show game over screen directly after animation
                 Handler(Looper.getMainLooper()).postDelayed({
                    showGameOverScreenDirectly(finalScore)
                }, 1500) // Delay to match progression path
            }
        }
        
        gameView.onLineClear = { lineCount ->
            Log.d(TAG, "Received line clear callback: $lineCount lines")
            // Use enhanced haptic feedback for line clears
            if (viewModel.isSoundEnabled.value == true) { // Read from ViewModel
                Log.d(TAG, "Sound is enabled, triggering haptic feedback")
                try {
                    gameHaptics.vibrateForLineClear(lineCount)
                    Log.d(TAG, "Haptic feedback triggered successfully")
                } catch (e: Exception) {
                    Log.e(TAG, "Error triggering haptic feedback", e)
                }
            } else {
                Log.d(TAG, "Sound is disabled, skipping haptic feedback")
            }
            // Record line clear in stats
            statsManager.recordLineClear(lineCount)
        }
        
        // Add callbacks for piece movement and locking
        gameView.onPieceMove = {
            if (viewModel.isSoundEnabled.value == true) { // Read from ViewModel
                gameHaptics.vibrateForPieceMove()
            }
        }
        
        // Set up button click listeners with haptic feedback
        binding.playAgainButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            hideGameOver()
            gameView.reset()
            startGame()
        }
        
        binding.resumeButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            hidePauseMenu()
            resumeGame()
        }
        
        binding.settingsButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            viewModel.toggleSound() // Use ViewModel
            // Observer will call updateSoundToggleUI
        }

        // Set up pause menu buttons
        binding.pauseStartButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            hidePauseMenu()
            gameView.reset()
            startGame()
        }

        binding.pauseRestartButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            hidePauseMenu()
            gameView.reset()
            startGame()
        }

        // High Scores button
        binding.highScoresButton.setOnClickListener {
            binding.pauseContainer.visibility = View.GONE
            val intent = Intent(this, HighScoresActivity::class.java)
            startActivity(intent)
        }

        // Leaderboard button
        binding.leaderboardButton?.setOnClickListener {
            showLeaderboard()
        }

        binding.pauseLevelUpButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            val currentSelected = viewModel.selectedLevel.value ?: 1
            if (currentSelected < maxLevel) {
                viewModel.setSelectedLevel(currentSelected + 1)
                updateLevelSelector()
            }
        }

        binding.pauseLevelDownButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            val currentSelected = viewModel.selectedLevel.value ?: 1
            if (currentSelected > 1) {
                viewModel.setSelectedLevel(currentSelected - 1)
                updateLevelSelector()
            }
        }
        
        // Set up stats button
        binding.statsButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            val intent = Intent(this, StatsActivity::class.java)
            startActivity(intent)
        }
        
        // Set up customization button
        binding.customizationButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            showCustomizationMenu()
        }

        // Set up customization back button
        binding.customizationBackButton.setOnClickListener {
            gameHaptics.performHapticFeedback(it, HapticFeedbackConstants.VIRTUAL_KEY)
            hideCustomizationMenu()
        }
        
        // Initialize level selector
        updateLevelSelector()
        
        // Enable edge-to-edge display
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // Use the WindowInsetsController for Android 11+ edge-to-edge display
            window.insetsController?.let { controller ->
                controller.hide(android.view.WindowInsets.Type.statusBars() or android.view.WindowInsets.Type.navigationBars())
                controller.systemBarsBehavior = android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // For Android 10, use the deprecated method
            @Suppress("DEPRECATION")
            window.setDecorFitsSystemWindows(false)
        }
        
        // Initialize pause menu items for gamepad navigation
        initPauseMenuNavigation()
        
        // Set up random mode switch
        binding.randomModeSwitch?.apply {
            isChecked = viewModel.isRandomModeEnabled.value ?: false
            isEnabled = progressionManager.getPlayerLevel() >= 5
            setOnCheckedChangeListener { _, isChecked ->
                // Only need to call toggle, ViewModel handles saving
                viewModel.toggleRandomMode()
            }
        }
    }
    
    /**
     * Update UI with current game state
     */
    private fun updateUI(score: Int, level: Int, lines: Int) {
        binding.scoreText.text = score.toString()
        binding.currentLevelText.text = level.toString()
        binding.linesText.text = lines.toString()
        binding.comboText.text = gameBoard.getCombo().toString()
        
        // Force redraw of next piece preview
        binding.nextPieceView.invalidate()
    }
    
    /**
     * Shows the final game over screen with stats.
     */
    private fun showGameOverScreenDirectly(score: Int) { // Keep score param for logging if needed elsewhere
        Log.d(TAG, "Showing final game over screen with score from param: $score, from StatsManager: ${statsManager.getSessionScore()}")
        // Ensure game UI is hidden
        binding.gameControlsContainer.visibility = View.GONE
        binding.holdPieceView.visibility = View.GONE
        binding.nextPieceView.visibility = View.GONE
        binding.pauseButton.visibility = View.GONE
        binding.leftControlsPanel?.visibility = View.GONE
        binding.rightControlsPanel?.visibility = View.GONE
        progressionScreen.visibility = View.GONE // Ensure progression is hidden

        // Update session stats display in the gameOverContainer
        val timeFormat = SimpleDateFormat("HH:mm:ss", Locale.getDefault())
        timeFormat.timeZone = TimeZone.getTimeZone("UTC")
        // val gameTime = System.currentTimeMillis() - gameStartTime // No longer needed here
        
        // --- Consistently use StatsManager session getters --- 
        binding.sessionScoreText.text = "Score: ${statsManager.getSessionScore()}"
        binding.sessionLinesText.text = "Lines: ${statsManager.getSessionLines()}"
        binding.sessionPiecesText.text = "Pieces: ${statsManager.getSessionPieces()}"
        binding.sessionTimeText.text = "Time: ${timeFormat.format(statsManager.getSessionTime())}" 
        binding.sessionLevelText.text = "Level: ${statsManager.getSessionLevel()}" 
        
        binding.sessionSinglesText.text = "Singles: ${statsManager.getSessionSingles()}"
        binding.sessionDoublesText.text = "Doubles: ${statsManager.getSessionDoubles()}"
        binding.sessionTriplesText.text = "Triples: ${statsManager.getSessionTriples()}"
        binding.sessionQuadsText.text = "Quads: ${statsManager.getSessionQuads()}"
        // --- End StatsManager usage ---
        
        // Make the container visible
        binding.gameOverContainer.visibility = View.VISIBLE
        
        // Vibrate if not already vibrated by progression
        if (progressionScreen.visibility != View.VISIBLE) {
             vibrate(VibrationEffect.EFFECT_DOUBLE_CLICK)
        }
    }
    
    /**
     * Show high score entry screen
     */
    private fun showHighScoreEntry(score: Int) {
        val intent = Intent(this, HighScoreEntryActivity::class.java).apply {
            putExtra("score", score)
            putExtra("level", viewModel.currentLevel.value ?: 1) // Read from ViewModel
        }
        // Use the launcher instead of startActivity
        highScoreEntryLauncher.launch(intent)
    }
    
    /**
     * Hide game over screen
     */
    private fun hideGameOver() {
        binding.gameOverContainer.visibility = View.GONE
        progressionScreen.visibility = View.GONE
    }
    
    /**
     * Show customization menu
     */
    private fun showCustomizationMenu() {
        binding.pauseContainer.visibility = View.GONE
        binding.customizationContainer.visibility = View.VISIBLE
        
        // Get theme colors
        val themeColor = getThemeColor(currentTheme)
        val backgroundColor = getThemeBackgroundColor(currentTheme)
        
        // Apply background color to customization container
        binding.customizationContainer.setBackgroundColor(backgroundColor)
        
        // Update level badge with player's level and theme color
        binding.customizationLevelBadge.setLevel(progressionManager.getPlayerLevel())
        binding.customizationLevelBadge.setThemeColor(themeColor)
        
        // Apply theme color to all text views in the container
        applyThemeColorToTextViews(binding.customizationContainer, themeColor)
        
        // Update theme selector with available themes
        binding.customizationThemeSelector?.updateThemes(
            unlockedThemes = progressionManager.getUnlockedThemes(),
            currentTheme = currentTheme
        )
        
        // Update block skin selector with available skins
        binding.customizationBlockSkinSelector?.updateBlockSkins(
            progressionManager.getUnlockedBlocks(),
            gameView.getCurrentBlockSkin(),
            progressionManager.getPlayerLevel()
        )
        
        // Set up block skin selection callback
        binding.customizationBlockSkinSelector?.onBlockSkinSelected = { blockSkin ->
            gameView.setBlockSkin(blockSkin)
            progressionManager.setSelectedBlockSkin(blockSkin)
            gameHaptics.vibrateForPieceLock()
        }
        
        // Initialize customization menu items for gamepad navigation
        initCustomizationMenuNavigation()
        
        // Set up random mode switch
        binding.randomModeSwitch?.apply {
            isChecked = viewModel.isRandomModeEnabled.value ?: false
            isEnabled = progressionManager.getPlayerLevel() >= 5
            setOnCheckedChangeListener { _, isChecked ->
                // Only need to call toggle, ViewModel handles saving
                viewModel.toggleRandomMode()
            }
        }
    }
    
    private fun initCustomizationMenuNavigation() {
        customizationMenuItems.clear()
        
        // Add items in order
        customizationMenuItems.addAll(listOf(
            binding.customizationThemeSelector,
            binding.customizationBlockSkinSelector,
            binding.randomModeSwitch,
            binding.customizationBackButton
        ).filterNotNull().filter { it.visibility == View.VISIBLE })
        
        // Set up focus change listener for scrolling
        binding.customizationMenuScrollView.setOnFocusChangeListener { _, hasFocus ->
            if (hasFocus) {
                // When scroll view gets focus, scroll to focused item
                val focusedView = currentFocus
                if (focusedView != null) {
                    val scrollView = binding.customizationMenuScrollView
                    val itemTop = focusedView.top
                    val scrollViewHeight = scrollView.height
                    
                    // Calculate scroll position to center the focused item
                    val scrollY = itemTop - (scrollViewHeight / 2) + (focusedView.height / 2)
                    scrollView.smoothScrollTo(0, scrollY)
                }
            }
        }
        
        // Set up focus handling between items
        customizationMenuItems.forEachIndexed { index, item ->
            item.setOnFocusChangeListener { _, hasFocus ->
                if (hasFocus) {
                    currentCustomizationMenuSelection = index
                    highlightCustomizationMenuItem(index)
                }
            }
        }
    }
    
    /**
     * Hide customization menu
     */
    private fun hideCustomizationMenu() {
        binding.customizationContainer.visibility = View.GONE
        binding.pauseContainer.visibility = View.VISIBLE
        // Refresh the pause menu to apply theme changes
        showPauseMenu()
    }

    /**
     * Show settings menu
     */
    private fun showPauseMenu() {
        binding.pauseContainer.visibility = View.VISIBLE
        binding.customizationContainer.visibility = View.GONE
        
        // Set button visibility based on game state
        if (gameView.isPaused) {
            binding.resumeButton.visibility = View.VISIBLE
            binding.pauseStartButton.visibility = View.GONE
        } else {
            // This case might happen if pause is triggered before game start (e.g., from title)
            binding.resumeButton.visibility = View.GONE
            binding.pauseStartButton.visibility = View.VISIBLE
        }
        
        // Check if we're in landscape mode (used for finding specific views, not for order)
        val isLandscape = resources.configuration.orientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE
        
        // Update level badge
        binding.pauseLevelBadge?.setLevel(progressionManager.getPlayerLevel())
        binding.pauseLevelBadge?.setThemeColor(getThemeColor(currentTheme))
        
        // Get theme colors
        val themeColor = getThemeColor(currentTheme)
        val backgroundColor = getThemeBackgroundColor(currentTheme)
        
        // Apply background color to pause container
        binding.pauseContainer.setBackgroundColor(backgroundColor)
        
        // Apply theme colors to buttons and toggles
        binding.pauseStartButton.setTextColor(themeColor)
        binding.pauseRestartButton.setTextColor(themeColor)
        binding.resumeButton.setTextColor(themeColor)
        binding.highScoresButton.setTextColor(themeColor)
        binding.leaderboardButton?.setTextColor(themeColor)
        binding.statsButton.setTextColor(themeColor)
        binding.pauseLevelUpButton?.setTextColor(themeColor) // Safe call
        binding.pauseLevelDownButton?.setTextColor(themeColor) // Safe call
        binding.settingsButton?.setTextColor(themeColor) // Safe call for sound toggle button text
        binding.musicToggle?.setColorFilter(themeColor) // Safe call
        binding.customizationButton?.setTextColor(themeColor) // Safe call
        
        // Apply theme colors to text elements (using safe calls)
        binding.settingsTitle?.setTextColor(themeColor)
        binding.selectLevelText?.setTextColor(themeColor)
        binding.musicText?.setTextColor(themeColor)
        binding.pauseLevelText?.setTextColor(themeColor)
        
        // Apply to portrait container as well if needed (assuming root or specific container)
        applyThemeColorToTextViews(binding.pauseContainer, themeColor) // Apply to main container
        
        // Reset scroll position
        binding.pauseMenuScrollView?.scrollTo(0, 0)
        findLandscapeScrollView()?.scrollTo(0, 0)
        
        // Initialize pause menu navigation (builds the list of navigable items)
        initPauseMenuNavigation()
        
        // Reset selection index (will be set and highlighted in showPauseMenu)
        currentMenuSelection = 0
        
        // Highlight the initially selected menu item
        if (pauseMenuItems.isNotEmpty()) {
            highlightMenuItem(currentMenuSelection)
        }
    }
    
    /** Helper to apply theme color to TextViews within a container, avoiding selectors */
    private fun applyThemeColorToTextViews(container: View?, themeColor: Int) {
        if (container == null) return
        if (container is android.view.ViewGroup) {
            for (i in 0 until container.childCount) {
                val child = container.getChildAt(i)
                if (child is TextView) {
                    // Check if parent is a selector
                    var parent = child.parent
                    var isInSelector = false
                    while (parent != null) {
                        if (parent is ThemeSelector || parent is BlockSkinSelector) {
                            isInSelector = true
                            break
                        }
                        if (parent === container) break // Stop at the container boundary
                        parent = parent.parent
                    }
                    if (!isInSelector) {
                        child.setTextColor(themeColor)
                    }
                } else if (child is android.view.ViewGroup) {
                    // Recurse only if not a selector
                    if (child !is ThemeSelector && child !is BlockSkinSelector) {
                        applyThemeColorToTextViews(child, themeColor)
                    }
                }
            }
        }
    }

    /** Helper to get background color based on theme */
    private fun getThemeBackgroundColor(themeId: String): Int {
         return when (themeId) {
            PlayerProgressionManager.THEME_CLASSIC -> Color.BLACK
            PlayerProgressionManager.THEME_NEON -> Color.parseColor("#0D0221")
            PlayerProgressionManager.THEME_MONOCHROME -> Color.parseColor("#1A1A1A")
            PlayerProgressionManager.THEME_RETRO -> Color.parseColor("#3F2832")
            PlayerProgressionManager.THEME_MINIMALIST -> Color.WHITE
            PlayerProgressionManager.THEME_GALAXY -> Color.parseColor("#0B0C10")
            else -> Color.BLACK
        }
    }
    
    /**
     * Hide settings menu
     */
    private fun hidePauseMenu() {
        binding.pauseContainer.visibility = View.GONE
    }
    
    /**
     * Update the level selector display
     */
    private fun updateLevelSelector() {
        binding.pauseLevelText.text = viewModel.selectedLevel.value.toString()
        gameBoard.updateLevel(viewModel.selectedLevel.value ?: 1)
    }
    
    /**
     * Trigger device vibration with predefined effect
     */
    private fun vibrate(effectId: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            // For Android 12+ (API 31+)
            val vibratorManager = getSystemService(Context.VIBRATOR_MANAGER_SERVICE) as VibratorManager
            val vibrator = vibratorManager.defaultVibrator
            vibrator.vibrate(VibrationEffect.createPredefined(effectId))
        } else {
            // For older Android versions
            @Suppress("DEPRECATION")
            val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
            vibrator.vibrate(VibrationEffect.createPredefined(effectId))
        }
    }
    
    /**
     * Update the sound toggle button text
     */
    private fun updateSoundToggleUI(enabled: Boolean) {
        binding.settingsButton.text = getString(
            if (enabled) R.string.sound_on else R.string.sound_off
        )
    }
    
    /**
     * Update the music toggle button icon
     */
    private fun updateMusicToggleUI(enabled: Boolean) {
        binding.musicToggle.setImageResource(
            if (enabled) R.drawable.ic_volume_up
            else R.drawable.ic_volume_off
        )
    }
    
    /**
     * Start a new game
     */
    private fun startGame() {
        Log.d(TAG, "Starting game at level ${viewModel.selectedLevel.value}")
        // Reset session stats FIRST
        statsManager.startNewSession()

        // Reset game state
        viewModel.resetGame() // Resets score and level in ViewModel
        viewModel.setLevel(viewModel.selectedLevel.value ?: 1) // Set initial level from selection
        piecesPlaced = 0
        gameStartTime = System.currentTimeMillis()
        lastLines = 0
        lastLinesGroup = 0
        lastRandomLevel = 0
        // Observers will update scoreText and currentLevelText

        // Reset game view and game board
        gameBoard.reset()
        gameView.reset()
        
        // Ensure block skin is properly set
        val selectedSkin = progressionManager.getSelectedBlockSkin()
        gameView.setBlockSkin(selectedSkin)
        
        // Update selectors to refresh UI state
        blockSkinSelector.updateBlockSkins(
            progressionManager.getUnlockedBlocks(),
            selectedSkin,
            progressionManager.getPlayerLevel()
        )

        // Ensure game UI elements are visible and others hidden
        binding.gameView.visibility = View.VISIBLE
        binding.gameControlsContainer.visibility = View.VISIBLE
        binding.holdPieceView.visibility = View.VISIBLE
        binding.nextPieceView.visibility = View.VISIBLE
        binding.pauseButton.visibility = View.VISIBLE
        binding.gameOverContainer.visibility = View.GONE
        binding.pauseContainer.visibility = View.GONE
        titleScreen.visibility = View.GONE
        progressionScreen.visibility = View.GONE
        
        // Show landscape specific controls if needed
        if (resources.configuration.orientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE) {
            binding.leftControlsPanel?.visibility = View.VISIBLE
            binding.rightControlsPanel?.visibility = View.VISIBLE
        }
        
        // Configure callbacks
        gameView.onGameStateChanged = { score, level, lines ->
            // We'll adapt updateGameStateUI later to use ViewModel
            updateGameStateUI(score, level, lines) 
        }
        
        gameView.onGameOver = { finalScore ->
            // Start animation & pause music & play sound
            gameView.startGameOverAnimation()
            gameMusic.pause()
            if (viewModel.isSoundEnabled.value == true) { // Play sound if enabled
                gameMusic.playGameOver()
            }
            
            // Calculate final stats, XP, and high score
            val timePlayedMs = System.currentTimeMillis() - gameStartTime
            statsManager.updateSessionStats(finalScore, gameBoard.lines, piecesPlaced, timePlayedMs, viewModel.currentLevel.value ?: 1)
            val xpGained = progressionManager.calculateGameXP(
                score = finalScore,
                linesCleared = gameBoard.lines,
                level = viewModel.currentLevel.value ?: 1,
                gameTime = timePlayedMs,
                tSpins = statsManager.getSessionTSpins(),
                combos = statsManager.getSessionMaxCombo(),
                quadCount = statsManager.getSessionQuads(),
                perfectClearCount = statsManager.getSessionPerfectClears()
            )
            val newRewards = progressionManager.addXP(xpGained)
            val newHighScore = highScoreManager.isHighScore(finalScore)
            statsManager.endSession() // End session after calculations
            
            // CAPTURE session stats needed for display into MainActivity member variables
            lastSessionScore = statsManager.getSessionScore()
            lastSessionLines = statsManager.getSessionLines()
            lastSessionPieces = statsManager.getSessionPieces()
            lastSessionTime = statsManager.getSessionTime()
            lastSessionLevel = statsManager.getSessionLevel()
            lastSessionSingles = statsManager.getSessionSingles()
            lastSessionDoubles = statsManager.getSessionDoubles()
            lastSessionTriples = statsManager.getSessionTriples()
            lastSessionQuads = statsManager.getSessionQuads()

            // *** Add detailed logging here ***
            Log.d(TAG, "[GameOverDebug] Captured Stats:")
            Log.d(TAG, "[GameOverDebug]   Score: $lastSessionScore (from manager: ${statsManager.getSessionScore()})")
            Log.d(TAG, "[GameOverDebug]   Lines: $lastSessionLines (from manager: ${statsManager.getSessionLines()})")
            Log.d(TAG, "[GameOverDebug]   Pieces: $lastSessionPieces (from manager: ${statsManager.getSessionPieces()})")
            Log.d(TAG, "[GameOverDebug]   Time: $lastSessionTime (from manager: ${statsManager.getSessionTime()})")
            Log.d(TAG, "[GameOverDebug]   Level: $lastSessionLevel (from manager: ${statsManager.getSessionLevel()})")
            Log.d(TAG, "[GameOverDebug]   Singles: $lastSessionSingles (from manager: ${statsManager.getSessionSingles()})")
            Log.d(TAG, "[GameOverDebug]   Doubles: $lastSessionDoubles (from manager: ${statsManager.getSessionDoubles()})")
            Log.d(TAG, "[GameOverDebug]   Triples: $lastSessionTriples (from manager: ${statsManager.getSessionTriples()})")
            Log.d(TAG, "[GameOverDebug]   Quads: $lastSessionQuads (from manager: ${statsManager.getSessionQuads()})")

            // End the session (updates lifetime stats)
            statsManager.endSession()

            Log.d(TAG, "Game Over. Captured Score: $lastSessionScore, Level: $lastSessionLevel, Lines: $lastSessionLines, Start Level: ${viewModel.selectedLevel.value}, New High Score: $newHighScore, XP Gained: $xpGained")

            // Show appropriate screen: Progression or Game Over directly
            if (xpGained > 0 || newHighScore) {
                // Delay showing progression slightly to let animation play
                Handler(Looper.getMainLooper()).postDelayed({
                    showProgressionScreen(xpGained, newRewards, newHighScore, finalScore)
                }, 1500) // Delay can be adjusted
            } else {
                // No XP, no high score -> show game over screen directly after animation
                 Handler(Looper.getMainLooper()).postDelayed({
                    showGameOverScreenDirectly(finalScore)
                }, 1500) // Delay to match progression path
            }
        }
        
        // Connect line clear callback to gamepad rumble
        gameView.onLineClear = { lineCount ->
            // Vibrate phone
            gameHaptics.vibrateForLineClear(lineCount)
            
            // Vibrate gamepad if connected
            gamepadController.vibrateForLineClear(lineCount)
            
            // Record line clear in stats
            statsManager.recordLineClear(lineCount)
        }
        
        // Reset pause button state
        binding.pauseStartButton.visibility = View.VISIBLE
        binding.resumeButton.visibility = View.GONE
        
        // Start background music if enabled
        if (viewModel.isMusicEnabled.value == true) { // Read from ViewModel
            gameMusic.prepareMusic() // Ensure player is ready
            gameMusic.start()
        }
        
        // Start the game
        gameView.start()
        // Observer ensures gameMusic is enabled/disabled correctly via gameMusic.setEnabled()
        
        // Reset session stats - MOVED TO TOP
        // statsManager.startNewSession()
        progressionManager.startNewSession()
        gameBoard.updateLevel(viewModel.selectedLevel.value ?: 1)
    }
    
    private fun restartGame() {
        gameBoard.reset()
        gameView.visibility = View.VISIBLE
        gameView.start()
        showPauseMenu()
    }
    
    private fun resumeGame() {
        gameView.resume()
        if (viewModel.isMusicEnabled.value == true) { // Read from ViewModel
            gameMusic.resume()
        }
        // Force a redraw to ensure pieces aren't frozen
        gameView.invalidate()
    }
    
    override fun onPause() {
        super.onPause()
        if (gameView.visibility == View.VISIBLE) {
            gameView.pause()
            gameMusic.pause()
        }
        
        // Unregister broadcast receiver
        try {
            unregisterReceiver(inputDeviceReceiver)
        } catch (e: IllegalArgumentException) {
            // Receiver wasn't registered
        }
    }
    
    override fun onResume() {
        super.onResume()
        
        // Register for input device changes
        val filter = IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)
        registerReceiver(inputDeviceReceiver, filter)
        
        // Check for already connected gamepads
        checkGamepadConnections()
        
        // Update visibility of control panels in landscape orientation based on title screen visibility
        if (resources.configuration.orientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE) {
            if (titleScreen.visibility == View.VISIBLE) {
                // Hide control panels when title screen is visible
                binding.leftControlsPanel?.visibility = View.GONE
                binding.rightControlsPanel?.visibility = View.GONE
            } else if (gameView.visibility == View.VISIBLE && binding.gameOverContainer.visibility == View.GONE 
                && binding.pauseContainer.visibility == View.GONE) {
                // Show control panels when game is active
                binding.leftControlsPanel?.visibility = View.VISIBLE
                binding.rightControlsPanel?.visibility = View.VISIBLE
            }
        }
        
        // If we're on the title screen, don't auto-resume the game
        if (titleScreen.visibility == View.GONE && gameView.visibility == View.VISIBLE && binding.gameOverContainer.visibility == View.GONE && binding.pauseContainer.visibility == View.GONE) {
            resumeGame()
        }
        
        // Update theme selector with available themes when pause screen appears
        updateThemeSelector()
    }
    
    override fun onDestroy() {
        super.onDestroy()
        gameMusic.release()
    }
    
    /**
     * Show title screen (for game restart)
     */
    private fun showTitleScreen() {
        gameView.reset()
        gameView.visibility = View.GONE
        binding.gameControlsContainer.visibility = View.GONE
        binding.gameOverContainer.visibility = View.GONE
        binding.pauseContainer.visibility = View.GONE
        titleScreen.visibility = View.VISIBLE
        titleScreen.applyTheme(currentTheme)
    }

    /**
     * Show high scores
     */
    private fun showHighScores() {
        val intent = Intent(this, HighScoresActivity::class.java)
        startActivity(intent)
    }
    
    /**
     * Update the theme selector with unlocked themes
     */
    private fun updateThemeSelector() {
        binding.customizationThemeSelector?.updateThemes(
            unlockedThemes = progressionManager.getUnlockedThemes(),
            currentTheme = currentTheme
        )
    }
    
    /**
     * Apply a theme to the game
     */
    private fun applyTheme(themeId: String) {
        currentTheme = themeId
        val themeColor = when (themeId) {
            PlayerProgressionManager.THEME_CLASSIC -> Color.WHITE
            PlayerProgressionManager.THEME_NEON -> Color.parseColor("#FF00FF")
            PlayerProgressionManager.THEME_MONOCHROME -> Color.LTGRAY
            PlayerProgressionManager.THEME_RETRO -> Color.parseColor("#FF5A5F")
            PlayerProgressionManager.THEME_MINIMALIST -> Color.BLACK
            PlayerProgressionManager.THEME_GALAXY -> Color.parseColor("#66FCF1")
            else -> Color.WHITE
        }
        
        // Get background color for the theme
        val backgroundColor = when (themeId) {
            PlayerProgressionManager.THEME_CLASSIC -> Color.BLACK
            PlayerProgressionManager.THEME_NEON -> Color.parseColor("#0D0221")
            PlayerProgressionManager.THEME_MONOCHROME -> Color.parseColor("#1A1A1A")
            PlayerProgressionManager.THEME_RETRO -> Color.parseColor("#3F2832")
            PlayerProgressionManager.THEME_MINIMALIST -> Color.WHITE
            PlayerProgressionManager.THEME_GALAXY -> Color.parseColor("#0B0C10")
            else -> Color.BLACK
        }
        
        // Apply background color to root view
        binding.root.setBackgroundColor(backgroundColor)
        
        // Apply theme color to title screen
        titleScreen.setThemeColor(themeColor)
        titleScreen.setBackgroundColor(backgroundColor)
        
        // Apply theme color to game over screen
        binding.gameOverContainer.setBackgroundColor(backgroundColor)
        binding.gameOverText.setTextColor(themeColor)
        binding.scoreText.setTextColor(themeColor)
        binding.currentLevelText.setTextColor(themeColor)
        binding.linesText.setTextColor(themeColor)
        binding.comboText.setTextColor(themeColor)
        binding.playAgainButton.setTextColor(themeColor)
        binding.playAgainButton.setBackgroundResource(android.R.color.transparent)
        binding.playAgainButton.setTextSize(24f)
        
        // Apply theme to progression screen (it will handle its own colors)
        progressionScreen.applyTheme(themeId)
        
        // Apply theme color to game view
        gameView.setThemeColor(themeColor)
        gameView.setBackgroundColor(backgroundColor)
        
        // Save theme preference
        progressionManager.setSelectedTheme(themeId)
    }
    
    /**
     * Get the appropriate color for the current theme
     */
    private fun getThemeColor(themeId: String): Int {
        return when (themeId) {
            PlayerProgressionManager.THEME_CLASSIC -> Color.WHITE
            PlayerProgressionManager.THEME_NEON -> Color.parseColor("#FF00FF")
            PlayerProgressionManager.THEME_MONOCHROME -> Color.LTGRAY
            PlayerProgressionManager.THEME_RETRO -> Color.parseColor("#FF5A5F")
            PlayerProgressionManager.THEME_MINIMALIST -> Color.BLACK
            PlayerProgressionManager.THEME_GALAXY -> Color.parseColor("#66FCF1")
            else -> Color.WHITE
        }
    }

    /**
     * Disables the Android system back gesture to prevent accidental exits
     */
    private fun disableAndroidBackGesture() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            // Set the entire window to be excluded from the system gesture areas
            window.decorView.post {
                // Create a list of rectangles representing the edges of the screen to exclude from system gestures
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                    // Use the new API for Android 11+
                    window.decorView.rootWindowInsets?.let { insets ->
                        val leftEdge = Rect(0, 0, 50, window.decorView.height)
                        val rightEdge = Rect(window.decorView.width - 50, 0, window.decorView.width, window.decorView.height)
                        val bottomEdge = Rect(0, window.decorView.height - 50, window.decorView.width, window.decorView.height)
                        
                        window.decorView.systemGestureExclusionRects = listOf(leftEdge, rightEdge, bottomEdge)
                    }
                } else {
                    // Use the deprecated API for Android 10
                    @Suppress("DEPRECATION")
                    val gestureInsets = window.decorView.rootWindowInsets?.systemGestureInsets
                    if (gestureInsets != null) {
                        val leftEdge = Rect(0, 0, 50, window.decorView.height)
                        val rightEdge = Rect(window.decorView.width - 50, 0, window.decorView.width, window.decorView.height)
                        val bottomEdge = Rect(0, window.decorView.height - 50, window.decorView.width, window.decorView.height)
                        
                        window.decorView.systemGestureExclusionRects = listOf(leftEdge, rightEdge, bottomEdge)
                    }
                }
            }
        }
        
        // Add an on back pressed callback to handle back button/gesture
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            onBackPressedDispatcher.addCallback(this, object : androidx.activity.OnBackPressedCallback(true) {
                override fun handleOnBackPressed() {
                    // If we're playing the game, handle it as a pause action instead of exiting
                    if (gameView.visibility == View.VISIBLE && !gameView.isPaused && !gameView.isGameOver()) {
                        gameView.pause()
                        gameMusic.pause()
                        showPauseMenu()
                        binding.pauseStartButton.visibility = View.GONE
                        binding.resumeButton.visibility = View.VISIBLE
                    } else if (binding.pauseContainer.visibility == View.VISIBLE) {
                        // If pause menu is showing, handle as a resume
                        resumeGame()
                    } else if (binding.customizationContainer.visibility == View.VISIBLE) {
                        // If customization menu is showing, hide it
                        hideCustomizationMenu()
                    } else if (binding.gameOverContainer.visibility == View.VISIBLE) {
                        // If game over is showing, go back to title
                        hideGameOver()
                        showTitleScreen()
                    } else if (titleScreen.visibility == View.VISIBLE) {
                        // If title screen is showing, allow normal back behavior (exit app)
                        isEnabled = false
                        onBackPressedDispatcher.onBackPressed()
                    }
                }
            })
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // For Android 11 (R) to Android 12 (S), use the WindowInsetsController to disable gestures
            window.insetsController?.systemBarsBehavior = 
                android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
        }
    }
    
    /**
     * GamepadConnectionListener implementation
     */
    override fun onGamepadConnected(gamepadName: String) {
        runOnUiThread {
            Toast.makeText(this, "Gamepad connected: $gamepadName", Toast.LENGTH_SHORT).show()
            // Set gamepad connected state in haptics
            gameHaptics.setGamepadConnected(true)
            // Provide haptic feedback for gamepad connection
            gameHaptics.vibrateForPieceLock()
            
            // Show gamepad help if not shown before
            if (!hasSeenGamepadHelp()) {
                showGamepadHelpDialog()
            }
        }
    }
    
    override fun onGamepadDisconnected(gamepadName: String) {
        runOnUiThread {
            Toast.makeText(this, "Gamepad disconnected: $gamepadName", Toast.LENGTH_SHORT).show()
            // Set gamepad disconnected state in haptics
            gameHaptics.setGamepadConnected(false)
        }
    }
    
    /**
     * Show gamepad help dialog
     */
    private fun showGamepadHelpDialog() {
        val dialogView = layoutInflater.inflate(R.layout.gamepad_help_dialog, null)
        val dialog = android.app.AlertDialog.Builder(this, android.R.style.Theme_DeviceDefault_Dialog_NoActionBar)
            .setView(dialogView)
            .setCancelable(true)
            .create()
        
        // Set up dismiss button
        dialogView.findViewById<View>(R.id.gamepad_help_dismiss_button).setOnClickListener {
            dialog.dismiss()
            markGamepadHelpSeen()
        }
        
        dialog.show()
    }
    
    /**
     * Check if user has seen the gamepad help
     */
    private fun hasSeenGamepadHelp(): Boolean {
        val prefs = getSharedPreferences("com.com.pixelmintgames.pixelmintdrop.preferences", Context.MODE_PRIVATE)
        return prefs.getBoolean("has_seen_gamepad_help", false)
    }
    
    /**
     * Mark that user has seen the gamepad help
     */
    private fun markGamepadHelpSeen() {
        val prefs = getSharedPreferences("com.com.pixelmintgames.pixelmintdrop.preferences", Context.MODE_PRIVATE)
        prefs.edit().putBoolean("has_seen_gamepad_help", true).apply()
    }
    
    /**
     * Check for connected/disconnected gamepads
     */
    private fun checkGamepadConnections() {
        val currentGamepads = GamepadController.getConnectedGamepadsInfo().toSet()
        
        // Find newly connected gamepads
        currentGamepads.filter { it !in connectedGamepads }.forEach { gamepadName ->
            onGamepadConnected(gamepadName)
        }
        
        // Find disconnected gamepads
        connectedGamepads.filter { it !in currentGamepads }.forEach { gamepadName ->
            onGamepadDisconnected(gamepadName)
        }
        
        // Update the stored list of connected gamepads
        connectedGamepads.clear()
        connectedGamepads.addAll(currentGamepads)
    }

    /**
     * Handle key events for both device controls and gamepads
     */
    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (event == null) return super.onKeyDown(keyCode, event)
        
        // First check if it's a gamepad input
        if (GamepadController.isGamepad(event.device)) {
            // Handle title screen start with gamepad
            if (titleScreen.visibility == View.VISIBLE && 
                (keyCode == KeyEvent.KEYCODE_BUTTON_A || keyCode == KeyEvent.KEYCODE_BUTTON_START)) {
                titleScreen.performClick()
                return true
            }
            
            // If gamepad input was handled by the controller, consume the event
            if (gamepadController.handleKeyEvent(keyCode, event)) {
                return true
            }
        }
        
        // If not handled as gamepad, handle as regular key event
        // Handle back button
        if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_BUTTON_B) {
            // Handle back button press as a pause action during gameplay
            if (gameView.visibility == View.VISIBLE && !gameView.isPaused && !gameView.isGameOver()) {
                gameView.pause()
                gameMusic.pause()
                showPauseMenu()
                binding.pauseStartButton.visibility = View.GONE
                binding.resumeButton.visibility = View.VISIBLE
                return true // Consume the event
            } else if (binding.pauseContainer.visibility == View.VISIBLE) {
                // If pause menu is showing, handle as a resume
                resumeGame()
                return true // Consume the event
            } else if (binding.customizationContainer.visibility == View.VISIBLE) {
                // If customization menu is showing, hide it
                hideCustomizationMenu()
                return true // Consume the event
            } else if (binding.gameOverContainer.visibility == View.VISIBLE) {
                // If game over is showing, go back to title
                hideGameOver()
                showTitleScreen()
                return true // Consume the event
            }
        }
        
        return super.onKeyDown(keyCode, event)
    }

    /**
     * Handle motion events for gamepad analog sticks
     */
    override fun onGenericMotionEvent(event: MotionEvent): Boolean {
        // Check if it's a gamepad motion event (analog sticks)
        if ((event.source and InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK) {
            if (gamepadController.handleMotionEvent(event)) {
                return true
            }
        }
        
        return super.onGenericMotionEvent(event)
    }

    private fun showProgressionScreen(xpGained: Long, newRewards: List<String>, isNewHighScore: Boolean, finalScore: Int) {
        // Apply theme before showing the screen
        progressionScreen.applyTheme(currentTheme)
        
        // Hide game/other UI elements
        binding.gameControlsContainer.visibility = View.GONE
        binding.holdPieceView.visibility = View.GONE
        binding.nextPieceView.visibility = View.GONE
        binding.pauseButton.visibility = View.GONE
        
        // Hide landscape panels if they exist
        binding.leftControlsPanel?.visibility = View.GONE
        binding.rightControlsPanel?.visibility = View.GONE
        
        // Show the progression screen
        binding.gameOverContainer.visibility = View.GONE
        progressionScreen.visibility = View.VISIBLE
        
        // Display progression data
        progressionScreen.showProgress(progressionManager, xpGained, newRewards, currentTheme)
        
        // Set up the continue action
        progressionScreen.onContinue = {
            if (isNewHighScore) {
                showHighScoreEntry(finalScore)
            } else {
                // No high score, just show the final game over screen
                showGameOverScreenDirectly(finalScore)
            }
        }
    }

    /**
     * Implements GamepadMenuListener to handle start button press
     */
    override fun onPauseRequested() {
        runOnUiThread {
            if (binding.customizationContainer.visibility == View.VISIBLE) {
                // If customization menu is showing, hide it
                hideCustomizationMenu()
            } else if (gameView.visibility == View.VISIBLE && !gameView.isPaused && !gameView.isGameOver()) {
                gameView.pause()
                gameMusic.pause()
                showPauseMenu()
                binding.pauseStartButton.visibility = View.GONE
                binding.resumeButton.visibility = View.VISIBLE
            } else if (binding.pauseContainer.visibility == View.VISIBLE) {
                // If pause menu is showing, handle as a resume
                hidePauseMenu()
                resumeGame()
            } else if (titleScreen.visibility == View.VISIBLE) {
                // If title screen is showing, start the game
                titleScreen.performClick()
            }
        }
    }

    /**
     * Implements GamepadNavigationListener to handle menu navigation
     */
    override fun onMenuUp() {
        runOnUiThread {
            if (binding.pauseContainer.visibility == View.VISIBLE) {
                moveMenuSelectionUp()
                scrollToSelectedItem()
            } else if (binding.customizationContainer.visibility == View.VISIBLE) {
                moveCustomizationMenuSelectionUp()
                scrollToSelectedCustomizationItem()
            }
        }
    }
    
    override fun onMenuDown() {
        runOnUiThread {
            if (binding.pauseContainer.visibility == View.VISIBLE) {
                moveMenuSelectionDown()
                scrollToSelectedItem()
            } else if (binding.customizationContainer.visibility == View.VISIBLE) {
                moveCustomizationMenuSelectionDown()
                scrollToSelectedCustomizationItem()
            }
        }
    }
    
    override fun onMenuLeft() {
        runOnUiThread {
            if (binding.pauseContainer.visibility == View.VISIBLE && pauseMenuItems.isNotEmpty()) {
                val selectedItem = pauseMenuItems.getOrNull(currentMenuSelection)
                when (selectedItem) {
                    is ThemeSelector -> selectedItem.focusPreviousItem()
                    is BlockSkinSelector -> selectedItem.focusPreviousItem()
                }
            } else if (binding.customizationContainer.visibility == View.VISIBLE && customizationMenuItems.isNotEmpty()) {
                val selectedItem = customizationMenuItems.getOrNull(currentCustomizationMenuSelection)
                when (selectedItem) {
                    is ThemeSelector -> selectedItem.focusPreviousItem()
                    is BlockSkinSelector -> selectedItem.focusPreviousItem()
                }
            }
        }
    }
    
    override fun onMenuRight() {
        runOnUiThread {
            if (binding.pauseContainer.visibility == View.VISIBLE && pauseMenuItems.isNotEmpty()) {
                val selectedItem = pauseMenuItems.getOrNull(currentMenuSelection)
                when (selectedItem) {
                    is ThemeSelector -> selectedItem.focusNextItem()
                    is BlockSkinSelector -> selectedItem.focusNextItem()
                }
            } else if (binding.customizationContainer.visibility == View.VISIBLE && customizationMenuItems.isNotEmpty()) {
                val selectedItem = customizationMenuItems.getOrNull(currentCustomizationMenuSelection)
                when (selectedItem) {
                    is ThemeSelector -> selectedItem.focusNextItem()
                    is BlockSkinSelector -> selectedItem.focusNextItem()
                }
            }
        }
    }
    
    override fun onMenuSelect() {
        runOnUiThread {
            if (binding.pauseContainer.visibility == View.VISIBLE && pauseMenuItems.isNotEmpty()) {
                activateSelectedMenuItem()
            } else if (binding.customizationContainer.visibility == View.VISIBLE && customizationMenuItems.isNotEmpty()) {
                activateSelectedCustomizationMenuItem()
            } else if (titleScreen.visibility == View.VISIBLE) {
                titleScreen.performClick()
            } else if (progressionScreen.visibility == View.VISIBLE) {
                progressionScreen.performContinue()
            } else if (binding.gameOverContainer.visibility == View.VISIBLE) {
                binding.playAgainButton.performClick()
            }
        }
    }

    /**
     * Initialize pause menu items for gamepad navigation
     */
    private fun initPauseMenuNavigation() {
        pauseMenuItems.clear()
        
        // Check landscape mode only to select the *correct instance* of the view
        val isLandscape = resources.configuration.orientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE
        
        // Define the unified order (Portrait Order)
        val orderedViews = mutableListOf<View?>()

        // Group 1: Game control buttons (Resume/Start New Game, Restart)
        if (binding.resumeButton.visibility == View.VISIBLE) {
            orderedViews.add(binding.resumeButton)
        }
        if (binding.pauseStartButton.visibility == View.VISIBLE) {
            orderedViews.add(binding.pauseStartButton)
        }
        orderedViews.add(binding.pauseRestartButton)

        // Group 2: Stats and Scoring
        orderedViews.add(binding.highScoresButton)
        orderedViews.add(binding.leaderboardButton)
        orderedViews.add(binding.statsButton)
        
        // Group 3: Level selection (use safe calls)
        orderedViews.add(binding.pauseLevelUpButton)
        orderedViews.add(binding.pauseLevelDownButton)

        // Group 4: Sound and Music controls (Moved UP) - Use safe calls
        orderedViews.add(binding.settingsButton)  // Sound toggle (Button)
        orderedViews.add(binding.musicToggle)     // Music toggle (ImageButton)

        // Group 5: Customization Menu
        orderedViews.add(binding.customizationButton)  // Add the customization button

        // Add all non-null, visible items from the defined order to the final navigation list
        pauseMenuItems.addAll(orderedViews.filterNotNull().filter { it.visibility == View.VISIBLE })
    }
    
    /**
     * Highlight the currently selected menu item
     */
    private fun highlightMenuItem(index: Int) {
        // Ensure index is valid
        if (pauseMenuItems.isEmpty() || index < 0 || index >= pauseMenuItems.size) {
            Log.w(TAG, "highlightMenuItem called with invalid index: $index or empty items")
            return
        }
        
        val themeColor = getThemeColor(currentTheme)
        val highlightBorderColor = themeColor // Use theme color for the main highlight border
        
        pauseMenuItems.forEachIndexed { i, item ->
            val isSelected = (i == index)
            
            // Reset common properties
            item.alpha = if (isSelected) 1.0f else 0.7f
            if (item is Button || item is ImageButton) {
                item.scaleX = 1.0f
                item.scaleY = 1.0f
            }
            // Reset
             when (item) {
                 is Button -> item.background = ColorDrawable(Color.TRANSPARENT)
                 is ImageButton -> item.background = null // Let default background handle non-selected
                 is ThemeSelector -> {
                     item.background = ColorDrawable(Color.TRANSPARENT)
                     item.setHasFocus(false) // Explicitly remove component focus
                 }
                 is BlockSkinSelector -> {
                     item.background = ColorDrawable(Color.TRANSPARENT)
                     item.setHasFocus(false) // Explicitly remove component focus
                 }
             }
            
            // Apply highlight to the selected item
            if (isSelected) {
                // Apply scaling to buttons
                if (item is Button || item is ImageButton) {
                    item.scaleX = 1.1f
                    item.scaleY = 1.1f
                }
                
                // Add border/background based on type
                val borderWidth = 4 // Unified border width for highlight
                val cornerRadius = 12f
                
                when (item) {
                    is Button -> {
                        // Attempt to use a themed drawable, fallback to simple border
                         ContextCompat.getDrawable(this, R.drawable.menu_item_selected)?.mutate()?.let {
                             if (it is GradientDrawable) {
                                 it.setStroke(borderWidth, highlightBorderColor)
                                 item.background = it
                             } else {
                                 // Fallback for non-gradient drawable (e.g., tinting)
                                 it.setTint(highlightBorderColor)
                                 item.background = it
                             }
                         } ?: run {
                             // Fallback to simple border if drawable not found
                             var gradientDrawable = GradientDrawable().apply {
                                 setColor(Color.TRANSPARENT)
                                 setStroke(borderWidth, highlightBorderColor)
                                 setCornerRadius(cornerRadius)
                             }
                             item.background = gradientDrawable
                         }
                    }
                    is ImageButton -> {
                        // Similar handling for ImageButton
                        ContextCompat.getDrawable(this, R.drawable.menu_item_selected)?.mutate()?.let {
                            if (it is GradientDrawable) {
                                it.setStroke(borderWidth, highlightBorderColor)
                                item.background = it
                            } else {
                                it.setTint(highlightBorderColor)
                                item.background = it
                            }
                        } ?: run {
                            var gradientDrawable = GradientDrawable().apply {
                                setColor(Color.TRANSPARENT)
                                setStroke(borderWidth, highlightBorderColor)
                                setCornerRadius(cornerRadius)
                            }
                            item.background = gradientDrawable
                        }
                    }
                }
            }
        }
        
        // Provide haptic feedback for selection change
        gameHaptics.vibrateForPieceMove()
        
        // Ensure the selected item is visible
        scrollToSelectedItem()
    }
    
    /**
     * Move menu selection up
     */
    private fun moveMenuSelectionUp() {
        if (pauseMenuItems.isEmpty()) return
        
        // Calculate new selection index with wrapping
        val previousSelection = currentMenuSelection
        currentMenuSelection = (currentMenuSelection - 1)
        
        // Prevent wrapping from bottom to top for more intuitive navigation
        if (currentMenuSelection < 0) {
            currentMenuSelection = 0
            return  // Already at top, don't provide feedback
        }
        
        // Only provide feedback if selection actually changed
        if (previousSelection != currentMenuSelection) {
            highlightMenuItem(currentMenuSelection)
        }
    }
    
    /**
     * Move menu selection down
     */
    private fun moveMenuSelectionDown() {
        if (pauseMenuItems.isEmpty()) return
        
        // Calculate new selection index with wrapping
        val previousSelection = currentMenuSelection
        currentMenuSelection = (currentMenuSelection + 1)
        
        // Prevent wrapping from bottom to top for more intuitive navigation
        if (currentMenuSelection >= pauseMenuItems.size) {
            currentMenuSelection = pauseMenuItems.size - 1
            return  // Already at bottom, don't provide feedback
        }
        
        // Only provide feedback if selection actually changed
        if (previousSelection != currentMenuSelection) {
            highlightMenuItem(currentMenuSelection)
        }
    }

    /**
     * Scroll the selected menu item into view
     */
    private fun scrollToSelectedItem() {
        if (pauseMenuItems.isEmpty() || currentMenuSelection < 0 || currentMenuSelection >= pauseMenuItems.size) return
        
        val selectedItem = pauseMenuItems[currentMenuSelection]
        
        // Determine which scroll view to use based on orientation
        val isLandscape = resources.configuration.orientation == android.content.res.Configuration.ORIENTATION_LANDSCAPE
        val scrollView = if (isLandscape) {
            findLandscapeScrollView()
        } else {
            binding.pauseMenuScrollView
        } ?: return
        
        // Delay the scrolling slightly to ensure measurements are correct
        scrollView.post {
            try {
                // Calculate item's position in the ScrollView's coordinate system
                val scrollBounds = Rect()
                scrollView.getHitRect(scrollBounds)
                
                // Get item's location on screen
                val itemLocation = IntArray(2)
                selectedItem.getLocationOnScreen(itemLocation)
                
                // Get ScrollView's location on screen
                val scrollLocation = IntArray(2)
                scrollView.getLocationOnScreen(scrollLocation)
                
                // Calculate relative position
                val itemY = itemLocation[1] - scrollLocation[1]
                
                // Get the top and bottom of the item relative to the ScrollView
                val itemTop = itemY
                val itemBottom = itemY + selectedItem.height
                
                // Get the visible height of the ScrollView
                val visibleHeight = scrollView.height
                
                // Add padding for better visibility
                val padding = 50
                
                // Calculate the scroll target position
                val scrollY = scrollView.scrollY
                
                // If item is above visible area
                if (itemTop < padding) {
                    scrollView.smoothScrollTo(0, scrollY + (itemTop - padding))
                }
                // If item is below visible area
                else if (itemBottom > visibleHeight - padding) {
                    scrollView.smoothScrollTo(0, scrollY + (itemBottom - visibleHeight + padding))
                }
            } catch (e: Exception) {
                // Handle any exceptions that might occur during scrolling
                Log.e(TAG, "Error scrolling to selected item", e)
            }
        }
    }
    
    /**
     * Activate the currently selected menu item
     */
    private fun activateSelectedMenuItem() {
        if (pauseMenuItems.isEmpty() || currentMenuSelection < 0 || currentMenuSelection >= pauseMenuItems.size) return
        
        val selectedItem = pauseMenuItems[currentMenuSelection]
        
        // Vibrate regardless of item type for consistent feedback
        gameHaptics.vibrateForPieceLock() 
        
        when (selectedItem) {
            is ThemeSelector -> {
                // Confirm the internally focused theme
                selectedItem.confirmSelection()
                // Applying the theme might change colors, so refresh the pause menu display
                // Need to delay slightly to allow theme application to potentially finish
                Handler(Looper.getMainLooper()).postDelayed({ showPauseMenu() }, 100) 
            }
            is BlockSkinSelector -> {
                // Confirm the internally focused block skin
                selectedItem.confirmSelection()
                // Skin change doesn't affect menu colors, no refresh needed here
            }
            else -> {
                // Handle other menu items with a standard click
                selectedItem.performClick()
            }
        }
    }

    /**
     * Find any ScrollView in the pause container for landscape mode
     */
    private fun findLandscapeScrollView(): ScrollView? {
        // First try to find a ScrollView directly in the landscape layout
        val pauseContainer = findViewById<View>(R.id.pauseContainer) ?: return null
        
        // Try to find any ScrollView in the pause container
        if (pauseContainer is android.view.ViewGroup) {
            // Search for ScrollView in the container
            fun findScrollView(view: android.view.View): ScrollView? {
                if (view is ScrollView && view.visibility == View.VISIBLE) {
                    return view
                } else if (view is android.view.ViewGroup) {
                    for (i in 0 until view.childCount) {
                        val child = view.getChildAt(i)
                        val scrollView = findScrollView(child)
                        if (scrollView != null) {
                            return scrollView
                        }
                    }
                }
                return null
            }
            
            // Try to find ScrollView in the container 
            val scrollView = findScrollView(pauseContainer)
            if (scrollView != null && scrollView != binding.pauseMenuScrollView) {
                return scrollView
            }
        }
        
        // If no landscape ScrollView is found, fall back to the default one
        return binding.pauseMenuScrollView
    }

    // Add these new methods for customization menu navigation
    private fun moveCustomizationMenuSelectionUp() {
        if (customizationMenuItems.isEmpty()) return
        
        val previousSelection = currentCustomizationMenuSelection
        currentCustomizationMenuSelection = (currentCustomizationMenuSelection - 1)
        
        if (currentCustomizationMenuSelection < 0) {
            currentCustomizationMenuSelection = 0
            return
        }
        
        if (previousSelection != currentCustomizationMenuSelection) {
            highlightCustomizationMenuItem(currentCustomizationMenuSelection)
        }
    }
    
    private fun moveCustomizationMenuSelectionDown() {
        if (customizationMenuItems.isEmpty()) return
        
        val previousSelection = currentCustomizationMenuSelection
        currentCustomizationMenuSelection = (currentCustomizationMenuSelection + 1)
        
        if (currentCustomizationMenuSelection >= customizationMenuItems.size) {
            currentCustomizationMenuSelection = customizationMenuItems.size - 1
            return
        }
        
        if (previousSelection != currentCustomizationMenuSelection) {
            highlightCustomizationMenuItem(currentCustomizationMenuSelection)
        }
    }

    private fun highlightCustomizationMenuItem(index: Int) {
        if (customizationMenuItems.isEmpty() || index < 0 || index >= customizationMenuItems.size) {
            Log.w(TAG, "highlightCustomizationMenuItem called with invalid index: $index or empty items")
            return
        }
        
        val themeColor = getThemeColor(currentTheme)
        val highlightBorderColor = themeColor
        val borderWidth = 4 // Define border width for highlight
        val cornerRadius = 12f
        
        customizationMenuItems.forEachIndexed { i, item ->
            val isSelected = (i == index)
            
            item.alpha = if (isSelected) 1.0f else 0.7f
            if (item is Button || item is ImageButton) {
                item.scaleX = 1.0f
                item.scaleY = 1.0f
            }
            
            when (item) {
                is Button -> item.background = ColorDrawable(Color.TRANSPARENT)
                is ImageButton -> item.background = null
                is ThemeSelector -> {
                    item.background = ColorDrawable(Color.TRANSPARENT)
                    item.setHasFocus(false)
                }
                is BlockSkinSelector -> {
                    item.background = ColorDrawable(Color.TRANSPARENT)
                    item.setHasFocus(false)
                }
                is Switch -> {
                    item.background = ColorDrawable(Color.TRANSPARENT)
                }
            }
            
            if (isSelected) {
                when (item) {
                    is Button -> {
                        var gradientDrawable = GradientDrawable().apply {
                            setColor(Color.TRANSPARENT)
                            setStroke(borderWidth, highlightBorderColor)
                            setCornerRadius(cornerRadius)
                        }
                        item.background = gradientDrawable
                    }
                    is ImageButton -> {
                        var gradientDrawable = GradientDrawable().apply {
                            setColor(Color.TRANSPARENT)
                            setStroke(borderWidth, highlightBorderColor)
                            setCornerRadius(cornerRadius)
                        }
                        item.background = gradientDrawable
                    }
                    is ThemeSelector -> {
                        var gradientDrawable = GradientDrawable().apply {
                            setColor(Color.TRANSPARENT)
                            setStroke(borderWidth, highlightBorderColor)
                            setCornerRadius(cornerRadius)
                        }
                        item.background = gradientDrawable
                        item.setHasFocus(true)
                    }
                    is BlockSkinSelector -> {
                        var gradientDrawable = GradientDrawable().apply {
                            setColor(Color.TRANSPARENT)
                            setStroke(borderWidth, highlightBorderColor)
                            setCornerRadius(cornerRadius)
                        }
                        item.background = gradientDrawable
                        item.setHasFocus(true)
                    }
                    is Switch -> {
                        var gradientDrawable = GradientDrawable().apply {
                            setColor(Color.TRANSPARENT)
                            setStroke(borderWidth, highlightBorderColor)
                            setCornerRadius(cornerRadius)
                        }
                        item.background = gradientDrawable
                    }
                }
            }
        }
        
        gameHaptics.vibrateForPieceMove()
        scrollToSelectedCustomizationItem()
    }

    private fun scrollToSelectedCustomizationItem() {
        if (customizationMenuItems.isEmpty() || currentCustomizationMenuSelection < 0 || currentCustomizationMenuSelection >= customizationMenuItems.size) return
        
        val selectedItem = customizationMenuItems[currentCustomizationMenuSelection]
        val scrollView = binding.customizationMenuScrollView
        
        scrollView.post {
            try {
                val scrollBounds = Rect()
                scrollView.getHitRect(scrollBounds)
                
                val itemLocation = IntArray(2)
                selectedItem.getLocationOnScreen(itemLocation)
                
                val scrollLocation = IntArray(2)
                scrollView.getLocationOnScreen(scrollLocation)
                
                val itemY = itemLocation[1] - scrollLocation[1]
                val itemTop = itemY
                val itemBottom = itemY + selectedItem.height
                val visibleHeight = scrollView.height
                val padding = 50
                val scrollY = scrollView.scrollY
                
                if (itemTop < padding) {
                    scrollView.smoothScrollTo(0, scrollY + (itemTop - padding))
                } else if (itemBottom > visibleHeight - padding) {
                    scrollView.smoothScrollTo(0, scrollY + (itemBottom - visibleHeight + padding))
                }
            } catch (e: Exception) {
                Log.e(TAG, "Error scrolling to selected customization item", e)
            }
        }
    }

    private fun activateSelectedCustomizationMenuItem() {
        if (customizationMenuItems.isEmpty() || currentCustomizationMenuSelection < 0 || currentCustomizationMenuSelection >= customizationMenuItems.size) return
        
        val selectedItem = customizationMenuItems[currentCustomizationMenuSelection]
        gameHaptics.vibrateForPieceLock()
        
        when (selectedItem) {
            is ThemeSelector -> {
                selectedItem.confirmSelection()
                Handler(Looper.getMainLooper()).postDelayed({ showCustomizationMenu() }, 100)
            }
            is BlockSkinSelector -> {
                selectedItem.confirmSelection()
                // The onBlockSkinSelected callback will handle updating the game view and saving the selection
            }
            is Switch -> {
                if (selectedItem.isEnabled) {
                    selectedItem.isChecked = !selectedItem.isChecked
                }
            }
            else -> {
                selectedItem.performClick()
            }
        }
    }

    private fun updateGameStateUI(score: Int, level: Int, lines: Int) {
        viewModel.setScore(score.toLong()) // Use ViewModel setter
        viewModel.setLevel(level) // Use ViewModel setter
        
        // Update other UI elements not handled by score/level observers
        binding.linesText.text = "$lines"
        binding.comboText.text = gameBoard.getCombo().toString()
        
        // If random mode is enabled, check if we should change theme or block skin
        if (viewModel.isRandomModeEnabled.value == true) {
            // Get the current 10-line group (0 for 0-9, 1 for 10-19, etc.)
            val currentLinesGroup = lines / 10
            
            // Determine if we should change themes and skins:
            // 1. If we've moved to a new 10-line group
            // 2. If we've leveled up to a level we haven't applied random to yet
            val lineGroupChanged = lines > 0 && currentLinesGroup > lastLinesGroup
            val levelIncreased = level > 1 && level > lastRandomLevel
            
            if (lineGroupChanged || levelIncreased) {
                Log.d("RandomMode", "Triggering change - Lines: $lines (group $currentLinesGroup, was $lastLinesGroup), Level: $level (was $lastRandomLevel)")
                applyRandomThemeAndBlockSkin()
                
                // Update tracking variables
                lastLinesGroup = currentLinesGroup
                lastRandomLevel = level
            }
        }
        
        // Update last lines count
        lastLines = lines
    }
    
    private fun applyRandomThemeAndBlockSkin() {
        val unlockedThemes = progressionManager.getUnlockedThemes().toList()
        val unlockedBlocks = progressionManager.getUnlockedBlocks().toList()
        
        // Log available options
        Log.d("RandomMode", "Available themes: ${unlockedThemes.joinToString()}")
        Log.d("RandomMode", "Available blocks: ${unlockedBlocks.joinToString()}")
        
        // Get current block skin for debugging
        val currentBlockSkin = gameView.getCurrentBlockSkin()
        Log.d("RandomMode", "Current block skin before change: $currentBlockSkin")
        
        // Only proceed if there are unlocked themes and blocks
        if (unlockedThemes.isNotEmpty() && unlockedBlocks.isNotEmpty()) {
            // Apply random theme from unlocked themes - make sure not to pick the current theme
            val availableThemes = unlockedThemes.filter { it != currentTheme }
            val randomTheme = if (availableThemes.isNotEmpty()) {
                availableThemes.random()
            } else {
                unlockedThemes.random()
            }
            
            // Apply random block skin from unlocked block skins - make sure not to pick the current skin
            val availableBlocks = unlockedBlocks.filter { it != currentBlockSkin }
            val randomBlock = if (availableBlocks.isNotEmpty()) {
                availableBlocks.random()
            } else {
                unlockedBlocks.random()
            }
            
            Log.d("RandomMode", "Applying random theme: $randomTheme and block skin: $randomBlock")
            
            // Apply the theme
            currentTheme = randomTheme
            applyTheme(randomTheme)
            
            // Force update the block skin with a specific call - with intentional delay
            handler.post {
                Log.d("RandomMode", "Setting block skin to: $randomBlock")
                gameView.setBlockSkin(randomBlock)
                progressionManager.setSelectedBlockSkin(randomBlock)
                
                // Get current block skin after change for debugging
                val newBlockSkin = gameView.getCurrentBlockSkin()
                Log.d("RandomMode", "Block skin after change: $newBlockSkin")
                
                // Update the UI to reflect the changes
                themeSelector.updateThemes(progressionManager.getUnlockedThemes(), currentTheme)
                blockSkinSelector.updateBlockSkins(
                    progressionManager.getUnlockedBlocks(),
                    randomBlock,
                    progressionManager.getPlayerLevel()
                )
                
                // Add a vibration to indicate the change to the player
                gameHaptics.vibrateForPieceLock()
            }
        } else {
            Log.d("RandomMode", "Cannot apply random theme/skin - no unlocked options available")
        }
    }
    
    /**
     * Handles sign-in to Google Play Games Services
     */
    private fun signInToPlayGames() {
        gamesSignInClient.isAuthenticated.addOnCompleteListener { task ->
            val isAuthenticated = task.isSuccessful && task.result.isAuthenticated
            
            if (!isAuthenticated) {
                // Silent sign-in failed, offer to sign in explicitly
                Log.d(TAG, "Not authenticated with Play Games, will prompt user later")
                
                // We don't show UI for this immediately, we'll add a button to the pause menu
            } else {
                Log.d(TAG, "Already authenticated with Play Games")
                
                // If we were already authenticated, make sure scores are synced
                val lastHighScore = highScoreManager.getHighScores().maxByOrNull { it.score }
                lastHighScore?.let {
                    highScoreManager.getGooglePlayGamesManager().submitScore(it.score.toLong(), this)
                }
            }
        }
    }
    
    // Method to show Google Play Games leaderboard
    private fun showLeaderboard() {
        // New logic: Try silent sign-in first, then interactive if needed.
        Log.d(TAG, "Attempting silent sign-in before showing leaderboard...")
        // Use googleSignInClient for silentSignIn
        googleSignInClient.silentSignIn().addOnCompleteListener { silentSignInTask ->
            if (silentSignInTask.isSuccessful) {
                // Silent sign-in successful OR user already signed in.
                Log.d(TAG, "Silent sign-in successful/already signed in. Getting leaderboard intent.")
                getAndShowLeaderboardIntent()
            } else {
                // Silent sign-in failed. Need explicit sign-in.
                Log.w(TAG, "Silent sign-in failed. Attempting interactive sign-in.", silentSignInTask.exception)
                // Use gamesSignInClient for interactive signIn
                gamesSignInClient.signIn().addOnCompleteListener { interactiveSignInTask ->
                    if (interactiveSignInTask.isSuccessful) {
                        // Interactive sign-in successful
                        Log.d(TAG, "Interactive sign-in successful. Getting leaderboard intent.")
                        getAndShowLeaderboardIntent()
                    } else {
                        // Interactive sign-in failed
                        Log.e(TAG, "Interactive sign-in failed.", interactiveSignInTask.exception)
                        Toast.makeText(this, "Sign-in failed. Please try again.", Toast.LENGTH_SHORT).show()
                    }
                }
            }
        }
    }
    
    // Helper function to get the intent from GooglePlayGamesManager and show it
    private fun getAndShowLeaderboardIntent() {
        highScoreManager.getGooglePlayGamesManager().showLeaderboard(this, 
            object : GooglePlayGamesManager.LeaderboardIntentListener {
                override fun onLeaderboardIntentSuccess(intent: Intent) {
                    Log.d(TAG, "Received leaderboard intent, starting activity for result.")
                    try {
                        startActivityForResult(intent, RC_LEADERBOARD_UI)
                    } catch (e: Exception) {
                        Log.e(TAG, "Failed to start leaderboard activity for result", e)
                        Toast.makeText(this@MainActivity, "Could not display leaderboard.", Toast.LENGTH_SHORT).show()
                    }
                }

                override fun onLeaderboardIntentFailure(exception: Exception) {
                    Log.e(TAG, "Failed to get leaderboard intent.", exception)
                    Toast.makeText(this@MainActivity, "Could not display leaderboard.", Toast.LENGTH_SHORT).show()
                }
            })
    }
} 