extends CanvasLayer

# Minimalistic Inventory UI with Stats Panel
# Toggle with Tab key, shows stats, equipment slots and inventory items
# Uses inventory_slot graphics like inspiration inventory system
# Supports keyboard navigation with arrow keys

var is_open: bool = false
var local_player: Node = null

# Selection tracking
var selected_item: Item = null  # Selected inventory item
var selected_slot: String = ""  # Selected equipment slot name
var selected_type: String = ""  # "item" or "equipment"

# Navigation tracking (for keyboard navigation)
var inventory_selection_row: int = 0  # Current inventory row (0-based)
var inventory_selection_col: int = 0  # Current inventory column (0-based)
var equipment_selection_index: int = 0  # Current equipment slot index (0-5: mainhand, offhand, headgear, armour, boots, accessory)

# UI Nodes (from scene)
@onready var container: Control = $InventoryContainer
@onready var stats_panel: Control = $InventoryContainer/HBox/StatsPanel
@onready var equipment_panel: GridContainer = $InventoryContainer/HBox/InventoryPanel/EquipmentPanel
@onready var scroll_container: ScrollContainer = $InventoryContainer/HBox/InventoryPanel/InventoryScroll
@onready var inventory_grid: VBoxContainer = $InventoryContainer/HBox/InventoryPanel/InventoryScroll/InventoryVBox
@onready var selection_rectangle: Panel = $InventoryContainer/SelectionRectangle
@onready var info_panel: Control = $InventoryContainer/InfoPanel
@onready var info_label: Label = $InventoryContainer/InfoPanel/InfoLabel
@onready var label_base_stats: Label = $InventoryContainer/HBox/StatsPanel/StatsHBox/LabelBaseStats
@onready var label_base_stats_value: Label = $InventoryContainer/HBox/StatsPanel/StatsHBox/LabelBaseStatsValue
@onready var label_derived_stats: Label = $InventoryContainer/HBox/StatsPanel/StatsHBox/LabelDerivedStats
@onready var label_derived_stats_value: Label = $InventoryContainer/HBox/StatsPanel/StatsHBox/LabelDerivedStatsValue

# Store button/item mappings for selection highlighting
var inventory_buttons: Dictionary = {}  # item -> button
var equipment_buttons: Dictionary = {}  # slot_name -> button
var inventory_items_list: Array = []  # Flat list of items for navigation
var inventory_rows_list: Array = []  # List of HBoxContainers (rows)

# Equipment slot buttons
var equipment_slots: Dictionary = {
	"mainhand": null,
	"offhand": null,
	"headgear": null,
	"armour": null,
	"boots": null,
	"accessory": null
}
var equipment_slots_list: Array = ["mainhand", "offhand", "headgear", "armour", "boots", "accessory"]  # Order for navigation

# StyleBoxes for inventory slots (like inspiration system)
var style_box_hover: StyleBox = null
var style_box_focused: StyleBox = null
var style_box_pressed: StyleBox = null
var style_box_empty: StyleBox = null
var quantity_font: Font = null

# Selection animation
var selection_animation_time: float = 0.0

func _ready():
	# Set layer to be above game but below chat
	layer = 150
	
	# Load styleboxes for inventory slots (like inspiration system)
	_setup_styleboxes()
	
	# Setup fonts for labels
	_setup_fonts()
	
	# Create equipment slot buttons (dynamically)
	_create_equipment_slots()
	
	# Setup selection rectangle (already in scene, just configure it)
	_setup_selection_rectangle()
	
	# Find local player
	call_deferred("_find_local_player")

func _setup_styleboxes():
	# Create styleboxes similar to inspiration inventory system
	var slot_texture = preload("res://assets/gfx/ui/inventory_slot_kenny_white.png")
	if not slot_texture:
		# Fallback if texture doesn't exist
		slot_texture = null
	
	style_box_empty = StyleBoxEmpty.new()
	
	if slot_texture:
		style_box_hover = StyleBoxTexture.new()
		style_box_hover.texture = slot_texture
		
		style_box_focused = StyleBoxTexture.new()
		style_box_focused.texture = slot_texture
		
		style_box_pressed = StyleBoxTexture.new()
		style_box_pressed.texture = slot_texture
	else:
		# Fallback to empty styleboxes if texture not found
		style_box_hover = StyleBoxEmpty.new()
		style_box_focused = StyleBoxEmpty.new()
		style_box_pressed = StyleBoxEmpty.new()
	
	# Load quantity font (dmg_numbers.png)
	if ResourceLoader.exists("res://assets/fonts/dmg_numbers.png"):
		quantity_font = load("res://assets/fonts/dmg_numbers.png")

