extends Area2D

# Room Trigger - Detects when players enter/exit a room

var room: Dictionary = {} # Room data this trigger covers
var players_in_room: Array = [] # Players currently in the room
var doors_in_room: Array = [] # Doors that belong to this room
var enemies_in_room: Array = [] # Enemies in this room
var floor_switches_in_room: Array = [] # Floor switches in this room
var enemy_spawners: Array = [] # Enemy spawners for this room
var enemies_spawned: bool = false # True if enemies have been spawned for this room
var debug_label: Label = null # Debug label showing puzzle type and trigger status
var room_entered: bool = false # True if player has entered this room

func _ready():
	# Set collision mask to detect players
	collision_layer = 0
	collision_mask = 1 # Detect players (layer 1)
	
	# Connect signals
	body_entered.connect(_on_body_entered)
	body_exited.connect(_on_body_exited)
	
	# Find doors, enemies, and switches in this room (deferred to ensure doors are fully initialized)
	# This ensures doors have their blocking_room set before we try to find them
	call_deferred("_find_room_entities")
	
	# Create debug label (deferred to avoid blocking on font load during startup)
	# Only create if debug mode is enabled
	call_deferred("_create_debug_label")

func _on_body_entered(body):
	# Player entered the room
	if body.is_in_group("player"):
		if not body in players_in_room:
			players_in_room.append(body)
			_on_player_entered_room(body)

func _on_body_exited(body):
	# Player left the room
	if body.is_in_group("player"):
		if body in players_in_room:
			players_in_room.erase(body)
			_on_player_exited_room(body)

func _on_player_entered_room(player: Node):
	# Handle player entering room
	LogManager.log("Player " + str(player.name) + " entered room at " + str(room.x) + ", " + str(room.y), LogManager.CATEGORY_DUNGEON)
	LogManager.log("RoomTrigger: This trigger is for room (" + str(room.x) + ", " + str(room.y) + ", " + str(room.w) + "x" + str(room.h) + ")", LogManager.CATEGORY_DUNGEON)
	LogManager.log("RoomTrigger: Found " + str(doors_in_room.size()) + " doors in this room", LogManager.CATEGORY_DUNGEON)
	
	# Check if this is the exit room (has EXIT modifier) - trigger exit found notification
	if room.has("modifiers") and room.modifiers is Array:
		for modifier in room.modifiers:
			if modifier is Dictionary and modifier.has("type") and modifier.type == "EXIT":
				# This is the exit room - notify player to show alert and play sound
				if player and is_instance_valid(player) and player.has_method("_on_exit_found"):
					player._on_exit_found()
				LogManager.log("RoomTrigger: Exit room entered! Player " + str(player.name) + " found the exit!", LogManager.CATEGORY_DUNGEON)
				break
	
	# Mark room as entered and update debug label
	room_entered = true
	_update_debug_label()
	
	# Check if this room has a puzzle (has blocking doors IN this room)
	# If this room has a puzzle, close the doors IN this room (blocking exits)
	# doors_in_room contains doors where room1 == this room OR blocking_room == this room (doors IN this room)
	for door in doors_in_room:
		if not is_instance_valid(door):
			continue
		
		# CRITICAL: Verify this door is actually IN this room
		# A door is IN a room if door.room1 == this room OR door.blocking_room == this room
		var door_room1 = door.room1 if door.room1 else {}
		var door_blocking_room = door.blocking_room if door.blocking_room else {}
		var door_in_this_room = false
		
		# Check if door.room1 matches this room (door starts FROM this room)
		if door_room1 and not door_room1.is_empty():
			door_in_this_room = (door_room1.x == room.x and door_room1.y == room.y and \
								door_room1.w == room.w and door_room1.h == room.h)
		
		# Also check blocking_room
		if not door_in_this_room and door_blocking_room and not door_blocking_room.is_empty():
			door_in_this_room = (door_blocking_room.x == room.x and door_blocking_room.y == room.y and \
								door_blocking_room.w == room.w and door_blocking_room.h == room.h)
		
		if not door_in_this_room:
			# Door is NOT in this room - DO NOT call it!
			var door_room1_x = str(door_room1.x) if door_room1 and not door_room1.is_empty() else "none"
			var door_room1_y = str(door_room1.y) if door_room1 and not door_room1.is_empty() else "none"
			var door_blocking_room_x = str(door_blocking_room.x) if door_blocking_room and not door_blocking_room.is_empty() else "none"
			var door_blocking_room_y = str(door_blocking_room.y) if door_blocking_room and not door_blocking_room.is_empty() else "none"
			LogManager.log_error("RoomTrigger: ERROR - Door " + str(door.name) + " is NOT in room (" + str(room.x) + ", " + str(room.y) + ")!", LogManager.CATEGORY_DUNGEON)
			LogManager.log("RoomTrigger:   Door room1: (" + door_room1_x + ", " + door_room1_y + ")", LogManager.CATEGORY_DUNGEON)
			LogManager.log("RoomTrigger:   Door blocking_room: (" + door_blocking_room_x + ", " + door_blocking_room_y + ")", LogManager.CATEGORY_DUNGEON)
			LogManager.log("RoomTrigger:   Removing from this trigger's doors list!", LogManager.CATEGORY_DUNGEON)
			doors_in_room.erase(door)
			if door.room_trigger_area == self:
				door.room_trigger_area = null
			continue
		
		# Door is in this room - verify it's connected to this trigger
		if door.room_trigger_area != self:
			door.room_trigger_area = self
		
		# Call the door's _on_room_entered to close it (if puzzle not solved)
		if door.has_method("_on_room_entered"):
			door._on_room_entered(player)
	
	# Spawn enemies if this room has a spawner
	LogManager.log("RoomTrigger: About to call _spawn_room_enemies()...", LogManager.CATEGORY_DUNGEON)
	_spawn_room_enemies()
	LogManager.log("RoomTrigger: Finished _spawn_room_enemies()", LogManager.CATEGORY_DUNGEON)

