extends Node

enum State { IDLE, CHASE, ATTACK, RETURN }

func _physics_process(delta: float) -> void:
  _process_group(delta, EnemyData)
  _process_group(delta, BossData)

func _process_group(delta: float, data_source: Node) -> void:
  for entity in data_source.entities:
    if not is_instance_valid(entity) or not data_source.is_alive(entity):
      continue
    var data: Dictionary = data_source.entities[entity]
    if entity.is_in_group("invasion"):
      _force_invasion_target(entity, data)
    var state: int = data["state"]
    match state:
      State.IDLE:
        entity.velocity.x = 0
        entity.velocity.z = 0
      State.CHASE:
        _chase(entity, data, data_source)
      State.ATTACK:
        _attack(entity, data, data_source, delta)
      State.RETURN:
        _return_to_spawn(entity, data, data_source, delta)

func _force_invasion_target(entity: Node, data: Dictionary) -> void:
  var tavern: Node = get_tree().get_first_node_in_group("tavern")
  if not tavern:
    return
  data["target"] = tavern
  if data["state"] == State.IDLE or data["state"] == State.RETURN:
    data["state"] = State.CHASE

func _chase(entity: Node, data: Dictionary, data_source: Node) -> void:
  if not is_instance_valid(data["target"]):
    data["state"] = State.RETURN
    return
  var base: EnemyStats = data_source.get_base(entity)
  var attack_range: float = base.attack_range
  if data["target"].is_in_group("tavern"):
    attack_range += 3.0
  var dist: float = entity.global_position.distance_to(data["target"].global_position)
  if dist <= attack_range:
    data["state"] = State.ATTACK
    return
  var nav_agent: NavigationAgent3D = entity.get_node_or_null("NavigationAgent3D")
  if not nav_agent:
    return
  nav_agent.target_position = data["target"].global_position
  var next_pos := nav_agent.get_next_path_position()
  var direction: Vector3 = (next_pos - entity.global_position).normalized()
  direction.y = 0
  entity.velocity.x = direction.x * base.speed
  entity.velocity.z = direction.z * base.speed

func _attack(entity: Node, data: Dictionary, data_source: Node, delta: float) -> void:
  data["attack_timer"] -= delta
  if not is_instance_valid(data["target"]):
    data["state"] = State.RETURN
    return
  var base: EnemyStats = data_source.get_base(entity)
  var attack_range: float = base.attack_range
  if data["target"].is_in_group("tavern"):
    attack_range += 3.0
  var dist: float = entity.global_position.distance_to(data["target"].global_position)
  if dist > attack_range:
    data["state"] = State.CHASE
    return
  if data["attack_timer"] <= 0:
    data["attack_timer"] = base.attack_cooldown
    var scale: float = data.get("scale", 1.0)
    EventBus.damage_requested.emit(entity, data["target"], base.attack_damage * scale)
  entity.velocity.x = 0
  entity.velocity.z = 0

func _return_to_spawn(entity: Node, data: Dictionary, data_source: Node, delta: float) -> void:
  var spawn_pos: Vector3 = data["spawn_position"]
  var dist: float = entity.global_position.distance_to(spawn_pos)
  if dist < 1.0:
    data["state"] = State.IDLE
    entity.velocity.x = 0
    entity.velocity.z = 0
    return
  var base: EnemyStats = data_source.get_base(entity)
  var nav_agent: NavigationAgent3D = entity.get_node_or_null("NavigationAgent3D")
  if not nav_agent:
    return
  nav_agent.target_position = spawn_pos
  var next_pos := nav_agent.get_next_path_position()
  var direction: Vector3 = (next_pos - entity.global_position).normalized()
  direction.y = 0
  entity.velocity.x = direction.x * base.speed
  entity.velocity.z = direction.z * base.speed
  _regenerate(entity, data, data_source, delta)

func _regenerate(entity: Node, data: Dictionary, data_source: Node, delta: float) -> void:
  var health: float = data["health"]
  var max_health: float = data["max_health"]
  if health < max_health:
    var base: EnemyStats = data_source.get_base(entity)
    var rate: float = base.regen_fast
    if health >= max_health * 0.99:
      rate = base.regen_slow
    health = min(health + max_health * rate * delta, max_health)
    data_source.set_health(entity, health)