func _setup_fonts():
	# Setup fonts for labels (standard_font.png)
	var standard_font_resource = null
	if ResourceLoader.exists("res://assets/fonts/standard_font.png"):
		standard_font_resource = load("res://assets/fonts/standard_font.png")
		if standard_font_resource:
			# Stats panel labels
			if label_base_stats:
				label_base_stats.add_theme_font_override("font", standard_font_resource)
			if label_base_stats_value:
				label_base_stats_value.add_theme_font_override("font", standard_font_resource)
			if label_derived_stats:
				label_derived_stats.add_theme_font_override("font", standard_font_resource)
			if label_derived_stats_value:
				label_derived_stats_value.add_theme_font_override("font", standard_font_resource)
			
			# Info label
			if info_label:
				info_label.add_theme_font_override("font", standard_font_resource)
			
			# Equipment and Inventory labels
			var eq_label = container.get_node_or_null("HBox/InventoryPanel/EquipmentLabel")
			if eq_label:
				eq_label.add_theme_font_override("font", standard_font_resource)
			var inv_label = container.get_node_or_null("HBox/InventoryPanel/InventoryLabel")
			if inv_label:
				inv_label.add_theme_font_override("font", standard_font_resource)
			var stats_label = container.get_node_or_null("HBox/StatsPanel/StatsLabel")
			if stats_label:
				stats_label.add_theme_font_override("font", standard_font_resource)

func _setup_selection_rectangle():
	# Selection rectangle is already in scene, just ensure it's configured correctly
	if selection_rectangle:
		selection_rectangle.visible = false

func _find_local_player():
	# Find the local player
	var game_world = get_tree().get_first_node_in_group("game_world")
	if game_world:
		var player_manager = game_world.get_node_or_null("PlayerManager")
		if player_manager:
			var local_players = player_manager.get_local_players()
			if local_players.size() > 0:
				local_player = local_players[0]
				if local_player and local_player.character_stats:
					# Connect to character_changed signal
					if local_player.character_stats.character_changed.is_connected(_on_character_changed):
						local_player.character_stats.character_changed.disconnect(_on_character_changed)
					local_player.character_stats.character_changed.connect(_on_character_changed)
					# Initial update
					_update_ui()
					_update_stats()

func _update_stats():
	if not local_player or not local_player.character_stats:
		return
	
	var char_stats = local_player.character_stats
	
	# Update base stats
	label_base_stats_value.text = str(char_stats.level) + "\n\n" + \
		str(int(char_stats.hp)) + "/" + str(int(char_stats.maxhp)) + "\n" + \
		str(int(char_stats.mp)) + "/" + str(int(char_stats.maxmp)) + "\n\n" + \
		str(char_stats.baseStats.str) + "\n" + \
		str(char_stats.baseStats.dex) + "\n" + \
		str(char_stats.baseStats.end) + "\n" + \
		str(char_stats.baseStats.int) + "\n" + \
		str(char_stats.baseStats.wis) + "\n" + \
		str(char_stats.baseStats.lck)
	
	# Update derived stats
	label_derived_stats_value.text = str(int(char_stats.xp)) + "/" + str(int(char_stats.xp_to_next_level)) + "\n" + \
		str(char_stats.coin) + "\n\n\n\n" + \
		str(char_stats.damage) + "\n" + \
		str(char_stats.defense) + "\n" + \
		str(char_stats.move_speed) + "\n" + \
		str(char_stats.attack_speed) + "\n" + \
		str(char_stats.sight) + "\n" + \
		str(char_stats.spell_amp) + "\n" + \
		str(char_stats.crit_chance) + "%"