func _on_player_exited_room(player: Node):
	# Handle player leaving room
	LogManager.log("Player " + str(player.name) + " exited room at " + str(room.x) + ", " + str(room.y), LogManager.CATEGORY_DUNGEON)

func _find_room_entities():
	# Find all doors, enemies, and switches that belong to this room
	var game_world = get_tree().get_first_node_in_group("game_world")
	if not game_world:
		return
	
	var entities_node = game_world.get_node_or_null("Entities")
	if not entities_node:
		return
	
	# Find doors - search in Entities node
	# CRITICAL: Find doors where room1 == THIS room OR blocking_room == THIS room
	# Blocking doors are IN the puzzle room (they lead OUT OF this room)
	# When you enter this room, doors IN this room should close (blocking exits)
	LogManager.log("RoomTrigger: Finding doors for room (" + str(room.x) + ", " + str(room.y) + ", " + str(room.w) + "x" + str(room.h) + ")", LogManager.CATEGORY_DUNGEON)
	var _total_blocking_doors = 0
	for child in entities_node.get_children():
		if child.is_in_group("blocking_door") or child.name.begins_with("BlockingDoor_"):
			_total_blocking_doors += 1
			if not is_instance_valid(child):
				LogManager.log("RoomTrigger:   Door " + str(child.name) + " is invalid, skipping", LogManager.CATEGORY_DUNGEON)
				continue
			
			# Check if door is IN this room (room1 == this room OR blocking_room == this room)
			var door_in_this_room = false
			var door_room1 = child.room1 if child.room1 else {}
			var door_blocking_room = child.blocking_room if child.blocking_room else {}
			
			# CRITICAL: For blocking doors (StoneDoor/GateDoor), BOTH room1 AND blocking_room should match this room
			# For KeyDoors, only room1 needs to match
			var is_blocking_door = (child.type == "StoneDoor" or child.type == "GateDoor")
			
			# Check room1 first (door starts FROM this room)
			if door_room1 and not door_room1.is_empty():
				var room1_matches = (door_room1.x == room.x and door_room1.y == room.y and \
									door_room1.w == room.w and door_room1.h == room.h)
				if room1_matches:
					door_in_this_room = true
					LogManager.log("RoomTrigger:   Door " + str(child.name) + " room1 matches this room (door IN this room)", LogManager.CATEGORY_DUNGEON)
			
			# For blocking doors, also verify blocking_room matches (it should match room1)
			if door_in_this_room and is_blocking_door and door_blocking_room and not door_blocking_room.is_empty():
				var blocking_matches = (door_blocking_room.x == room.x and door_blocking_room.y == room.y and \
									   door_blocking_room.w == room.w and door_blocking_room.h == room.h)
				if not blocking_matches:
					# Blocking door's blocking_room doesn't match - this is an error!
					LogManager.log_error("RoomTrigger:   ERROR - Blocking door " + str(child.name) + " room1 matches but blocking_room (" + str(door_blocking_room.x) + ", " + str(door_blocking_room.y) + ") doesn't match this room (" + str(room.x) + ", " + str(room.y) + ")!", LogManager.CATEGORY_DUNGEON)
					door_in_this_room = false # Reject this door
				else:
					LogManager.log("RoomTrigger:   Blocking door " + str(child.name) + " blocking_room also matches this room (verified)", LogManager.CATEGORY_DUNGEON)
			
			# For non-blocking doors or if room1 didn't match, check blocking_room as fallback
			if not door_in_this_room and door_blocking_room and not door_blocking_room.is_empty():
				door_in_this_room = (door_blocking_room.x == room.x and door_blocking_room.y == room.y and \
									 door_blocking_room.w == room.w and door_blocking_room.h == room.h)
				if door_in_this_room:
					LogManager.log("RoomTrigger:   Door " + str(child.name) + " blocking_room matches this room (fallback check)", LogManager.CATEGORY_DUNGEON)
				else:
					var blocking_room_x = str(door_blocking_room.x) if door_blocking_room and not door_blocking_room.is_empty() else "none"
					var blocking_room_y = str(door_blocking_room.y) if door_blocking_room and not door_blocking_room.is_empty() else "none"
					LogManager.log("RoomTrigger:   Door " + str(child.name) + " blocking_room (" + blocking_room_x + ", " + blocking_room_y + ") doesn't match this room (" + str(room.x) + ", " + str(room.y) + ")", LogManager.CATEGORY_DUNGEON)
			
			if not door_room1 and not door_blocking_room:
				LogManager.log("RoomTrigger:   Door " + str(child.name) + " has no room1 or blocking_room set!", LogManager.CATEGORY_DUNGEON)
			
			if door_in_this_room:
				# This door is IN THIS room (blocks exits from this room) - add it to this trigger
				# CRITICAL: Check if door is already connected to a different trigger FIRST
				# This prevents doors from being connected to multiple triggers
				if child.room_trigger_area and child.room_trigger_area != self:
					# Door already connected to a different trigger - this is an ERROR!
					var other_trigger_room = child.room_trigger_area.room if child.room_trigger_area.room else {}
					var other_room_str = "(" + str(other_trigger_room.x if other_trigger_room else "none") + ", " + str(other_trigger_room.y if other_trigger_room else "none") + ")"
					var this_room_str = "(" + str(room.x) + ", " + str(room.y) + ")"
					
					# Debug: Print door's room info to understand why it's matching multiple rooms
					var door_room1_x_str = str(door_room1.x) if door_room1 and not door_room1.is_empty() else "none"
					var door_room1_y_str = str(door_room1.y) if door_room1 and not door_room1.is_empty() else "none"
					var door_blocking_room_x_str = str(door_blocking_room.x) if door_blocking_room and not door_blocking_room.is_empty() else "none"
					var door_blocking_room_y_str = str(door_blocking_room.y) if door_blocking_room and not door_blocking_room.is_empty() else "none"
					LogManager.log("RoomTrigger: WARNING - Door " + str(child.name) + " already connected to trigger for room " + other_room_str + "!", LogManager.CATEGORY_DUNGEON)
					LogManager.log("RoomTrigger:   Door room1: (" + door_room1_x_str + ", " + door_room1_y_str + ")", LogManager.CATEGORY_DUNGEON)
					LogManager.log("RoomTrigger:   Door blocking_room: (" + door_blocking_room_x_str + ", " + door_blocking_room_y_str + ")", LogManager.CATEGORY_DUNGEON)
					LogManager.log("RoomTrigger:   Current trigger room: " + this_room_str, LogManager.CATEGORY_DUNGEON)
					LogManager.log("RoomTrigger:   Skipping this door - it belongs to the other trigger!", LogManager.CATEGORY_DUNGEON)
					
					# Don't add to this trigger if already connected to another trigger
					if child in doors_in_room:
						doors_in_room.erase(child)
					continue # Skip this door entirely
				
				# Door is not connected to another trigger - safe to add
				# CRITICAL: Only add if not already in the list (avoid duplicates)
				if not child in doors_in_room:
					doors_in_room.append(child)
					LogManager.log("RoomTrigger: Added door " + str(child.name) + " that is IN room (" + str(room.x) + ", " + str(room.y) + ") to this trigger", LogManager.CATEGORY_DUNGEON)
				
				# Set door's room trigger reference (should be null at this point, but set it anyway)
				if not child.room_trigger_area:
					child.room_trigger_area = self
			else:
				# This door is NOT in this room - ensure it's not in this trigger's list
				# This prevents doors from being accidentally connected to wrong triggers
				if child in doors_in_room:
					LogManager.log("RoomTrigger: Removing door " + str(child.name) + " from this trigger - it's not in this room (" + str(room.x) + ", " + str(room.y) + ")", LogManager.CATEGORY_DUNGEON)
					doors_in_room.erase(child)
				if child.room_trigger_area == self:
					LogManager.log("RoomTrigger: Disconnecting door " + str(child.name) + " from this trigger - wrong room!", LogManager.CATEGORY_DUNGEON)
					child.room_trigger_area = null
	
	LogManager.log("RoomTrigger: Found " + str(doors_in_room.size()) + " doors for room (" + str(room.x) + ", " + str(room.y) + ")", LogManager.CATEGORY_DUNGEON)
	
	# Find enemies (only if room has enemies - skip for empty rooms to avoid unnecessary work)
	for child in entities_node.get_children():
		if child.is_in_group("enemy"):
			# Check if enemy is in this room
			if child.has_meta("room"):
				var enemy_room = child.get_meta("room")
				if enemy_room == room:
					enemies_in_room.append(child)
			else:
				# Check by position
				var tile_size = 16
				var enemy_tile_x = int(child.global_position.x / tile_size)
				var enemy_tile_y = int(child.global_position.y / tile_size)
				var room_min_x = room.x + 2
				var room_max_x = room.x + room.w - 2
				var room_min_y = room.y + 2
				var room_max_y = room.y + room.h - 2
				
				if enemy_tile_x >= room_min_x and enemy_tile_x < room_max_x and \
				   enemy_tile_y >= room_min_y and enemy_tile_y < room_max_y:
					enemies_in_room.append(child)
	
	# Find floor switches (search in Entities node, not all nodes in scene)
	# This is more efficient and avoids searching the entire scene tree
	for child in entities_node.get_children():
		if child.is_in_group("floor_switch") and is_instance_valid(child):
			# Check if switch is in this room
			var tile_size = 16
			var switch_tile_x = int(child.global_position.x / tile_size)
			var switch_tile_y = int(child.global_position.y / tile_size)
			var room_min_x = room.x + 2
			var room_max_x = room.x + room.w - 2
			var room_min_y = room.y + 2
			var room_max_y = room.y + room.h - 2
			
			if switch_tile_x >= room_min_x and switch_tile_x < room_max_x and \
			   switch_tile_y >= room_min_y and switch_tile_y < room_max_y:
				floor_switches_in_room.append(child)
	
	LogManager.log("RoomTrigger: Found " + str(enemies_in_room.size()) + " enemies and " + str(floor_switches_in_room.size()) + " switches for room (" + str(room.x) + ", " + str(room.y) + ")", LogManager.CATEGORY_DUNGEON)
	
	# Update debug label after finding all entities (skip if label not created yet)
	if debug_label:
		call_deferred("_update_debug_label")

