extends RigidBody3D
class_name WorldWeapon

## Weapon as a physics object in the world
## Can be picked up by players
## Spawned when a weapon is dropped or placed in the level

@export var weapon_data: WeaponData

var weapon_id: int = -1  # Set by Level when spawned
var _mesh_instance: Node3D = null
var _collision_shape: CollisionShape3D = null
var _pickup_area: Area3D = null
var _is_being_picked_up: bool = false

func _ready():
	print("[WorldWeapon ", name, "] _ready() called. weapon_id=", weapon_id, ", weapon_data=", weapon_data)

	# Set collision layer to "weapon" (layer 3 = bit 4)
	collision_layer = 4
	collision_mask = 2  # Collide with world

	# Set up physics
	if weapon_data:
		mass = weapon_data.weight
		print("[WorldWeapon ", name, "] Set mass to ", mass)

	# Spawn mesh
	if weapon_data and weapon_data.mesh_scene:
		print("[WorldWeapon ", name, "] Spawning mesh from ", weapon_data.mesh_scene)
		_spawn_mesh()
	else:
		print("[WorldWeapon ", name, "] ERROR: Cannot spawn mesh. weapon_data=", weapon_data, ", mesh_scene=", weapon_data.mesh_scene if weapon_data else "null")

	# Create collision shape if not exists
	_setup_collision()

	# Create pickup area
	_setup_pickup_area()

	# Only server manages pickup logic
	if multiplayer.is_server():
		_pickup_area.body_entered.connect(_on_body_entered_pickup_area)

func _spawn_mesh():
	# Remove old mesh if exists
	if _mesh_instance:
		_mesh_instance.queue_free()

	# Instantiate mesh
	_mesh_instance = weapon_data.mesh_scene.instantiate()
	add_child(_mesh_instance)
	print("[WorldWeapon ", name, "] Mesh spawned successfully: ", _mesh_instance)

func _setup_collision():
	# Check if we already have a collision shape
	for child in get_children():
		if child is CollisionShape3D:
			_collision_shape = child
			return

	# Create a basic box collision if none exists
	_collision_shape = CollisionShape3D.new()
	var box_shape = BoxShape3D.new()
	box_shape.size = Vector3(0.5, 0.5, 1.5)  # Approximate weapon size
	_collision_shape.shape = box_shape
	add_child(_collision_shape)

func _setup_pickup_area():
	# Create Area3D for pickup detection
	_pickup_area = Area3D.new()
	_pickup_area.name = "PickupArea"
	_pickup_area.collision_layer = 4  # Layer 3 (weapon layer) so player can detect it
	_pickup_area.collision_mask = 1  # Detect players
	add_child(_pickup_area)

	# Create sphere collision for pickup range
	var pickup_collision = CollisionShape3D.new()
	var sphere = SphereShape3D.new()
	sphere.radius = weapon_data.pickup_radius if weapon_data else 1.5
	pickup_collision.shape = sphere
	_pickup_area.add_child(pickup_collision)

func _on_body_entered_pickup_area(body: Node3D):
	if _is_being_picked_up:
		return

	# Check if it's a player trying to pick up
	if body is Character and body.is_multiplayer_authority():
		# Let the player handle the pickup
		# The player will call try_pickup() via RPC
		pass

## Called by player to attempt pickup
@rpc("any_peer", "reliable")
func try_pickup(player_id: int):
	# Only server validates pickup
	if not multiplayer.is_server():
		return

	if _is_being_picked_up:
		return

	# Find the player
	var level = get_tree().get_current_scene()
	if not level or not level.has_node("PlayersContainer"):
		return

	var players_container = level.get_node("PlayersContainer")
	if not players_container.has_node(str(player_id)):
		return

	var player = players_container.get_node(str(player_id))
	if not player is Character:
		return

	# Check distance
	var distance = global_position.distance_to(player.global_position)
	if distance > (weapon_data.pickup_radius if weapon_data else 1.5):
		return

	_is_being_picked_up = true

	# Get the resource path
	var resource_path = weapon_data.resource_path
	if resource_path == "":
		push_error("WeaponData has no resource path!")
		return

	# Check weapon_id is valid
	if weapon_id == -1:
		push_error("WorldWeapon.try_pickup: weapon_id is -1! This weapon was not spawned correctly.")
		print("  Weapon name: ", name)
		print("  Weapon data: ", weapon_data.resource_path if weapon_data else "null")
		return

	# Tell the player to equip this weapon (on all clients)
	print("[Server] Telling player ", player_id, " to equip weapon via RPC")
	player.rpc("equip_weapon_from_world", resource_path)

	# Remove this world weapon from all clients using level's centralized system
	print("[Server] Removing world weapon ", name, " (ID: ", weapon_id, ") via level.remove_world_weapon")
	if level.has_method("remove_world_weapon"):
		level.remove_world_weapon(weapon_id)
	else:
		push_error("Level doesn't have remove_world_weapon method!")

## Remove weapon from all clients
@rpc("any_peer", "call_local", "reliable")
func _remove_from_all_clients():
	print("[Client ", multiplayer.get_unique_id(), "] Removing weapon ", name)
	# Delay removal to ensure RPC is fully processed
	await get_tree().process_frame
	queue_free()

## Set weapon data and refresh
func set_weapon_data(data: WeaponData):
	weapon_data = data
	if is_inside_tree():
		_spawn_mesh()
		if weapon_data:
			mass = weapon_data.weight
