# Idle-support stability tests for res://scripts/player.gd (static helpers).
extends GdUnitTestSuite

const PLAYER_SCRIPT: Script = preload("res://scripts/player.gd")


func test_idle_support_is_stable_on_flat_floor_without_wall_contacts() -> void:
	# Arrange
	var slide_normals: Array[Vector3] = [Vector3.UP]
	# Act
	var stable: bool = PLAYER_SCRIPT.idle_support_is_stable(true, Vector3.UP, slide_normals, 0)
	# Assert
	assert_that(stable).is_true()


func test_idle_support_is_stable_false_when_floor_is_not_flat_enough() -> void:
	# Arrange
	var slide_normals: Array[Vector3] = [Vector3.UP]
	# Must be steeper than [member STABLE_IDLE_FLOOR_MIN_UP_DOT] (0.998) *and* below
	# [member IDLE_SLOPE_STABLE_MIN_UP_DOT] (0.88), or the ramp short-circuit treats support as stable.
	var tilted_floor: Vector3 = Vector3(0.5, 0.82, 0.0).normalized()
	# Act
	var stable: bool = PLAYER_SCRIPT.idle_support_is_stable(true, tilted_floor, slide_normals, 0)
	# Assert
	assert_that(tilted_floor.dot(Vector3.UP)).is_less(
		PLAYER_SCRIPT.get("IDLE_SLOPE_STABLE_MIN_UP_DOT")
	)
	assert_that(stable).is_false()


func test_idle_support_is_stable_min_flat_up_dot_parameter() -> void:
	# Arrange
	var slide_normals: Array[Vector3] = [Vector3.UP]
	var floor_n: Vector3 = Vector3(0.05, 0.99875, 0.0).normalized()
	# Act
	var strict: bool = PLAYER_SCRIPT.idle_support_is_stable(true, floor_n, slide_normals, 0, 0.999)
	var holdish: bool = PLAYER_SCRIPT.idle_support_is_stable(true, floor_n, slide_normals, 0, 0.992)
	# Assert
	assert_that(strict).is_false()
	assert_that(holdish).is_true()


func test_idle_support_is_stable_true_when_flat_floor_has_extra_contacts() -> void:
	# Arrange
	var slide_normals: Array[Vector3] = [Vector3.UP, Vector3(0.0, 0.6, 0.8).normalized()]
	# Act
	var stable: bool = PLAYER_SCRIPT.idle_support_is_stable(true, Vector3.UP, slide_normals, 0)
	# Assert
	assert_that(stable).is_true()


func test_idle_support_is_stable_true_when_loose_ticks_and_ridged_but_floor_still_level() -> void:
	# Arrange
	var slide_normals: Array[Vector3] = [Vector3.UP, Vector3(1.0, 0.0, 0.0)]
	# Act
	var stable: bool = PLAYER_SCRIPT.idle_support_is_stable(true, Vector3.UP, slide_normals, 12)
	# Assert
	assert_that(stable).is_true()


func test_idle_support_is_stable_false_when_loose_ticks_and_ridged_and_shallow_floor() -> void:
	# Arrange
	var slide_normals: Array[Vector3] = [Vector3.UP, Vector3(1.0, 0.0, 0.0)]
	# Normal must be outside the ramp-stable band [IDLE_SLOPE_STABLE_MIN_UP_DOT, IDLE_RIM) or
	# `idle_ridged_stair_lip_only` is false and the ramp short-circuit returns stable. Use a tread
	# tilt above the rim dot but still below the ridged hold threshold (0.992).
	var floor_n: Vector3 = Vector3(0.14, 0.98, 0.0).normalized()
	# Act
	var stable: bool = PLAYER_SCRIPT.idle_support_is_stable(true, floor_n, slide_normals, 12)
	# Assert
	var up_dot: float = floor_n.dot(Vector3.UP)
	assert_that(up_dot).is_greater_equal(PLAYER_SCRIPT.get("IDLE_RIM_MIN_FLOOR_UP_DOT") as float)
	assert_that(up_dot).is_less(PLAYER_SCRIPT.get("STABLE_IDLE_FLOOR_MIN_UP_DOT") as float)
	assert_that(stable).is_false()


func test_idle_support_is_stable_true_when_loose_ticks_but_flat_open_support() -> void:
	# Arrange
	var slide_normals: Array[Vector3] = [Vector3.UP]
	# Act
	var stable: bool = PLAYER_SCRIPT.idle_support_is_stable(true, Vector3.UP, slide_normals, 12)
	# Assert
	assert_that(stable).is_true()


func test_idle_support_is_stable_true_when_loose_ticks_and_shallow_seam_not_ridged() -> void:
	# Arrange
	var n2: Vector3 = Vector3(0.0, 0.42, sqrt(1.0 - 0.42 * 0.42)).normalized()
	var slide_normals: Array[Vector3] = [Vector3.UP, n2]
	# Act
	var stable: bool = PLAYER_SCRIPT.idle_support_is_stable(true, Vector3.UP, slide_normals, 12)
	# Assert
	assert_that(stable).is_true()


func test_idle_support_is_stable_false_when_not_on_floor() -> void:
	# Arrange
	var slide_normals: Array[Vector3] = [Vector3.UP]
	# Act
	var stable: bool = PLAYER_SCRIPT.idle_support_is_stable(false, Vector3.UP, slide_normals, 0)
	# Assert
	assert_that(stable).is_false()