func _create_equipment_slots():
	# Equipment slot order: mainhand, offhand, headgear, armour, boots, accessory
	var slot_names = ["mainhand", "offhand", "headgear", "armour", "boots", "accessory"]
	var slot_labels = ["Main-hand", "Off-hand", "Head", "Armour", "Boots", "Accessory"]
	
	for i in range(slot_names.size()):
		var slot_name = slot_names[i]
		var slot_label = slot_labels[i]
		
		# Container for slot
		var slot_container = VBoxContainer.new()
		slot_container.name = slot_name + "_slot"
		equipment_panel.add_child(slot_container)
		
		# Label
		var label = Label.new()
		label.text = slot_label
		label.add_theme_font_size_override("font_size", 10)
		label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
		var standard_font_resource = null
		if ResourceLoader.exists("res://assets/fonts/standard_font.png"):
			var font_resource = load("res://assets/fonts/standard_font.png")
			if font_resource:
				label.add_theme_font_override("font", font_resource)
		slot_container.add_child(label)
		
		# Button (use styleboxes like inspiration system)
		var button = Button.new()
		button.name = slot_name + "_btn"
		button.custom_minimum_size = Vector2(24, 24)  # Smaller like inspiration (24x24 instead of 60x60)
		button.size = Vector2(24, 24)
		if style_box_empty:
			button.add_theme_stylebox_override("normal", style_box_empty)
		if style_box_hover:
			button.add_theme_stylebox_override("hover", style_box_hover)
		if style_box_focused:
			button.add_theme_stylebox_override("focus", style_box_focused)
		if style_box_pressed:
			button.add_theme_stylebox_override("pressed", style_box_pressed)
		button.flat = false  # Use styleboxes instead of flat
		button.connect("pressed", _on_equipment_slot_pressed.bind(slot_name))
		slot_container.add_child(button)
		
		equipment_slots[slot_name] = button
		equipment_buttons[slot_name] = button

func _has_equipment_in_slot(slot_name: String) -> bool:
	# Check if there's an item equipped in this slot
	if not local_player or not local_player.character_stats:
		return false
	return local_player.character_stats.equipment[slot_name] != null

func _find_next_filled_equipment_slot(start_index: int, direction: int) -> int:
	# Find next filled equipment slot, or -1 if none found
	var current_index = start_index
	for _i in range(equipment_slots_list.size()):
		current_index += direction
		if current_index < 0:
			current_index = equipment_slots_list.size() - 1
		elif current_index >= equipment_slots_list.size():
			current_index = 0
		
		var slot_name = equipment_slots_list[current_index]
		if _has_equipment_in_slot(slot_name):
			return current_index
	return -1

func _on_equipment_slot_pressed(slot_name: String):
	if not local_player or not local_player.character_stats:
		return
	
	# Only select if there's an item equipped
	if not _has_equipment_in_slot(slot_name):
		return
	
	# Select this slot
	selected_slot = slot_name
	selected_item = local_player.character_stats.equipment[slot_name]
	selected_type = "equipment" if selected_item else ""
	
	# Update navigation position
	if slot_name in equipment_slots_list:
		equipment_selection_index = equipment_slots_list.find(slot_name)
	
	_update_selection_highlight()
	_update_selection_rectangle()

func _update_selection_highlight():
	# Reset all button styles
	for button in equipment_buttons.values():
		if button:
			var highlight = button.get_node_or_null("Highlight")
			if highlight:
				highlight.queue_free()
	
	for button in inventory_buttons.values():
		if button:
			var highlight = button.get_node_or_null("Highlight")
			if highlight:
				highlight.queue_free()

func _update_selection_rectangle():
	# Update visual selection rectangle position and visibility
	if not selection_rectangle or not container:
		return
	
	var target_button: Button = null
	var target_position: Vector2 = Vector2.ZERO
	
	if selected_type == "equipment" and selected_slot != "":
		# Show rectangle on equipment slot (only if it has an item)
		if _has_equipment_in_slot(selected_slot):
			target_button = equipment_buttons.get(selected_slot)
			if target_button and target_button.is_inside_tree():
				# Get button position relative to container
				var button_global_pos = target_button.global_position
				var container_global_pos = container.global_position
				target_position = button_global_pos - container_global_pos
				selection_rectangle.visible = true
			else:
				selection_rectangle.visible = false
		else:
			selection_rectangle.visible = false
	elif selected_type == "item" and inventory_selection_row < inventory_rows_list.size():
		# Show rectangle on inventory item
		var row = inventory_rows_list[inventory_selection_row]
		if row and inventory_selection_col < row.get_child_count():
			target_button = row.get_child(inventory_selection_col) as Button
			if target_button and target_button.is_inside_tree():
				# Get button position relative to container
				var button_global_pos = target_button.global_position
				var container_global_pos = container.global_position
				target_position = button_global_pos - container_global_pos
				selection_rectangle.visible = true
			else:
				selection_rectangle.visible = false
		else:
			selection_rectangle.visible = false
	else:
		selection_rectangle.visible = false
	
	if target_button and selection_rectangle.visible:
		selection_rectangle.position = target_position
		# Ensure size is correct (48x48 to match sprite scale)
		selection_rectangle.size = Vector2(48, 48)