func _spawn_room_enemies():
	LogManager.log("RoomTrigger: ===== _spawn_room_enemies() CALLED for room (" + str(room.x) + ", " + str(room.y) + ") =====", LogManager.CATEGORY_DUNGEON)
	
	# Spawn enemies when player enters room (if room has spawners and not already spawned)
	if enemies_spawned:
		LogManager.log("RoomTrigger: Already spawned enemies, skipping...", LogManager.CATEGORY_DUNGEON)
		return # Already spawned enemies
	
	# CRITICAL: Remove any existing smoke puffs before spawning new ones
	_cleanup_smoke_puffs()
	
	# Find enemy spawners for this room
	_find_room_spawners()
	
	LogManager.log("RoomTrigger: ===== Found " + str(enemy_spawners.size()) + " spawners for room (" + str(room.x) + ", " + str(room.y) + ") =====", LogManager.CATEGORY_DUNGEON)
	
	# Spawn enemies from all spawners in this room (only once)
	if enemy_spawners.size() > 0:
		for spawner in enemy_spawners:
			if not is_instance_valid(spawner):
				LogManager.log("RoomTrigger: WARNING - Invalid spawner found, skipping", LogManager.CATEGORY_DUNGEON)
				continue
			
			if not spawner.has_method("spawn_enemy"):
				LogManager.log("RoomTrigger: WARNING - Spawner " + str(spawner.name) + " doesn't have spawn_enemy method!", LogManager.CATEGORY_DUNGEON)
				continue
			
			# CRITICAL: Verify spawner has enemy scenes set
			if "enemy_scenes" in spawner:
				if spawner.enemy_scenes.size() == 0:
					LogManager.log_error("RoomTrigger: ERROR - Spawner " + str(spawner.name) + " has empty enemy_scenes array! Cannot spawn!", LogManager.CATEGORY_DUNGEON)
					continue
				else:
					LogManager.log("RoomTrigger: Spawner " + str(spawner.name) + " has " + str(spawner.enemy_scenes.size()) + " enemy scenes available", LogManager.CATEGORY_DUNGEON)
			else:
				LogManager.log_error("RoomTrigger: ERROR - Spawner " + str(spawner.name) + " has no enemy_scenes property!", LogManager.CATEGORY_DUNGEON)
				continue
			
			# CRITICAL: Verify spawner is on server (authority) - only server can spawn
			if multiplayer.has_multiplayer_peer() and not spawner.is_multiplayer_authority():
				LogManager.log("RoomTrigger: WARNING - Spawner " + str(spawner.name) + " is not multiplayer authority! Cannot spawn on client!", LogManager.CATEGORY_DUNGEON)
				continue
			
			LogManager.log("RoomTrigger: Calling spawn_enemy() on spawner " + str(spawner.name) + " at " + str(spawner.global_position), LogManager.CATEGORY_DUNGEON)
			# Spawn enemies from this spawner (spawner will handle max_enemies check)
			# NOTE: spawn_enemy() is async (uses await), so we don't await it here - it will execute asynchronously
			spawner.spawn_enemy()
		
		enemies_spawned = true
		LogManager.log("RoomTrigger: Called spawn_enemy() on " + str(enemy_spawners.size()) + " spawners in room at " + str(room.x) + ", " + str(room.y), LogManager.CATEGORY_DUNGEON)
		
		# Update debug label
		_update_debug_label()
		
		# Wait a bit for enemies to actually spawn (since spawn_enemy() waits for smoke puffs first)
		# Give it enough time for smoke puffs to finish (2.4s) plus a small buffer
		await get_tree().create_timer(3.0).timeout
		_find_room_entities() # Refresh enemy list after spawning completes
		_update_debug_label() # Update again after enemies spawn
	else:
		LogManager.log("RoomTrigger: No spawners found for room (" + str(room.x) + ", " + str(room.y) + ")", LogManager.CATEGORY_DUNGEON)
		_update_debug_label()

