## Tests for RoomNavigator — floor/room state and camera navigation logic.
extends GutTest

const RoomNavigatorScript: GDScript = preload("res://scripts/systems/room_navigator.gd")

var _nav: Node
var _camera: Camera2D


func before_each() -> void:
	_nav = RoomNavigatorScript.new()
	add_child_autofree(_nav)
	_camera = Camera2D.new()
	add_child_autofree(_camera)
	_nav.initialize(_camera)


func test_initial_floor_is_zero() -> void:
	assert_eq(_nav.get_current_floor(), 0)


func test_initial_room_is_zero() -> void:
	assert_eq(_nav.get_current_room(), 0)


func test_go_to_room_updates_floor() -> void:
	_nav.go_to_room(1, 2)
	assert_eq(_nav.get_current_floor(), 1)


func test_go_to_room_updates_room() -> void:
	_nav.go_to_room(1, 2)
	assert_eq(_nav.get_current_room(), 2)


func test_go_to_room_same_position_when_already_there_is_noop() -> void:
	_nav.go_to_room(1, 2)
	var camera_pos: Vector2 = _camera.position
	_nav.go_to_room(1, 2)
	assert_eq(_camera.position, camera_pos)


func test_go_to_floor_navigates_to_room_zero() -> void:
	_nav.go_to_floor(2)
	assert_eq(_nav.get_current_floor(), 2)
	assert_eq(_nav.get_current_room(), 0)


func test_go_to_room_emits_room_changed_signal() -> void:
	watch_signals(_nav)
	_nav.go_to_room(1, 2)
	await wait_for_signal(_nav.room_changed, 1.0)
	assert_signal_emitted(_nav, "room_changed")


func test_go_to_room_emits_room_changed_with_correct_parameters() -> void:
	watch_signals(_nav)
	_nav.go_to_room(1, 2)
	await wait_for_signal(_nav.room_changed, 1.0)
	assert_signal_emitted_with_parameters(_nav, "room_changed", [1, 2])


func test_go_to_room_moves_camera_to_target_position() -> void:
	_nav.go_to_room(0, 0)
	_camera.position = Vector2.ZERO
	_nav.go_to_room(1, 0)
	await wait_for_signal(_nav.room_changed, 1.0)
	assert_eq(_camera.position, Vector2(640.0, -360.0))


func test_go_to_floor_does_not_emit_if_already_on_floor_room_zero() -> void:
	watch_signals(_nav)
	_nav.go_to_floor(0)
	assert_signal_not_emitted(_nav, "room_changed")


func test_initialize_with_null_camera_still_updates_state() -> void:
	var nav: Node = RoomNavigatorScript.new()
	add_child_autofree(nav)
	nav.initialize(null)
	nav.go_to_room(1, 2)
	assert_eq(nav.get_current_floor(), 1)
	assert_eq(nav.get_current_room(), 2)


func test_multiple_room_changes_update_state() -> void:
	_nav.go_to_room(0, 1)
	_nav.go_to_room(1, 0)
	_nav.go_to_room(2, 3)
	assert_eq(_nav.get_current_floor(), 2)
	assert_eq(_nav.get_current_room(), 3)


func test_is_at_home_starts_false() -> void:
	assert_false(_nav.is_at_home())


func test_go_to_home_sets_is_at_home_true() -> void:
	_nav.go_to_home()
	assert_true(_nav.is_at_home())


func test_go_to_home_twice_is_noop_on_second_call() -> void:
	_nav.go_to_home()
	var camera_pos: Vector2 = _camera.position
	_nav.go_to_home()
	assert_eq(_camera.position, camera_pos)


func test_go_to_hospital_clears_is_at_home() -> void:
	_nav.go_to_home()
	_nav.go_to_hospital()
	assert_false(_nav.is_at_home())


func test_go_to_hospital_restores_last_floor() -> void:
	_nav.go_to_room(1, 2)
	_nav.go_to_home()
	_nav.go_to_hospital()
	assert_eq(_nav.get_current_floor(), 1)


func test_go_to_hospital_restores_last_room() -> void:
	_nav.go_to_room(1, 2)
	_nav.go_to_home()
	_nav.go_to_hospital()
	assert_eq(_nav.get_current_room(), 2)


func test_go_to_hospital_when_not_at_home_is_noop() -> void:
	_nav.go_to_room(1, 2)
	var camera_pos: Vector2 = _camera.position
	_nav.go_to_hospital()
	assert_eq(_camera.position, camera_pos)


func test_go_to_room_after_home_clears_is_at_home() -> void:
	_nav.go_to_home()
	_nav.go_to_room(0, 0)
	assert_false(_nav.is_at_home())


func test_room_names_dict_has_eleven_entries() -> void:
	assert_eq(RoomNavigator._ROOM_NAMES.size(), 11)


func test_get_room_name_floor0_room0_is_reception() -> void:
	assert_eq(RoomNavigator.get_room_name(0, 0), "reception")


func test_get_room_name_floor0_room3_is_emergency() -> void:
	assert_eq(RoomNavigator.get_room_name(0, 3), "emergency")


func test_get_room_name_floor1_room2_is_lab() -> void:
	assert_eq(RoomNavigator.get_room_name(1, 2), "lab")


func test_get_room_name_floor2_room1_is_delivery_room() -> void:
	assert_eq(RoomNavigator.get_room_name(2, 1), "delivery_room")


func test_get_room_name_unknown_returns_empty_string() -> void:
	assert_eq(RoomNavigator.get_room_name(99, 0), "")
	assert_eq(RoomNavigator.get_room_name(0, 99), "")


func test_go_to_room_by_name_garden_party_sets_is_at_home() -> void:
	RoomNavigator.go_to_room_by_name("garden_party")
	assert_true(RoomNavigator.is_at_home())
	RoomNavigator._is_at_home = false


func test_go_to_room_by_name_unknown_is_noop() -> void:
	var floor_before: int = RoomNavigator.get_current_floor()
	RoomNavigator.go_to_room_by_name("nonexistent_room_xyz")
	assert_eq(RoomNavigator.get_current_floor(), floor_before)
