extends GdUnitTestSuite

const Resolver := preload("res://scripts/hotbar_cast_slot_resolver.gd")


func _eight_empty_slots() -> Array:
	var slots: Array = []
	slots.resize(8)
	for i in range(8):
		slots[i] = null
	return slots


func test_resolve_returns_ok_with_target_from_locked_target_id() -> void:
	# Arrange
	var slots := _eight_empty_slots()
	slots[0] = "prototype_pulse"
	var target_state := {"lockedTargetId": "prototype_target_alpha", "sequence": 3}

	# Act
	var outcome: Dictionary = Resolver.resolve(0, slots, target_state)

	# Assert
	assert_that(bool(outcome.get(Resolver.KEY_OK, false))).is_true()
	assert_that(int(outcome.get(Resolver.KEY_SLOT_INDEX, -1))).is_equal(0)
	assert_that(outcome.get(Resolver.KEY_ABILITY_ID)).is_equal("prototype_pulse")
	assert_that(outcome.get(Resolver.KEY_TARGET_ID)).is_equal("prototype_target_alpha")


func test_resolve_returns_null_target_when_no_lock() -> void:
	# Arrange
	var slots := _eight_empty_slots()
	slots[1] = "prototype_guard"
	var target_state := {"lockedTargetId": null, "validity": "none"}

	# Act
	var outcome: Dictionary = Resolver.resolve(1, slots, target_state)

	# Assert
	assert_that(bool(outcome.get(Resolver.KEY_OK, false))).is_true()
	assert_that(outcome.get(Resolver.KEY_TARGET_ID, "sentinel")).is_null()


func test_resolve_returns_null_target_when_lock_empty_string() -> void:
	# Arrange
	var slots := _eight_empty_slots()
	slots[2] = "prototype_dash"
	var target_state := {"lockedTargetId": ""}

	# Act
	var outcome: Dictionary = Resolver.resolve(2, slots, target_state)

	# Assert
	assert_that(bool(outcome.get(Resolver.KEY_OK, false))).is_true()
	assert_that(outcome.get(Resolver.KEY_TARGET_ID, "sentinel")).is_null()


func test_resolve_denies_empty_slot_without_ability() -> void:
	# Arrange
	var slots := _eight_empty_slots()
	slots[3] = null
	var target_state := {"lockedTargetId": "prototype_target_beta"}

	# Act
	var outcome: Dictionary = Resolver.resolve(3, slots, target_state)

	# Assert
	assert_that(bool(outcome.get(Resolver.KEY_OK, true))).is_false()
	assert_that(str(outcome.get(Resolver.KEY_REASON, ""))).is_equal(Resolver.REASON_EMPTY_SLOT)


func test_resolve_denies_empty_string_ability() -> void:
	# Arrange
	var slots := _eight_empty_slots()
	slots[4] = "   "
	var target_state := {}

	# Act
	var outcome: Dictionary = Resolver.resolve(4, slots, target_state)

	# Assert
	assert_that(bool(outcome.get(Resolver.KEY_OK, true))).is_false()
	assert_that(str(outcome.get(Resolver.KEY_REASON, ""))).is_equal(Resolver.REASON_EMPTY_SLOT)


func test_resolve_denies_slot_index_out_of_range() -> void:
	# Arrange
	var slots := _eight_empty_slots()
	slots[0] = "prototype_pulse"
	var target_state := {}

	# Act
	var high: Dictionary = Resolver.resolve(8, slots, target_state)
	var low: Dictionary = Resolver.resolve(-1, slots, target_state)

	# Assert
	assert_that(bool(high.get(Resolver.KEY_OK, true))).is_false()
	assert_that(str(high.get(Resolver.KEY_REASON, ""))).is_equal(Resolver.REASON_INVALID_SLOT)
	assert_that(bool(low.get(Resolver.KEY_OK, true))).is_false()
	assert_that(str(low.get(Resolver.KEY_REASON, ""))).is_equal(Resolver.REASON_INVALID_SLOT)
