extends CharacterBody3D

@export var move_speed := 7.0
@export var acceleration := 18.0
@export var rotation_speed := 12.0
@export var camera_rig: Node3D

@export var simulation_manager: Node

@export var pantry_marker: Marker3D
@export var guard_zone: Marker3D
@export var study_zone: Marker3D

@export var stomach_capacity_for_food := 5
@export var interaction_range := 3.0


func _physics_process(delta: float) -> void:
	var input := Input.get_vector("move_left", "move_right", "move_forward", "move_backward")

	var forward := -camera_rig.global_transform.basis.z
	var right := camera_rig.global_transform.basis.x

	forward.y = 0
	right.y = 0

	forward = forward.normalized()
	right = right.normalized()

	var direction := (right * input.x + forward * -input.y).normalized()

	var target_velocity := direction * move_speed

	velocity.x = move_toward(velocity.x, target_velocity.x, acceleration * delta)
	velocity.z = move_toward(velocity.z, target_velocity.z, acceleration * delta)

	if not is_on_floor():
		velocity.y -= 30.0 * delta
	else:
		velocity.y = 0.0

	move_and_slide()

	if direction.length() > 0.01:
		var target_angle := atan2(direction.x, direction.z)
		rotation.y = lerp_angle(rotation.y, target_angle, rotation_speed * delta)


func _unhandled_input(event: InputEvent) -> void:
	# keep your camera mouse code here too
	if event.is_action_pressed("interact"):
		try_interact()


func try_interact() -> void:
	if simulation_manager == null:
		return

	if try_harvest_resource_node():
		return

	if is_near(guard_zone):
		simulation_manager.add_safety(3.0)
		print("Player helped guard the village.")
	elif is_near(study_zone):
		simulation_manager.add_knowledge(2.0)
		print("Player shared knowledge.")
	elif is_near(pantry_marker):
		simulation_manager.eat_food(stomach_capacity_for_food)
		print("Player ate food from the village supply.")


func try_harvest_resource_node() -> bool:
	if not simulation_manager.has_method("find_resource_node_for_player"):
		push_error("Player: SimulationManager cannot find ResourceNodes")
		return false
	var node: ResourceNode = simulation_manager.find_resource_node_for_player(
		global_position, interaction_range
	)
	if node == null:
		return false

	if not node.is_enabled():
		print("%s is unavailable." % node.node_id)
		return true

	if node.is_depleted():
		print("%s is depleted." % node.node_id)
		return true

	if not simulation_manager.has_method("harvest_resource_node"):
		push_error("Player: SimulationManager cannot harvest ResourceNodes")
		return true

	var extracted: float = simulation_manager.harvest_resource_node(node)
	if extracted > 0.0:
		print("Player gathered %s %s from %s." % [extracted, node.resource_id, node.node_id])
	else:
		print("%s could not be harvested." % node.node_id)
	return true


func is_near(zone: Marker3D) -> bool:
	if zone == null:
		return false

	return global_position.distance_to(zone.global_position) <= interaction_range