func _cleanup_smoke_puffs():
	# Remove all existing smoke puffs in the scene before spawning new ones
	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 not entities_node:
		entities_node = get_node_or_null("/root/GameWorld/Entities")
	
	if not entities_node:
		return
	
	# Find and remove all smoke puffs
	var smoke_puffs_removed = 0
	for child in entities_node.get_children():
		if child.is_in_group("smoke_puff") or child.name.begins_with("SmokePuff"):
			LogManager.log("RoomTrigger: Removing existing smoke puff: " + str(child.name), LogManager.CATEGORY_DUNGEON)
			child.queue_free()
			smoke_puffs_removed += 1
	
	if smoke_puffs_removed > 0:
		LogManager.log("RoomTrigger: Cleaned up " + str(smoke_puffs_removed) + " existing smoke puffs before spawning", LogManager.CATEGORY_DUNGEON)

func _find_room_spawners():
	# CRITICAL: Clear the list first to avoid accumulating old spawners
	enemy_spawners.clear()
	
	# Find enemy spawners in this room
	var game_world = get_tree().get_first_node_in_group("game_world")
	if not game_world:
		LogManager.log_error("RoomTrigger: ERROR - No game_world found when searching for spawners!", LogManager.CATEGORY_DUNGEON)
		return
	
	var entities_node = game_world.get_node_or_null("Entities")
	if not entities_node:
		LogManager.log_error("RoomTrigger: ERROR - No Entities node found when searching for spawners!", LogManager.CATEGORY_DUNGEON)
		return
	
	LogManager.log("RoomTrigger: ===== Searching for spawners in room (" + str(room.x) + ", " + str(room.y) + ", " + str(room.w) + "x" + str(room.h) + ") =====", LogManager.CATEGORY_DUNGEON)
	LogManager.log("RoomTrigger: Entities node has " + str(entities_node.get_child_count()) + " children", LogManager.CATEGORY_DUNGEON)
	
	# Search for spawners (they might be direct children of Entities or in a Spawners node)
	var found_spawners_count = 0
	for child in entities_node.get_children():
		if child.name.begins_with("EnemySpawner_") or child.is_in_group("enemy_spawner"):
			found_spawners_count += 1
			LogManager.log("RoomTrigger: Checking spawner: " + str(child.name) + " at " + str(child.global_position), LogManager.CATEGORY_DUNGEON)
			
			if not is_instance_valid(child):
				LogManager.log("RoomTrigger:   Spawner is invalid, skipping", LogManager.CATEGORY_DUNGEON)
				continue
			
			var spawner_in_room = false
			
			# First check if spawner has room metadata matching this room
			if child.has_meta("room"):
				var spawner_room = child.get_meta("room")
				var spawner_room_x_str = str(spawner_room.x) if spawner_room and not spawner_room.is_empty() else "none"
				var spawner_room_y_str = str(spawner_room.y) if spawner_room and not spawner_room.is_empty() else "none"
				LogManager.log("RoomTrigger:   Spawner has room metadata: (" + spawner_room_x_str + ", " + spawner_room_y_str + ")", LogManager.CATEGORY_DUNGEON)
				if spawner_room and not spawner_room.is_empty():
					# Compare rooms by position and size
					if spawner_room.x == room.x and spawner_room.y == room.y and \
					   spawner_room.w == room.w and spawner_room.h == room.h:
						spawner_in_room = true
						LogManager.log("RoomTrigger:   ✓ Spawner room matches this trigger room!", LogManager.CATEGORY_DUNGEON)
					else:
						LogManager.log("RoomTrigger:   ✗ Spawner room doesn't match - spawner: (" + str(spawner_room.x) + "," + str(spawner_room.y) + "," + str(spawner_room.w) + "x" + str(spawner_room.h) + "), trigger: (" + str(room.x) + "," + str(room.y) + "," + str(room.w) + "x" + str(room.h) + ")", LogManager.CATEGORY_DUNGEON)
			
			# Also check blocking_room metadata (fallback)
			if not spawner_in_room and child.has_meta("blocking_room"):
				var blocking_room = child.get_meta("blocking_room")
				var blocking_room_x_str = str(blocking_room.x) if blocking_room and not blocking_room.is_empty() else "none"
				var blocking_room_y_str = str(blocking_room.y) if blocking_room and not blocking_room.is_empty() else "none"
				LogManager.log("RoomTrigger:   Spawner has blocking_room metadata: (" + blocking_room_x_str + ", " + blocking_room_y_str + ")", LogManager.CATEGORY_DUNGEON)
				if blocking_room and not blocking_room.is_empty():
					# Compare rooms by position and size
					if blocking_room.x == room.x and blocking_room.y == room.y and \
					   blocking_room.w == room.w and blocking_room.h == room.h:
						spawner_in_room = true
						LogManager.log("RoomTrigger:   ✓ Spawner blocking_room matches this trigger room!", LogManager.CATEGORY_DUNGEON)
					else:
						LogManager.log("RoomTrigger:   ✗ Spawner blocking_room doesn't match - spawner: (" + str(blocking_room.x) + "," + str(blocking_room.y) + "," + str(blocking_room.w) + "x" + str(blocking_room.h) + "), trigger: (" + str(room.x) + "," + str(room.y) + "," + str(room.w) + "x" + str(room.h) + ")", LogManager.CATEGORY_DUNGEON)
			
			# Also check by position (fallback if no room metadata)
			if not spawner_in_room:
				var tile_size = 16
				var spawner_tile_x = int(child.global_position.x / tile_size)
				var spawner_tile_y = int(child.global_position.y / tile_size)
				var room_min_x = room.x + 2
				var room_max_x = room.x + room.w - 2
				var room_min_y = room.y + 2
				var room_max_y = room.y + room.h - 2
				
				LogManager.log("RoomTrigger:   Checking by position: spawner at tile (" + str(spawner_tile_x) + ", " + str(spawner_tile_y) + "), room bounds: (" + str(room_min_x) + "-" + str(room_max_x) + ", " + str(room_min_y) + "-" + str(room_max_y) + ")", LogManager.CATEGORY_DUNGEON)
				
				if spawner_tile_x >= room_min_x and spawner_tile_x < room_max_x and \
				   spawner_tile_y >= room_min_y and spawner_tile_y < room_max_y:
					spawner_in_room = true
					LogManager.log("RoomTrigger:   Spawner is within room bounds!", LogManager.CATEGORY_DUNGEON)
			
			if spawner_in_room and not child in enemy_spawners:
				enemy_spawners.append(child)
				LogManager.log("RoomTrigger: ✓ Added spawner " + str(child.name) + " to this room trigger", LogManager.CATEGORY_DUNGEON)
			elif spawner_in_room:
				LogManager.log("RoomTrigger:   Spawner already in list, skipping", LogManager.CATEGORY_DUNGEON)
			else:
				LogManager.log("RoomTrigger:   Spawner is NOT in this room, skipping", LogManager.CATEGORY_DUNGEON)
	
	LogManager.log("RoomTrigger: Total spawners found: " + str(found_spawners_count) + ", spawners in this room: " + str(enemy_spawners.size()), LogManager.CATEGORY_DUNGEON)
	
	# Update debug label after finding entities
	call_deferred("_update_debug_label")

