package com.pixelmintdrop.ui

import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.GridLayout
import android.widget.TextView
import androidx.cardview.widget.CardView
import com.pixelmintdrop.R
import android.graphics.drawable.GradientDrawable

/**
 * UI component for selecting block skins
 */
class BlockSkinSelector @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    private val skinsGrid: GridLayout
    private val availableSkinsLabel: TextView
    
    // Callback when a block skin is selected
    var onBlockSkinSelected: ((String) -> Unit)? = null
    
    // Currently selected block skin (persisted)
    private var selectedSkin: String = "block_skin_1"
    
    // Block skin cards map (skinId -> CardView)
    private val skinCards = mutableMapOf<String, CardView>()
    // Ordered list of skin IDs for navigation
    private val skinIdList = mutableListOf<String>()
    // Currently focused skin ID (for gamepad navigation within the selector)
    private var focusedSkinId: String? = null
    // Index of the currently focused skin in skinIdList
    private var focusedIndex: Int = -1
    // Flag indicating if the entire selector component has focus from the main menu
    private var hasComponentFocus: Boolean = false
    
    // Player level for determining what should be unlocked
    private var playerLevel: Int = 1
    
    init {
        // Inflate the layout
        LayoutInflater.from(context).inflate(R.layout.block_skin_selector, this, true)
        
        // Get references to views
        skinsGrid = findViewById(R.id.skins_grid)
        availableSkinsLabel = findViewById(R.id.available_skins_label)
    }
    
    /**
     * Update the block skin selector with unlocked skins
     */
    fun updateBlockSkins(unlockedSkins: Set<String>, currentSkin: String, playerLevel: Int = 1) {
        // Store player level
        this.playerLevel = playerLevel
        
        // Clear existing skin cards and ID list
        skinsGrid.removeAllViews()
        skinCards.clear()
        skinIdList.clear()
        
        // Update selected skin and initial focus
        selectedSkin = currentSkin
        focusedSkinId = currentSkin
        focusedIndex = -1 // Reset index
        
        // Get all possible skins and their details, sorted for consistent order
        val allSkins = getBlockSkins().entries.sortedWith(compareBy({ it.value.unlockLevel }, { it.value.displayName })).associate { it.key to it.value }
        
        // Add skin cards to the grid and build ID list
        allSkins.forEach { (skinId, skinInfo) ->
            val isEffectivelyUnlocked = unlockedSkins.contains(skinId) || playerLevel >= skinInfo.unlockLevel
            val isSelected = skinId == selectedSkin
            
            // Only add unlocked skins to the navigable list
             if (isEffectivelyUnlocked) {
                 skinIdList.add(skinId)
             }

            val skinCard = createBlockSkinCard(skinId, skinInfo, isEffectivelyUnlocked, isSelected)
            skinCards[skinId] = skinCard
            skinsGrid.addView(skinCard)

            // Update focused index if this is the currently selected/focused skin
            if (isEffectivelyUnlocked && skinId == focusedSkinId) {
                 focusedIndex = skinIdList.indexOf(skinId)
            }
        }
        
        // Ensure focus index is valid if the previously focused skin is no longer available/unlocked
        if (focusedIndex == -1 && skinIdList.isNotEmpty()) {
            focusedIndex = 0
            focusedSkinId = skinIdList[0]
        }

        // Apply initial focus highlight if the component has focus
        highlightFocusedCard()
    }
    
    /**
     * Create a card for a block skin
     */
    private fun createBlockSkinCard(
        skinId: String,
        skinInfo: BlockSkinInfo,
        isUnlocked: Boolean,
        isSelected: Boolean
    ): CardView {
        // Create the card
        val card = CardView(context).apply {
            id = View.generateViewId()
            radius = 12f
            cardElevation = if (isSelected) 8f else 2f
            useCompatPadding = true
            
            // Set card background color based on skin
            setCardBackgroundColor(skinInfo.backgroundColor)
            
            // Set card dimensions
            val cardSize = resources.getDimensionPixelSize(R.dimen.theme_card_size)
            layoutParams = GridLayout.LayoutParams().apply {
                width = cardSize
                height = cardSize
                columnSpec = GridLayout.spec(GridLayout.UNDEFINED, 1f)
                rowSpec = GridLayout.spec(GridLayout.UNDEFINED, 1f)
                setMargins(8, 8, 8, 8)
            }
            
            // Apply locked/selected state visuals (only opacity here)
            alpha = if (isUnlocked) 1.0f else 0.5f
        }
        
        // Create block skin content container
        val container = FrameLayout(context).apply {
            layoutParams = FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT
            )
        }
        
        // Create the block skin preview
        val blockSkinPreview = View(context).apply {
            layoutParams = FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT
            )
            
            // Set the background color
            setBackgroundColor(skinInfo.backgroundColor)
        }
        
        // Add a label with the skin name
        val skinLabel = TextView(context).apply {
            text = skinInfo.displayName
            setTextColor(skinInfo.textColor)
            textSize = 14f
            textAlignment = View.TEXT_ALIGNMENT_CENTER
            
            // Position at the bottom of the card
            layoutParams = FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.WRAP_CONTENT
            ).apply {
                gravity = android.view.Gravity.BOTTOM or android.view.Gravity.CENTER_HORIZONTAL
                setMargins(4, 4, 4, 8)
            }
        }
        
        // Add level requirement for locked skins
        val levelRequirement = TextView(context).apply {
            text = "Level ${skinInfo.unlockLevel}"
            setTextColor(Color.WHITE)
            textSize = 12f
            textAlignment = View.TEXT_ALIGNMENT_CENTER
            visibility = if (isUnlocked) View.GONE else View.VISIBLE
            
            // Position at the center of the card
            layoutParams = FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.WRAP_CONTENT,
                FrameLayout.LayoutParams.WRAP_CONTENT
            ).apply {
                gravity = android.view.Gravity.CENTER
            }
            // Make text bold and more visible for better readability
            typeface = android.graphics.Typeface.DEFAULT_BOLD
            setShadowLayer(3f, 1f, 1f, Color.BLACK)
        }
        
        // Add a lock icon if the skin is locked
        val lockOverlay = View(context).apply {
            layoutParams = FrameLayout.LayoutParams(
                FrameLayout.LayoutParams.MATCH_PARENT,
                FrameLayout.LayoutParams.MATCH_PARENT
            )
            
            // Add lock icon or visual indicator
            setBackgroundResource(R.drawable.lock_overlay)
            visibility = if (isUnlocked) View.GONE else View.VISIBLE
        }
        
        // Add all elements to container
        container.addView(blockSkinPreview)
        container.addView(skinLabel)
        container.addView(lockOverlay)
        container.addView(levelRequirement)
        
        // Add container to card
        card.addView(container)
        
        // Set up click listener only for unlocked skins
        if (isUnlocked) {
            card.setOnClickListener {
                // Clicking directly selects the skin
                focusedSkinId = skinId
                focusedIndex = skinIdList.indexOf(skinId)
                confirmSelection() // Directly confirm click selection
            }
        }
        
        return card
    }
    
    /**
     * Data class for block skin information
     */
    data class BlockSkinInfo(
        val displayName: String,
        val backgroundColor: Int,
        val textColor: Int,
        val unlockLevel: Int
    )
    
    /**
     * Get all available block skins with their details
     */
    private fun getBlockSkins(): Map<String, BlockSkinInfo> {
        return mapOf(
            "block_skin_1" to BlockSkinInfo(
                displayName = "Classic",
                backgroundColor = Color.BLACK,
                textColor = Color.WHITE,
                unlockLevel = 1
            ),
            "block_skin_2" to BlockSkinInfo(
                displayName = "Neon",
                backgroundColor = Color.parseColor("#0D0221"),
                textColor = Color.parseColor("#FF00FF"),
                unlockLevel = 7
            ),
            "block_skin_3" to BlockSkinInfo(
                displayName = "Retro",
                backgroundColor = Color.parseColor("#3F2832"),
                textColor = Color.parseColor("#FF5A5F"),
                unlockLevel = 14
            ),
            "block_skin_4" to BlockSkinInfo(
                displayName = "Minimalist",
                backgroundColor = Color.WHITE,
                textColor = Color.BLACK,
                unlockLevel = 21
            ),
            "block_skin_5" to BlockSkinInfo(
                displayName = "Galaxy",
                backgroundColor = Color.parseColor("#0B0C10"),
                textColor = Color.parseColor("#66FCF1"),
                unlockLevel = 28
            )
        )
    }
    
    /**
     * Sets whether the entire component has focus (from the parent menu).
     */
    fun setHasFocus(hasFocus: Boolean) {
        hasComponentFocus = hasFocus
        highlightFocusedCard() // Re-apply highlights
    }

    /**
     * Moves the internal focus to the next available skin.
     */
    fun focusNextItem() {
        if (!hasComponentFocus || skinIdList.isEmpty()) return

        focusedIndex = (focusedIndex + 1) % skinIdList.size
        focusedSkinId = skinIdList[focusedIndex]
        highlightFocusedCard()
    }

    /**
     * Moves the internal focus to the previous available skin.
     */
    fun focusPreviousItem() {
        if (!hasComponentFocus || skinIdList.isEmpty()) return

        focusedIndex = (focusedIndex - 1 + skinIdList.size) % skinIdList.size
        focusedSkinId = skinIdList[focusedIndex]
        highlightFocusedCard()
    }

    /**
     * Confirms the currently focused skin as the selected skin.
     * Triggers the onBlockSkinSelected callback.
     */
    fun confirmSelection() {
        if (focusedSkinId == null || focusedSkinId == selectedSkin) {
            return // No change needed
        }
        
        // Update the selected skin
        val newlySelectedSkin = focusedSkinId!!
        selectedSkin = newlySelectedSkin

        // Update visual states
        highlightFocusedCard() 

        // Trigger the callback
        onBlockSkinSelected?.invoke(selectedSkin)
    }

    /**
     * Updates the visual highlight state of the skin cards based on
     * selection and internal focus.
     */
     private fun highlightFocusedCard() {
         if (skinCards.isEmpty()) return

         val focusColor = Color.YELLOW // Color for focused-but-not-selected
         val selectedColor = Color.WHITE // Color for selected (might be focused or not)

         skinCards.forEach { (skinId, card) ->
             val skinInfo = getBlockSkins()[skinId] ?: return@forEach
             // Check unlock status based on the navigable list derived from level/unlocks
             val isUnlocked = skinIdList.contains(skinId) 

             if (!isUnlocked) {
                 // Keep locked skins visually distinct
                 card.alpha = 0.5f
                 card.cardElevation = 2f
                 card.background = null
                 card.setCardBackgroundColor(skinInfo.backgroundColor)
                 card.scaleX = 1.0f // Reset scale
                 card.scaleY = 1.0f
                 return@forEach
             }

             // Reset unlocked cards first
             card.alpha = 1.0f
             card.cardElevation = 4f
             card.background = null
             card.setCardBackgroundColor(skinInfo.backgroundColor)
             card.scaleX = 1.0f
             card.scaleY = 1.0f

             val isSelected = (skinId == selectedSkin)
             val isFocused = (hasComponentFocus && skinId == focusedSkinId)

             var borderColor = Color.TRANSPARENT
             var borderWidth = 0
             var elevation = 4f
             var scale = 1.0f

             if (isSelected) {
                 borderColor = selectedColor
                 borderWidth = 6 // Thick border for selected
                 elevation = 12f // Higher elevation for selected
             }

             if (isFocused) {
                 // Focused item gets a distinct border (unless it's also selected)
                 if (!isSelected) {
                     borderColor = focusColor
                     borderWidth = 4 // Slightly thinner border for focused
                 }
                 elevation = 12f // Use high elevation for focus too
                 scale = 1.1f // Scale up the focused item
             }

             // Apply scale
             card.scaleX = scale
             card.scaleY = scale

             // Apply border and elevation
             if (borderWidth > 0) {
                 val gradientDrawable = GradientDrawable().apply {
                     setColor(skinInfo.backgroundColor) // Use skin's background for the fill
                     setStroke(borderWidth, borderColor)
                     cornerRadius = 12f
                 }
                 card.background = gradientDrawable
             } else {
                 card.background = null // Ensure no border if not selected/focused
             }
             card.cardElevation = elevation
         }
     }

    // Keep selectNextBlockSkin temporarily for compatibility, but it shouldn't be called by MainActivity anymore
    fun selectNextBlockSkin() {
        val allSkins = getBlockSkins().keys.toList()
        val currentIndex = allSkins.indexOf(selectedSkin)
        if (currentIndex == -1) return

        var nextIndex = (currentIndex + 1) % allSkins.size
        while (nextIndex != currentIndex) {
            val nextSkin = allSkins[nextIndex]
            val skinInfo = getBlockSkins()[nextSkin] ?: continue
            val isEffectivelyUnlocked = skinCards[nextSkin]?.alpha == 1.0f // Basic check based on alpha
                                       || playerLevel >= skinInfo.unlockLevel

            if (isEffectivelyUnlocked) {
                // This method now just sets the internal focus and confirms
                focusedSkinId = nextSkin
                focusedIndex = skinIdList.indexOf(nextSkin) // Update index based on navigable list
                if (focusedIndex == -1) { // If not found in navigable list, reset focus
                   focusedIndex = 0
                   focusedSkinId = if (skinIdList.isNotEmpty()) skinIdList[0] else null
                }
                 confirmSelection() // Confirm the selection
                return
            }
            nextIndex = (nextIndex + 1) % allSkins.size
        }
    }
} 