extends CharacterBody3D
class_name BaseUnit

## Base class for all units (players, enemies, NPCs) in the game
## Provides common functionality like health management and taking damage

signal health_changed(old_health: float, new_health: float)
signal died(killer_id: int)
signal respawned()

@export var max_health: float = 100.0
@export var can_respawn: bool = true
@export var respawn_delay: float = 3.0

var current_health: float = 100.0
var is_dead: bool = false
var _respawn_point: Vector3 = Vector3.ZERO

func _ready():
	current_health = max_health
	_respawn_point = global_position

func _enter_tree():
	set_multiplayer_authority(str(name).to_int())

## Take damage from an attacker
## Should only be called on the server for authority
@rpc("any_peer", "reliable")
func take_damage(amount: float, attacker_id: int = -1):
	# Only server can process damage
	if not multiplayer.is_server():
		return

	if is_dead:
		return

	var old_health = current_health
	current_health = max(0, current_health - amount)

	# Broadcast health change to all clients
	rpc("sync_health", current_health)
	health_changed.emit(old_health, current_health)

	if current_health <= 0:
		_die(attacker_id)

## Heal the unit
@rpc("any_peer", "reliable")
func heal(amount: float):
	if not multiplayer.is_server():
		return

	if is_dead:
		return

	var old_health = current_health
	current_health = min(max_health, current_health + amount)

	rpc("sync_health", current_health)
	health_changed.emit(old_health, current_health)

## Sync health across all clients
@rpc("any_peer", "call_local", "reliable")
func sync_health(new_health: float):
	var old_health = current_health
	current_health = new_health
	health_changed.emit(old_health, current_health)

## Handle death
func _die(killer_id: int):
	if is_dead:
		return

	is_dead = true
	died.emit(killer_id)
	rpc("sync_death", killer_id)

	if can_respawn and multiplayer.is_server():
		await get_tree().create_timer(respawn_delay).timeout
		_respawn()

## Sync death state to all clients
@rpc("any_peer", "call_local", "reliable")
func sync_death(killer_id: int):
	is_dead = true
	died.emit(killer_id)
	# Subclasses should override to add visual effects, disable collision, etc.

## Respawn the unit
func _respawn():
	if not multiplayer.is_server():
		return

	is_dead = false
	current_health = max_health
	global_position = _respawn_point
	velocity = Vector3.ZERO

	rpc("sync_respawn", _respawn_point)
	respawned.emit()

## Sync respawn to all clients
@rpc("any_peer", "call_local", "reliable")
func sync_respawn(spawn_pos: Vector3):
	is_dead = false
	current_health = max_health
	global_position = spawn_pos
	velocity = Vector3.ZERO
	respawned.emit()

## Set the respawn point
func set_respawn_point(point: Vector3):
	_respawn_point = point

## Get health percentage (0.0 to 1.0)
func get_health_percent() -> float:
	return current_health / max_health if max_health > 0 else 0.0