func _process(delta):
	if is_open and selection_rectangle and selection_rectangle.visible:
		# Animate selection rectangle border color
		selection_animation_time += delta * 2.0  # Speed of animation
		# Animate between yellow and orange
		var color1 = Color.YELLOW
		var color2 = Color(1.0, 0.7, 0.0)  # Orange-yellow
		var t = (sin(selection_animation_time) + 1.0) / 2.0  # 0 to 1
		var animated_color = color1.lerp(color2, t)
		
		# Update border color
		var stylebox = selection_rectangle.get_theme_stylebox("panel") as StyleBoxFlat
		if stylebox:
			stylebox.border_color = animated_color

func _update_ui():
	if not local_player or not local_player.character_stats:
		return
	
	var char_stats = local_player.character_stats
	
	# Debug: Print inventory contents
	print("InventoryUI: Updating UI - inventory size: ", char_stats.inventory.size())
	for i in range(char_stats.inventory.size()):
		var item = char_stats.inventory[i]
		print("  Item ", i, ": ", item.item_name if item else "null")
	
	# Clear button mappings
	inventory_buttons.clear()
	inventory_items_list.clear()
	inventory_rows_list.clear()
	
	# Update equipment slots
	for slot_name in equipment_slots.keys():
		var button = equipment_slots[slot_name]
		if not button:
			continue
		
		# Clear existing children (sprite, highlight)
		for child in button.get_children():
			child.queue_free()
		
		var equipped_item = char_stats.equipment[slot_name]
		if equipped_item:
			var sprite = Sprite2D.new()
			# Equipment slots should ONLY use spritePath (items_n_shit.png), NOT equipmentPath
			# equipmentPath is for character rendering only!
			var texture_path = equipped_item.spritePath
			
			var texture = load(texture_path)
			if texture:
				sprite.texture = texture
				sprite.hframes = equipped_item.spriteFrames.x if equipped_item.spriteFrames.x > 0 else 20
				sprite.vframes = equipped_item.spriteFrames.y if equipped_item.spriteFrames.y > 0 else 14
				sprite.frame = equipped_item.spriteFrame
				sprite.centered = false  # Like inspiration system
				sprite.position = Vector2(4, 4)  # Like inspiration system
				sprite.scale = Vector2(2.0, 2.0)  # 2x size as requested
				button.add_child(sprite)
	
	# Update inventory grid - clear existing HBoxContainers
	for child in inventory_grid.get_children():
		child.queue_free()
	
	# Add inventory items using HBoxContainers (like inspiration system)
	var current_hbox: HBoxContainer = null
	var items_per_row = 10  # Items per row (like inspiration system - they use 10 per HBox)
	var items_in_current_row = 0
	
	for item in char_stats.inventory:
		# Create new HBoxContainer if needed
		if current_hbox == null or items_in_current_row >= items_per_row:
			current_hbox = HBoxContainer.new()
			current_hbox.add_theme_constant_override("separation", 0)  # No separation like inspiration
			inventory_grid.add_child(current_hbox)
			inventory_rows_list.append(current_hbox)
			items_in_current_row = 0
		
		# Create button with styleboxes (like inspiration system)
		var button = Button.new()
		button.custom_minimum_size = Vector2(24, 24)  # Smaller like inspiration (24x24)
		button.size = Vector2(24, 24)
		if style_box_empty:
			button.add_theme_stylebox_override("normal", style_box_empty)
		if style_box_hover:
			button.add_theme_stylebox_override("hover", style_box_hover)
		if style_box_focused:
			button.add_theme_stylebox_override("focus", style_box_focused)
		if style_box_pressed:
			button.add_theme_stylebox_override("pressed", style_box_pressed)
		button.flat = false  # Use styleboxes
		button.connect("pressed", _on_inventory_item_pressed.bind(item))
		current_hbox.add_child(button)
		
		# Add item sprite (like inspiration system - positioned at 4,4 with centered=false)
		if item.spritePath != "":
			var sprite = Sprite2D.new()
			var texture = load(item.spritePath)
			if texture:
				sprite.texture = texture
				sprite.hframes = item.spriteFrames.x if item.spriteFrames.x > 0 else 20
				sprite.vframes = item.spriteFrames.y if item.spriteFrames.y > 0 else 14
				sprite.frame = item.spriteFrame
				sprite.centered = false  # Like inspiration system
				sprite.position = Vector2(4, 4)  # Like inspiration system
				sprite.scale = Vector2(2.0, 2.0)  # 2x size as requested
				button.add_child(sprite)
		
		# Add quantity label if item can have multiple (like inspiration system)
		if item.can_have_multiple_of and item.quantity > 1:
			var quantity_label = Label.new()
			quantity_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
			quantity_label.size = Vector2(24, 24)
			quantity_label.custom_minimum_size = Vector2(0, 0)
			quantity_label.position = Vector2(10, 2)
			quantity_label.text = str(item.quantity)
			if quantity_font:
				quantity_label.add_theme_font_override("font", quantity_font)
				quantity_label.add_theme_font_size_override("font_size", 8)
			quantity_label.scale = Vector2(0.5, 0.5)
			button.add_child(quantity_label)
		
		inventory_buttons[item] = button
		inventory_items_list.append(item)
		items_in_current_row += 1
	
	# Clamp selection to valid range
	if inventory_selection_row >= inventory_rows_list.size():
		inventory_selection_row = max(0, inventory_rows_list.size() - 1)
	if inventory_selection_row >= 0 and inventory_selection_row < inventory_rows_list.size():
		var row = inventory_rows_list[inventory_selection_row]
		if inventory_selection_col >= row.get_child_count():
			inventory_selection_col = max(0, row.get_child_count() - 1)
	
	# Update selection
	_update_selection_from_navigation()
	_update_selection_rectangle()
	_update_info_panel()