func _create_debug_label():
	# Create a debug label to show puzzle type and trigger status above the room
	# Only create if debug mode is enabled
	var network_manager = get_node_or_null("/root/NetworkManager")
	if not network_manager:
		LogManager.log("RoomTrigger: NetworkManager not found, skipping debug label", LogManager.CATEGORY_DUNGEON)
		return
	if not network_manager.show_room_labels:
		LogManager.log("RoomTrigger: Debug mode not enabled (show_room_labels = false), skipping debug label for room (" + str(room.x) + ", " + str(room.y) + ")", LogManager.CATEGORY_DUNGEON)
		return
	
	LogManager.log("RoomTrigger: Creating debug label for room (" + str(room.x) + ", " + str(room.y) + ") - debug mode enabled", LogManager.CATEGORY_DUNGEON)
	
	# Skip if label already exists
	if debug_label and is_instance_valid(debug_label):
		return
	
	var label = Label.new()
	label.name = "DebugLabel"
	
	# Position label at center-top of the room (relative to Area2D)
	var tile_size = 16
	var room_world_w = (room.w - 4) * tile_size
	
	# Position at center of room, slightly above top edge
	label.position = Vector2(room_world_w / 2.0 - 100, -40) # Centered horizontally, 40px above
	label.size = Vector2(200, 50) # Wide and tall enough for text
	
	# Set high z-index to be above everything
	label.z_index = 1000
	
	# Enable autowrap so text doesn't overflow
	label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
	
	# Load standard_font.png as bitmap font (it's imported as FontFile resource)
	# Use try-catch-like approach - if font loading fails, just skip it
	# This prevents blocking the game if font resource has issues
	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:
			label.add_theme_font_override("font", standard_font_resource)
	
	# Always set font size
	label.add_theme_font_size_override("font_size", 8)
	
	# Style the label
	label.add_theme_color_override("font_color", Color.YELLOW)
	label.add_theme_color_override("font_shadow_color", Color.BLACK)
	label.add_theme_constant_override("shadow_offset_x", 1)
	label.add_theme_constant_override("shadow_offset_y", 1)
	label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
	label.vertical_alignment = VERTICAL_ALIGNMENT_TOP
	
	# Set initial text
	label.text = "Room (%d,%d)\nPuzzle: ...\nStatus: Not entered" % [room.x, room.y]
	
	debug_label = label
	add_child(label)
	
	# Update label after entities are found (deferred)
	call_deferred("_update_debug_label")

