from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from data.world_loader import game_world
from data.items import ITEMS

# ... (main_menu_keyboard, move_keyboard are unchanged) ...
def main_menu_keyboard() -> InlineKeyboardMarkup:
    keyboard = [[InlineKeyboardButton("🗺️ Move", callback_data="move_menu"), InlineKeyboardButton("👀 Inspect Area", callback_data="inspect_area")], [InlineKeyboardButton("👤 Profile", callback_data="profile"), InlineKeyboardButton("🎒 Inventory", callback_data="inventory_menu")]]
    return InlineKeyboardMarkup(keyboard)

async def move_keyboard(current_location_id: str, player_id: int) -> InlineKeyboardMarkup:
    """
    Create a movement keyboard with stamina costs.
    Layout:
        [     North (⚡5)     ]
        [ West (⚡5) ] [ East (⚡5) ]
        [     South (⚡5)     ]
        [ Other exits (inside, down, etc.) ]
        [     Back      ]
    """
    from bot import database, logic
    
    keyboard = []
    location = game_world.get_location(current_location_id)
    player = await database.get_player(player_id)
    inventory = await database.get_inventory(player_id)
    
    if location and player:
        # Dictionary to hold direction buttons
        compass_directions = {}
        other_exits = []
        
        for direction, destination_id in location.exits.items():
            destination = game_world.get_location(destination_id)
            if destination:
                # Calculate stamina cost for this specific route
                stamina_cost = logic.calculate_travel_stamina_cost(player, inventory, location, destination)
                
                # Map direction to emoji and label
                direction_lower = direction.lower()
                if direction_lower == "north":
                    emoji = "⬆️"
                    compass_directions["north"] = InlineKeyboardButton(
                        f"{emoji} {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    )
                elif direction_lower == "south":
                    emoji = "⬇️"
                    compass_directions["south"] = InlineKeyboardButton(
                        f"{emoji} {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    )
                elif direction_lower == "east":
                    emoji = "➡️"
                    compass_directions["east"] = InlineKeyboardButton(
                        f"{emoji} {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    )
                elif direction_lower == "west":
                    emoji = "⬅️"
                    compass_directions["west"] = InlineKeyboardButton(
                        f"{emoji} {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    )
                elif direction_lower == "northeast":
                    emoji = "↗️"
                    compass_directions["northeast"] = InlineKeyboardButton(
                        f"{emoji} {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    )
                elif direction_lower == "northwest":
                    emoji = "↖️"
                    compass_directions["northwest"] = InlineKeyboardButton(
                        f"{emoji} {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    )
                elif direction_lower == "southeast":
                    emoji = "↘️"
                    compass_directions["southeast"] = InlineKeyboardButton(
                        f"{emoji} {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    )
                elif direction_lower == "southwest":
                    emoji = "↙️"
                    compass_directions["southwest"] = InlineKeyboardButton(
                        f"{emoji} {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    )
                elif direction_lower == "inside":
                    emoji = "🚪"
                    other_exits.append(InlineKeyboardButton(
                        f"{emoji} Enter {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    ))
                elif direction_lower == "outside":
                    emoji = "🚪"
                    other_exits.append(InlineKeyboardButton(
                        f"{emoji} Exit to {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    ))
                elif direction_lower == "down":
                    emoji = "⬇️"
                    other_exits.append(InlineKeyboardButton(
                        f"{emoji} Descend to {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    ))
                elif direction_lower == "up":
                    emoji = "⬆️"
                    other_exits.append(InlineKeyboardButton(
                        f"{emoji} Ascend to {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    ))
                else:
                    # Generic fallback for any other direction
                    emoji = "🔀"
                    other_exits.append(InlineKeyboardButton(
                        f"{emoji} {destination.name} (⚡{stamina_cost})", 
                        callback_data=f"move:{destination_id}"
                    ))
        
        # Build compass layout
        # Row 1: Northwest, North, Northeast
        top_row = []
        if "northwest" in compass_directions:
            top_row.append(compass_directions["northwest"])
        if "north" in compass_directions:
            top_row.append(compass_directions["north"])
        if "northeast" in compass_directions:
            top_row.append(compass_directions["northeast"])
        if top_row:
            keyboard.append(top_row)
        
        # Row 2: West and/or East
        middle_row = []
        if "west" in compass_directions:
            middle_row.append(compass_directions["west"])
        if "east" in compass_directions:
            middle_row.append(compass_directions["east"])
        if middle_row:
            keyboard.append(middle_row)
        
        # Row 3: Southwest, South, Southeast
        bottom_row = []
        if "southwest" in compass_directions:
            bottom_row.append(compass_directions["southwest"])
        if "south" in compass_directions:
            bottom_row.append(compass_directions["south"])
        if "southeast" in compass_directions:
            bottom_row.append(compass_directions["southeast"])
        if bottom_row:
            keyboard.append(bottom_row)
        
        # Add other exits (inside, outside, up, down, etc.)
        for exit_button in other_exits:
            keyboard.append([exit_button])
    
    keyboard.append([InlineKeyboardButton("⬅️ Back", callback_data="main_menu")])
    return InlineKeyboardMarkup(keyboard)

async def inspect_keyboard(location_id: str, dropped_items: list, wandering_enemies: list = None) -> InlineKeyboardMarkup:
    from bot import database
    from data.npcs import NPCS
    
    keyboard = []
    location = game_world.get_location(location_id)
    
    # Show wandering enemies first if present (in pairs, emoji only)
    if wandering_enemies:
        row = []
        for enemy in wandering_enemies:
            npc_def = NPCS.get(enemy['npc_id'])
            if npc_def:
                button = InlineKeyboardButton(
                    f"⚠️ {npc_def.emoji} {npc_def.name}",
                    callback_data=f"attack_wandering:{enemy['id']}"
                )
                row.append(button)
                if len(row) == 2:
                    keyboard.append(row)
                    row = []
        if row:  # Add remaining enemy if odd number
            keyboard.append(row)
        if wandering_enemies:
            keyboard.append([InlineKeyboardButton("--- Environment ---", callback_data="no_op")])
    
    # Show interactables in pairs when text is short enough
    if location:
        row = []
        for instance_id, interactable in location.interactables.items():
            label = interactable.name
            # Check if ANY action is available (not on cooldown)
            has_available_action = False
            for action_id in interactable.actions.keys():
                cooldown_key = f"{instance_id}:{action_id}"
                if await database.get_cooldown(cooldown_key) == 0:
                    has_available_action = True
                    break
            if not has_available_action and len(interactable.actions) > 0:
                label += " ⏳"
            
            # Include location_id in callback data for efficient lookup
            button = InlineKeyboardButton(label, callback_data=f"inspect:{location_id}:{instance_id}")
            
            # If text is short (< 20 chars), try to pair it
            if len(label) < 20:
                row.append(button)
                if len(row) == 2:
                    keyboard.append(row)
                    row = []
            else:
                # Long text, add any pending row first, then add this one alone
                if row:
                    keyboard.append(row)
                    row = []
                keyboard.append([button])
        
        # Add remaining button if odd number
        if row:
            keyboard.append(row)
    
    # Show player corpse bags
    player_corpses = await database.get_player_corpses_in_location(location_id)
    if player_corpses:
        keyboard.append([InlineKeyboardButton("--- Fallen survivors ---", callback_data="no_op")])
        row = []
        for corpse in player_corpses:
            button = InlineKeyboardButton(
                f"🎒 {corpse['player_name']}'s bag",
                callback_data=f"loot_player_corpse:{corpse['id']}"
            )
            row.append(button)
            if len(row) == 2:
                keyboard.append(row)
                row = []
        if row:
            keyboard.append(row)
    
    # Show NPC corpses
    npc_corpses = await database.get_npc_corpses_in_location(location_id)
    if npc_corpses:
        if not player_corpses:  # Only add separator if not already added
            keyboard.append([InlineKeyboardButton("--- Corpses ---", callback_data="no_op")])
        row = []
        for corpse in npc_corpses:
            from data.npcs import NPCS
            npc_def = NPCS.get(corpse['npc_id'])
            if npc_def:
                button = InlineKeyboardButton(
                    f"{npc_def.emoji} {npc_def.name}",
                    callback_data=f"scavenge_npc_corpse:{corpse['id']}"
                )
                row.append(button)
                if len(row) == 2:
                    keyboard.append(row)
                    row = []
        if row:
            keyboard.append(row)
            
    if dropped_items:
        keyboard.append([InlineKeyboardButton("--- Items on the ground ---", callback_data="no_op")])
        row = []
        for item in dropped_items:
            item_def = ITEMS.get(item['item_id'], {})
            emoji = item_def.get('emoji', '❔')
            quantity_text = f" x{item['quantity']}" if item['quantity'] > 1 else ""
            button = InlineKeyboardButton(
                f"{emoji} {item_def.get('name', 'Unknown')}{quantity_text}", 
                callback_data=f"pickup_menu:{item['id']}"
            )
            row.append(button)
            if len(row) == 2:
                keyboard.append(row)
                row = []
        if row:
            keyboard.append(row)

    keyboard.append([InlineKeyboardButton("⬅️ Back", callback_data="main_menu")])
    return InlineKeyboardMarkup(keyboard)

def pickup_options_keyboard(item_id: int, item_name: str, quantity: int) -> InlineKeyboardMarkup:
    """Create pickup options keyboard with x1, x5, x10, and All options."""
    keyboard = []
    
    if quantity == 1:
        # Just show a single "Pick" button for single items
        keyboard.append([InlineKeyboardButton("📦 Pick", callback_data=f"pickup:{item_id}:1")])
    else:
        # Build pickup row with available options
        pickup_row = [InlineKeyboardButton("📦 Pick x1", callback_data=f"pickup:{item_id}:1")]
        
        if quantity >= 5:
            pickup_row.append(InlineKeyboardButton("📦 Pick x5", callback_data=f"pickup:{item_id}:5"))
        if quantity >= 10:
            pickup_row.append(InlineKeyboardButton("📦 Pick x10", callback_data=f"pickup:{item_id}:10"))
        
        # Split into rows if more than 2 buttons
        if len(pickup_row) > 2:
            keyboard.append(pickup_row[:2])
            keyboard.append(pickup_row[2:])
        else:
            keyboard.append(pickup_row)
        
        # Add "Pick All" option
        keyboard.append([InlineKeyboardButton(f"📦 Pick All ({quantity})", callback_data=f"pickup:{item_id}:all")])
    
    # Back button
    keyboard.append([InlineKeyboardButton("⬅️ Back", callback_data="inspect_area")])
    
    return InlineKeyboardMarkup(keyboard)

async def actions_keyboard(location_id: str, instance_id: str) -> InlineKeyboardMarkup:
    from bot import database
    keyboard = []
    
    location = game_world.get_location(location_id)
    
    if location:
        interactable = location.get_interactable(instance_id)
        if interactable:
            for action_id, action in interactable.actions.items():
                cooldown_key = f"{instance_id}:{action_id}"
                cooldown = await database.get_cooldown(cooldown_key)
                label = action.label
                # Add stamina cost to the label
                if action.stamina_cost > 0:
                    label += f" (⚡{action.stamina_cost})"
                if cooldown > 0:
                    label += " ⏳"
                keyboard.append([InlineKeyboardButton(label, callback_data=f"action:{location_id}:{instance_id}:{action_id}")])
    
    keyboard.append([InlineKeyboardButton("⬅️ Back", callback_data=f"inspect_area_menu:{location_id}")])
    return InlineKeyboardMarkup(keyboard)

# ... (inventory_keyboard, inventory_item_actions_keyboard are unchanged) ...
def inventory_keyboard(inventory_items: list) -> InlineKeyboardMarkup:
    keyboard = []
    if inventory_items:
        # Categorize and sort items
        # Group items by item_id and equipped status to handle stacking properly
        item_groups = {}
        
        for item in inventory_items:
            item_def = ITEMS.get(item['item_id'], {})
            item_type = item_def.get('type', 'resource')
            item_name = item_def.get('name', 'Unknown')
            is_equipped = item.get('is_equipped', False)
            
            # Create a unique key for grouping: item_id + equipped status
            group_key = (item['item_id'], is_equipped)
            
            if group_key not in item_groups:
                item_groups[group_key] = {
                    'name': item_name,
                    'def': item_def,
                    'type': item_type,
                    'is_equipped': is_equipped,
                    'items': []
                }
            item_groups[group_key]['items'].append(item)
        
        # Categorize groups
        equipped = []
        consumables = []
        weapons = []
        equipment = []
        resources = []
        quest_items = []
        
        for group_key, group_data in item_groups.items():
            item_name = group_data['name']
            item_def = group_data['def']
            item_type = group_data['type']
            is_equipped = group_data['is_equipped']
            items_list = group_data['items']
            
            # Calculate total quantity and weight/volume for this group
            total_quantity = sum(itm['quantity'] for itm in items_list)
            weight_per_item = item_def.get('weight', 0)
            volume_per_item = item_def.get('volume', 0)
            total_weight = weight_per_item * total_quantity
            total_volume = volume_per_item * total_quantity
            
            # Use the first item's ID for the callback (they're all the same item type)
            first_item_id = items_list[0]['id']
            
            # Create item data tuple: (name, item_def, first_item_id, quantity, weight, volume, is_equipped)
            item_tuple = (item_name, item_def, first_item_id, total_quantity, total_weight, total_volume, is_equipped)
            
            # Only equipped items go to equipped section
            if is_equipped:
                equipped.append(item_tuple)
            elif item_type == 'consumable':
                consumables.append(item_tuple)
            elif item_type == 'weapon':
                weapons.append(item_tuple)
            elif item_type == 'equipment':
                equipment.append(item_tuple)
            elif item_type == 'quest':
                quest_items.append(item_tuple)
            else:
                resources.append(item_tuple)
        
        # Sort each category alphabetically by name
        equipped.sort(key=lambda x: x[0])
        consumables.sort(key=lambda x: x[0])
        weapons.sort(key=lambda x: x[0])
        equipment.sort(key=lambda x: x[0])
        resources.sort(key=lambda x: x[0])
        quest_items.sort(key=lambda x: x[0])
        
        # Build keyboard sections
        def add_section(section_name, items_list):
            if items_list:
                keyboard.append([InlineKeyboardButton(f"--- {section_name} ---", callback_data="no_op")])
                row = []
                for item_name, item_def, item_id, quantity, weight, volume, is_equipped in items_list:
                    emoji = item_def.get('emoji', '❔')
                    quantity_text = f" x{quantity}" if quantity > 1 else ""
                    equipped_marker = " ✓" if is_equipped else ""
                    # Round to 2 decimals
                    weight_vol_text = f" ({weight:.2f}kg, {volume:.2f}vol)" if quantity > 0 else ""
                    
                    button = InlineKeyboardButton(
                        f"{emoji} {item_name}{quantity_text}{equipped_marker}{weight_vol_text}",
                        callback_data=f"inventory_item:{item_id}"
                    )
                    row.append(button)
                    if len(row) == 2:
                        keyboard.append(row)
                        row = []
                # Add remaining item if odd number
                if row:
                    keyboard.append(row)
        
        # Add sections in order
        add_section("Equipped", equipped)
        add_section("Consumables", consumables)
        add_section("Weapons", weapons)
        add_section("Equipment", equipment)
        add_section("Resources", resources)
        add_section("Quest Items", quest_items)
        
        if not keyboard:
            keyboard.append([InlineKeyboardButton("--- Inventory is empty ---", callback_data="no_op")])
    else:
        keyboard.append([InlineKeyboardButton("--- Inventory is empty ---", callback_data="no_op")])
    
    keyboard.append([InlineKeyboardButton("⬅️ Back", callback_data="main_menu")])
    return InlineKeyboardMarkup(keyboard)
def inventory_item_actions_keyboard(item_db_id: int, item_def: dict, is_equipped: bool = False, quantity: int = 1) -> InlineKeyboardMarkup:
    keyboard = []
    
    # Use button for consumables
    if item_def.get('type') == 'consumable':
        keyboard.append([InlineKeyboardButton("➡️ Use Item", callback_data=f"inventory_use:{item_db_id}")])
    
    # Equip/Unequip button for weapons and equipment
    if item_def.get('type') in ["weapon", "equipment"]:
        if is_equipped:
            keyboard.append([InlineKeyboardButton("❌ Unequip", callback_data=f"inventory_unequip:{item_db_id}")])
        else:
            keyboard.append([InlineKeyboardButton("✅ Equip", callback_data=f"inventory_equip:{item_db_id}")])
    
    # Drop buttons - simplified for single items
    if quantity == 1:
        # Just show a single "Drop" button
        keyboard.append([InlineKeyboardButton("🗑️ Drop", callback_data=f"inventory_drop:{item_db_id}:all")])
    else:
        # Show x1, x5, x10 options based on quantity
        drop_row = [InlineKeyboardButton("🗑️ Drop x1", callback_data=f"inventory_drop:{item_db_id}:1")]
        if quantity >= 5:
            drop_row.append(InlineKeyboardButton("🗑️ Drop x5", callback_data=f"inventory_drop:{item_db_id}:5"))
        if quantity >= 10:
            drop_row.append(InlineKeyboardButton("🗑️ Drop x10", callback_data=f"inventory_drop:{item_db_id}:10"))
        
        # Split into rows if more than 2 buttons
        if len(drop_row) > 2:
            keyboard.append(drop_row[:2])
            keyboard.append(drop_row[2:])
        else:
            keyboard.append(drop_row)
        
        # Add "Drop All" option
        keyboard.append([InlineKeyboardButton(f"🗑️ Drop All ({quantity})", callback_data=f"inventory_drop:{item_db_id}:all")])
    
    keyboard.append([InlineKeyboardButton("⬅️ Back to Inventory", callback_data="inventory_menu")])
    return InlineKeyboardMarkup(keyboard)

async def combat_keyboard(player_id: int) -> InlineKeyboardMarkup:
    """Create combat action keyboard."""
    from bot import database
    keyboard = []
    
    # Attack option
    keyboard.append([InlineKeyboardButton("⚔️ Attack", callback_data="combat_attack")])
    
    # Flee option
    keyboard.append([InlineKeyboardButton("🏃 Try to Flee", callback_data="combat_flee")])
    
    # Use item option (show consumables)
    inventory_items = await database.get_inventory(player_id)
    consumables = [item for item in inventory_items if ITEMS.get(item['item_id'], {}).get('type') == 'consumable']
    
    if consumables:
        keyboard.append([InlineKeyboardButton("💊 Use Item", callback_data="combat_use_item_menu")])
    
    return InlineKeyboardMarkup(keyboard)

async def combat_items_keyboard(player_id: int) -> InlineKeyboardMarkup:
    """Show consumable items during combat."""
    from bot import database
    keyboard = []
    
    inventory_items = await database.get_inventory(player_id)
    consumables = [item for item in inventory_items if ITEMS.get(item['item_id'], {}).get('type') == 'consumable']
    
    if consumables:
        keyboard.append([InlineKeyboardButton("--- Select item to use ---", callback_data="no_op")])
        for item in consumables:
            item_def = ITEMS.get(item['item_id'], {})
            emoji = item_def.get('emoji', '❔')
            keyboard.append([InlineKeyboardButton(
                f"{emoji} {item_def.get('name', 'Unknown')} x{item['quantity']}",
                callback_data=f"combat_use_item:{item['id']}"
            )])
    
    keyboard.append([InlineKeyboardButton("⬅️ Back to Combat", callback_data="combat_back")])
    return InlineKeyboardMarkup(keyboard)

def corpse_keyboard(corpse_id: int, corpse_type: str) -> InlineKeyboardMarkup:
    """Create keyboard for interacting with corpses."""
    keyboard = []
    
    if corpse_type == "player":
        keyboard.append([InlineKeyboardButton("🎒 Loot Bag", callback_data=f"loot_player_corpse:{corpse_id}")])
    else:  # NPC corpse
        keyboard.append([InlineKeyboardButton("🔪 Scavenge Corpse", callback_data=f"scavenge_npc_corpse:{corpse_id}")])
    
    keyboard.append([InlineKeyboardButton("⬅️ Back", callback_data="inspect_area")])
    return InlineKeyboardMarkup(keyboard)

def player_corpse_loot_keyboard(corpse_id: int, items: list) -> InlineKeyboardMarkup:
    """Show items in a player corpse bag."""
    keyboard = []
    
    if items:
        keyboard.append([InlineKeyboardButton("--- Take items ---", callback_data="no_op")])
        for i, item_data in enumerate(items):
            item_def = ITEMS.get(item_data['item_id'], {})
            emoji = item_def.get('emoji', '❔')
            keyboard.append([InlineKeyboardButton(
                f"{emoji} Take {item_def.get('name', 'Unknown')} x{item_data['quantity']}",
                callback_data=f"take_corpse_item:{corpse_id}:{i}"
            )])
    else:
        keyboard.append([InlineKeyboardButton("--- Bag is empty ---", callback_data="no_op")])
    
    keyboard.append([InlineKeyboardButton("⬅️ Back", callback_data="inspect_area")])
    return InlineKeyboardMarkup(keyboard)

def npc_corpse_scavenge_keyboard(corpse_id: int, loot_items: list) -> InlineKeyboardMarkup:
    """Show scavenging options for NPC corpse."""
    keyboard = []
    
    if loot_items:
        keyboard.append([InlineKeyboardButton("--- Scavenge for materials ---", callback_data="no_op")])
        for i, loot_data in enumerate(loot_items):
            item_def = ITEMS.get(loot_data['item_id'], {})
            emoji = item_def.get('emoji', '❔')
            
            label = f"{emoji} {item_def.get('name', 'Unknown')}"
            if loot_data.get('required_tool'):
                tool_def = ITEMS.get(loot_data['required_tool'], {})
                label += f" (needs {tool_def.get('name', 'tool')})"
            
            keyboard.append([InlineKeyboardButton(
                label,
                callback_data=f"scavenge_corpse_item:{corpse_id}:{i}"
            )])
    else:
        keyboard.append([InlineKeyboardButton("--- Nothing left to scavenge ---", callback_data="no_op")])
    
    keyboard.append([InlineKeyboardButton("⬅️ Back", callback_data="inspect_area")])
    return InlineKeyboardMarkup(keyboard)

def spend_points_keyboard() -> InlineKeyboardMarkup:
    """Create keyboard for spending stat points."""
    keyboard = [
        [
            InlineKeyboardButton("❤️ Max HP (+10)", callback_data="spend_point:max_hp"),
            InlineKeyboardButton("⚡ Stamina (+5)", callback_data="spend_point:max_stamina")
        ],
        [
            InlineKeyboardButton("💪 Strength (+1)", callback_data="spend_point:strength"),
            InlineKeyboardButton("🏃 Agility (+1)", callback_data="spend_point:agility")
        ],
        [
            InlineKeyboardButton("💚 Endurance (+1)", callback_data="spend_point:endurance"),
            InlineKeyboardButton("🧠 Intellect (+1)", callback_data="spend_point:intellect")
        ],
        [InlineKeyboardButton("⬅️ Back to Profile", callback_data="profile")]
    ]
    return InlineKeyboardMarkup(keyboard)