func _update_selection_from_navigation():
	# Update selected_item/selected_slot based on navigation position
	if selected_type == "equipment" and equipment_selection_index >= 0 and equipment_selection_index < equipment_slots_list.size():
		var slot_name = equipment_slots_list[equipment_selection_index]
		if _has_equipment_in_slot(slot_name):
			selected_slot = slot_name
			if local_player and local_player.character_stats:
				selected_item = local_player.character_stats.equipment[slot_name]
		else:
			# Empty slot - switch to inventory
			selected_type = "item"
			selected_slot = ""
			selected_item = null
			if inventory_rows_list.size() > 0:
				inventory_selection_row = 0
				inventory_selection_col = 0
				_update_selection_from_navigation()
	elif selected_type == "item" and inventory_selection_row >= 0 and inventory_selection_row < inventory_rows_list.size():
		var row = inventory_rows_list[inventory_selection_row]
		if inventory_selection_col >= 0 and inventory_selection_col < row.get_child_count():
			var item_index = inventory_selection_row * 10 + inventory_selection_col
			if item_index >= 0 and item_index < inventory_items_list.size():
				selected_item = inventory_items_list[item_index]
				selected_slot = ""

func _format_item_info(item: Item) -> String:
	# Format item description, stats modifiers, and controls
	var text = ""
	
	# Description
	if item.description != "":
		text += item.description
	else:
		text += item.item_name
	
	text += "\n\n"
	
	# Stats modifiers
	var stat_lines = []
	if item.modifiers.has("str"):
		stat_lines.append("STR: +%d" % item.modifiers["str"])
	if item.modifiers.has("dex"):
		stat_lines.append("DEX: +%d" % item.modifiers["dex"])
	if item.modifiers.has("end"):
		stat_lines.append("END: +%d" % item.modifiers["end"])
	if item.modifiers.has("int"):
		stat_lines.append("INT: +%d" % item.modifiers["int"])
	if item.modifiers.has("wis"):
		stat_lines.append("WIS: +%d" % item.modifiers["wis"])
	if item.modifiers.has("lck"):
		stat_lines.append("LCK: +%d" % item.modifiers["lck"])
	if item.modifiers.has("dmg"):
		stat_lines.append("DMG: +%d" % item.modifiers["dmg"])
	if item.modifiers.has("def"):
		stat_lines.append("DEF: +%d" % item.modifiers["def"])
	if item.modifiers.has("hp"):
		stat_lines.append("HP: +%d" % item.modifiers["hp"])
	if item.modifiers.has("mp"):
		stat_lines.append("MP: +%d" % item.modifiers["mp"])
	if item.modifiers.has("maxhp"):
		stat_lines.append("MAXHP: +%d" % item.modifiers["maxhp"])
	if item.modifiers.has("maxmp"):
		stat_lines.append("MAXMP: +%d" % item.modifiers["maxmp"])
	
	if stat_lines.size() > 0:
		text += "\n".join(stat_lines)
		text += "\n\n"
	
	# Controls
	if item.item_type == Item.ItemType.Equippable:
		if selected_type == "equipment":
			text += "Press F to unequip"
		else:
			text += "Press F to equip"
	elif item.item_type == Item.ItemType.Restoration:
		text += "Press F to consume"
	
	if selected_type == "item":
		text += "\nPress E to drop"
	
	return text