func _update_debug_label():
	# Update the debug label with current puzzle type and trigger status
	if not debug_label:
		return
	
	# Determine puzzle type from doors in this room
	var puzzle_type = "none"
	var puzzle_info = ""
	
	# Check doors to determine puzzle type
	for door in doors_in_room:
		if not is_instance_valid(door):
			continue
		
		# Check if door is a blocking door
		if door.has_method("_on_room_entered"):
			if "type" in door:
				if door.type == "KeyDoor":
					puzzle_type = "keydoor"
					puzzle_info = "KeyDoor"
					break # KeyDoor takes priority
				elif door.type == "StoneDoor" or door.type == "GateDoor":
					# Check what puzzle type this door requires
					# These are regular properties defined in door.gd (lines 35-36), so they should always exist
					# Access properties directly - they're defined as var in the class
					var door_requires_enemies = false
					var door_requires_switch = false
					
					# Access properties directly (they're defined in door.gd as var requires_enemies and requires_switch)
					# Since they're class properties, they should always exist, so just access them
					door_requires_enemies = door.requires_enemies
					door_requires_switch = door.requires_switch
					
					if door_requires_enemies:
						puzzle_type = "enemy"
						puzzle_info = "Enemy Spawner"
					elif door_requires_switch:
						# Check switch type by looking at connected switches
						var has_pillar_switch = false
						var has_walk_switch = false
						for switch in floor_switches_in_room:
							if is_instance_valid(switch):
								# switch_type is an exported property in floor_switch.gd, so it should always exist
								var switch_type_val = switch.switch_type
								if switch_type_val == "pillar":
									has_pillar_switch = true
								elif switch_type_val == "walk":
									has_walk_switch = true
						
						if has_pillar_switch:
							puzzle_type = "switch_pillar"
							puzzle_info = "Pillar Switch"
						elif has_walk_switch:
							puzzle_type = "switch_walk"
							puzzle_info = "Walk Switch"
						else:
							puzzle_type = "switch"
							puzzle_info = "Switch"
					else:
						# Door exists but no puzzle info - show door type
						if puzzle_type == "none":
							puzzle_type = door.type.to_lower()
							puzzle_info = door.type
	
	# Also check switches and spawners directly
	if floor_switches_in_room.size() > 0:
		for switch in floor_switches_in_room:
			if is_instance_valid(switch):
				# switch_type is an exported property in floor_switch.gd, so it should always exist
				var switch_type_val = switch.switch_type
				if switch_type_val == "pillar":
					puzzle_type = "switch_pillar"
					puzzle_info = "Pillar Switch"
					break
				elif switch_type_val == "walk":
					if puzzle_type != "switch_pillar": # Pillar takes priority
						puzzle_type = "switch_walk"
						puzzle_info = "Walk Switch"
	
	if enemy_spawners.size() > 0:
		if puzzle_type != "keydoor": # KeyDoor takes priority
			puzzle_type = "enemy"
			puzzle_info = "Enemy Spawner (%d)" % enemy_spawners.size()
	
	# Determine status
	var status_text = "ENTERED" if room_entered else "Not entered"
	if enemies_spawned:
		status_text += " | Spawned"
	
	# Update label text
	debug_label.text = "Room (%d,%d)\nPuzzle: %s\nStatus: %s" % [room.x, room.y, puzzle_info, status_text]
	
	# Color code based on puzzle type
	var color = Color.WHITE
	match puzzle_type:
		"enemy":
			color = Color.RED
		"switch_walk":
			color = Color.GREEN
		"switch_pillar":
			color = Color.CYAN
		"keydoor":
			color = Color.YELLOW
		_:
			color = Color.GRAY
	
	if room_entered:
		color = color.lerp(Color.WHITE, 0.3) # Make entered rooms brighter
	
	debug_label.add_theme_color_override("font_color", color)
	
	# Update label position to stay at center-top of room
	var tile_size = 16
	var room_world_w = (room.w - 4) * tile_size
	debug_label.position = Vector2(room_world_w / 2.0 - 100, -40)

func check_puzzle_state():
	# Check if room puzzle is solved (all enemies defeated or switches activated)
	# This is called by doors to check their state
	var all_enemies_defeated = true
	for enemy in enemies_in_room:
		if is_instance_valid(enemy) and not enemy.is_dead:
			all_enemies_defeated = false
			break
	
	var all_switches_activated = true
	for switch in floor_switches_in_room:
		if is_instance_valid(switch):
			# is_activated is a variable, not a method
			if not switch.is_activated:
				all_switches_activated = false
				break
	
	return all_enemies_defeated or all_switches_activated