func _update_info_panel():
	# Update info panel based on selected item
	if not info_label:
		return
	
	if selected_item:
		info_label.text = _format_item_info(selected_item)
	else:
		info_label.text = ""

func _navigate_inventory(direction: String):
	# Handle navigation within inventory
	var items_per_row = 10
	
	match direction:
		"left":
			if inventory_selection_col > 0:
				inventory_selection_col -= 1
			else:
				# Wrap to end of previous row
				if inventory_selection_row > 0:
					inventory_selection_row -= 1
					var row = inventory_rows_list[inventory_selection_row]
					inventory_selection_col = row.get_child_count() - 1
		"right":
			if inventory_selection_row < inventory_rows_list.size():
				var row = inventory_rows_list[inventory_selection_row]
				if inventory_selection_col < row.get_child_count() - 1:
					inventory_selection_col += 1
				else:
					# Wrap to start of next row
					if inventory_selection_row < inventory_rows_list.size() - 1:
						inventory_selection_row += 1
						inventory_selection_col = 0
		"up":
			if inventory_selection_row > 0:
				inventory_selection_row -= 1
				# Clamp column to valid range
				var row = inventory_rows_list[inventory_selection_row]
				if inventory_selection_col >= row.get_child_count():
					inventory_selection_col = row.get_child_count() - 1
			else:
				# Move to equipment slots (only if there are filled slots)
				var next_equip_index = _find_next_filled_equipment_slot(-1, 1)  # Start from end, go forward
				if next_equip_index >= 0:
					selected_type = "equipment"
					equipment_selection_index = next_equip_index
					selected_slot = equipment_slots_list[next_equip_index]
					_update_selection_from_navigation()
					_update_selection_rectangle()
					_update_info_panel()
					return
		"down":
			if inventory_selection_row < inventory_rows_list.size() - 1:
				inventory_selection_row += 1
				# Clamp column to valid range
				var row = inventory_rows_list[inventory_selection_row]
				if inventory_selection_col >= row.get_child_count():
					inventory_selection_col = row.get_child_count() - 1
			# Can't go down from inventory (already at bottom)
	
	_update_selection_from_navigation()
	_update_selection_rectangle()
	_update_info_panel()

func _navigate_equipment(direction: String):
	# Handle navigation within equipment slots (only filled slots)
	# Equipment layout: 3 columns, 2 rows
	# Row 1: mainhand(0), offhand(1), headgear(2)
	# Row 2: armour(3), boots(4), accessory(5)
	
	match direction:
		"left":
			var next_index = _find_next_filled_equipment_slot(equipment_selection_index, -1)
			if next_index >= 0:
				equipment_selection_index = next_index
		"right":
			var next_index = _find_next_filled_equipment_slot(equipment_selection_index, 1)
			if next_index >= 0:
				equipment_selection_index = next_index
		"up":
			# Find next filled slot in row above (same column)
			var current_row = equipment_selection_index / 3
			var current_col = equipment_selection_index % 3
			if current_row > 0:
				var target_index = (current_row - 1) * 3 + current_col
				var target_slot = equipment_slots_list[target_index]
				if _has_equipment_in_slot(target_slot):
					equipment_selection_index = target_index
				else:
					# Skip to next filled slot in that row
					var next_index = _find_next_filled_equipment_slot(target_index - 1, 1)
					if next_index >= 0 and next_index < 3:  # Make sure it's in row 0
						equipment_selection_index = next_index
			# Can't go up from equipment (already at top)
		"down":
			# Find next filled slot in row below (same column), or move to inventory
			var current_row = equipment_selection_index / 3
			var current_col = equipment_selection_index % 3
			if current_row < 1:
				var target_index = (current_row + 1) * 3 + current_col
				var target_slot = equipment_slots_list[target_index]
				if _has_equipment_in_slot(target_slot):
					equipment_selection_index = target_index
				else:
					# No filled slot below, move to inventory
					selected_type = "item"
					inventory_selection_row = 0
					inventory_selection_col = current_col
					# Clamp to valid range
					if inventory_rows_list.size() > 0:
						var inv_row = inventory_rows_list[0]
						if inventory_selection_col >= inv_row.get_child_count():
							inventory_selection_col = inv_row.get_child_count() - 1
					else:
						inventory_selection_col = 0
					_update_selection_from_navigation()
					_update_selection_rectangle()
					_update_info_panel()
					return
			else:
				# Already at bottom row, move to inventory
				selected_type = "item"
				inventory_selection_row = 0
				inventory_selection_col = current_col
				# Clamp to valid range
				if inventory_rows_list.size() > 0:
					var inv_row = inventory_rows_list[0]
					if inventory_selection_col >= inv_row.get_child_count():
						inventory_selection_col = inv_row.get_child_count() - 1
				else:
					inventory_selection_col = 0
				_update_selection_from_navigation()
				_update_selection_rectangle()
				_update_info_panel()
				return
	
	_update_selection_from_navigation()
	_update_selection_rectangle()
	_update_info_panel()

func _on_inventory_item_pressed(item: Item):
	if not local_player or not local_player.character_stats:
		return
	
	selected_item = item
	selected_slot = ""
	selected_type = "item"
	
	# Update navigation position
	var item_index = inventory_items_list.find(item)
	if item_index >= 0:
		var items_per_row = 10
		inventory_selection_row = item_index / items_per_row
		inventory_selection_col = item_index % items_per_row
	
	_update_selection_highlight()
	_update_selection_rectangle()

func _on_character_changed(_char: CharacterStats):
	_update_ui()
	_update_stats()

func _input(event):
	# Toggle with Tab key
	if event is InputEventKey and event.keycode == KEY_TAB and event.pressed and not event.echo:
		if is_open:
			_close_inventory()
		else:
			_open_inventory()
		get_viewport().set_input_as_handled()
		return
	
	if not is_open:
		return
	
	# Arrow key navigation
	if event is InputEventKey and event.pressed and not event.echo:
		var direction = ""
		if event.keycode == KEY_LEFT:
			direction = "left"
		elif event.keycode == KEY_RIGHT:
			direction = "right"
		elif event.keycode == KEY_UP:
			direction = "up"
		elif event.keycode == KEY_DOWN:
			direction = "down"
		
		if direction != "":
			if selected_type == "equipment":
				_navigate_equipment(direction)
			else:
				_navigate_inventory(direction)
			get_viewport().set_input_as_handled()
			return
	
	# F key: Unequip/equip items
	if event is InputEventKey and event.keycode == KEY_F and event.pressed and not event.echo:
		_handle_f_key()
		get_viewport().set_input_as_handled()
		return
	
	# E key: Drop selected item
	if event is InputEventKey and event.keycode == KEY_E and event.pressed and not event.echo:
		_handle_e_key()
		get_viewport().set_input_as_handled()
		return

func _handle_f_key():
	if not local_player or not local_player.character_stats:
		return
	
	var char_stats = local_player.character_stats
	
	if selected_type == "equipment" and selected_slot != "":
		var equipped_item = char_stats.equipment[selected_slot]
		if equipped_item:
			char_stats.unequip_item(equipped_item)
			# After unequipping, if all equipment is empty, go to inventory
			var has_any_equipment = false
			for slot in equipment_slots_list:
				if _has_equipment_in_slot(slot):
					has_any_equipment = true
					break
			
			if not has_any_equipment:
				# No equipment left, go to inventory
				selected_type = "item"
				selected_slot = ""
				selected_item = null
				if inventory_rows_list.size() > 0:
					inventory_selection_row = 0
					inventory_selection_col = 0
				else:
					selected_type = ""
			else:
				# Find next filled equipment slot
				var next_index = _find_next_filled_equipment_slot(equipment_selection_index, 1)
				if next_index >= 0:
					equipment_selection_index = next_index
					selected_slot = equipment_slots_list[next_index]
					selected_item = char_stats.equipment[selected_slot]
				else:
					# No more equipment, go to inventory
					selected_type = "item"
					selected_slot = ""
					selected_item = null
					if inventory_rows_list.size() > 0:
						inventory_selection_row = 0
						inventory_selection_col = 0
			_update_selection_from_navigation()
			_update_selection_rectangle()
			return
	
	if selected_type == "item" and selected_item:
		if selected_item.item_type == Item.ItemType.Equippable and selected_item.equipment_type != Item.EquipmentType.NONE:
			char_stats.equip_item(selected_item)
			# After equipping, selection might move to equipment slot
			_update_ui()
			_update_selection_rectangle()
		elif selected_item.item_type == Item.ItemType.Restoration:
			_use_consumable_item(selected_item)
			_update_info_panel()

func _use_consumable_item(item: Item):
	if not local_player or not local_player.character_stats:
		return
	
	var char_stats = local_player.character_stats
	
	if item.modifiers.has("hp"):
		var hp_heal = item.modifiers["hp"]
		if local_player.has_method("heal"):
			local_player.heal(hp_heal)
	if item.modifiers.has("mp"):
		var mana_amount = item.modifiers["mp"]
		char_stats.restore_mana(mana_amount)
	
	var index = char_stats.inventory.find(item)
	if index >= 0:
		char_stats.inventory.remove_at(index)
		char_stats.character_changed.emit(char_stats)
	
	print(local_player.name, " used item: ", item.item_name)

func _handle_e_key():
	if not local_player or not local_player.character_stats:
		return
	
	if selected_type != "item" or not selected_item:
		return
	
	var char_stats = local_player.character_stats
	
	if not selected_item in char_stats.inventory:
		return
	
	var index = char_stats.inventory.find(selected_item)
	if index >= 0:
		char_stats.inventory.remove_at(index)
	
	var drop_position = local_player.global_position + Vector2(randf_range(-20, 20), randf_range(-20, 20))
	var game_world = get_tree().get_first_node_in_group("game_world")
	var entities_node = null
	if game_world:
		entities_node = game_world.get_node_or_null("Entities")
	
	if entities_node:
		var loot = ItemLootHelper.spawn_item_loot(selected_item, drop_position, entities_node, game_world)
		if loot:
			if local_player.has_method("get_multiplayer_authority"):
				var player_peer_id = local_player.get_multiplayer_authority()
				loot.set_meta("dropped_by_peer_id", player_peer_id)
				loot.set_meta("drop_time", Time.get_ticks_msec())
	
	selected_item = null
	selected_slot = ""
	selected_type = ""
	
	char_stats.character_changed.emit(char_stats)
	
	print(local_player.name, " dropped item")

func _open_inventory():
	if is_open:
		return
	
	is_open = true
	if container:
		container.visible = true
	
	_lock_player_controls(true)
	_update_ui()
	
	# Initialize selection - prefer inventory, but if empty, check equipment
	if inventory_rows_list.size() > 0:
		selected_type = "item"
		inventory_selection_row = 0
		inventory_selection_col = 0
		_update_selection_from_navigation()
		_update_selection_rectangle()
	else:
		# No inventory items, try equipment
		var first_filled_slot = _find_next_filled_equipment_slot(-1, 1)
		if first_filled_slot >= 0:
			selected_type = "equipment"
			equipment_selection_index = first_filled_slot
			selected_slot = equipment_slots_list[first_filled_slot]
			_update_selection_from_navigation()
			_update_selection_rectangle()
			_update_info_panel()
		else:
			# Nothing to select
			selected_type = ""
			selection_rectangle.visible = false
			if info_label:
				info_label.text = ""
	
	if not local_player:
		_find_local_player()

func _close_inventory():
	if not is_open:
		return
	
	is_open = false
	if container:
		container.visible = false
	
	if selection_rectangle:
		selection_rectangle.visible = false
	
	selected_item = null
	selected_slot = ""
	selected_type = ""
	
	_lock_player_controls(false)

func _lock_player_controls(lock: bool):
	var game_world = get_tree().get_first_node_in_group("game_world")
	if game_world:
		var player_manager = game_world.get_node_or_null("PlayerManager")
		if player_manager:
			var local_players = player_manager.get_local_players()
			for player in local_players:
				player.controls_disabled = lock
