extends Node

enum Role { TANK, DAMAGE, HEALER }

# Basis (aus Resource geladen)
var base: PlayerStats
var speed := 5.0
var jump_velocity := 4.5
var target_range := 20.0
var combat_timeout := 3.0
var respawn_time := 3.0
var gcd_time := 0.5
var aa_cooldown := 0.5

# Laufzeit
var health := 100.0
var max_health := 100.0
var health_regen := 0.0
var shield := 0.0
var max_shield := 0.0
var shield_regen_delay := 3.0
var shield_regen_time := 5.0
var shield_regen_timer := 0.0
var alive := true

# Buffs
var buff_damage := 1.0
var buff_heal := 1.0
var buff_shield := 1.0

# Level / XP
const XP_PER_LEVEL: int = 50
var level: int = 1
var xp: int = 0
var xp_to_next: int = XP_PER_LEVEL
var level_scale: float = 1.0

# Rolle
var current_role: int = Role.DAMAGE
var ability_set: AbilitySet = null

# Kampf
var target: Node3D = null
var in_combat := false
var combat_timer := 0.0

# Cooldowns
var cooldowns: Array[float] = []
var max_cooldowns: Array[float] = []
var gcd := 0.0
var aa_timer := 0.0

# Szenenwechsel
var portal_position := Vector3.ZERO
var returning_from_dungeon := false
var dungeon_cleared := false

# Cache für Szenenwechsel
var _cache: Dictionary = {}

func init_from_resource(res: PlayerStats) -> void:
  base = res
  speed = res.speed
  jump_velocity = res.jump_velocity
  target_range = res.target_range
  combat_timeout = res.combat_timeout
  respawn_time = res.respawn_time
  gcd_time = res.gcd_time
  aa_cooldown = res.aa_cooldown
  if _cache.is_empty():
    max_health = res.max_health * level_scale
    health = max_health
    health_regen = res.health_regen * level_scale
    max_shield = res.max_shield * level_scale
    shield = max_shield
    shield_regen_delay = res.shield_regen_delay
    shield_regen_time = res.shield_regen_time
    shield_regen_timer = 0.0
    alive = true
    buff_damage = 1.0
    buff_heal = 1.0
    buff_shield = 1.0
  else:
    _restore_cache()
  cooldowns.resize(5)
  cooldowns.fill(0.0)
  max_cooldowns.resize(5)
  max_cooldowns.fill(0.0)
  gcd = 0.0
  aa_timer = 0.0

func set_health(value: float) -> void:
  health = value
  EventBus.health_changed.emit(self, health, max_health)
  if health <= 0 and alive:
    alive = false
    EventBus.entity_died.emit(self)

func set_shield(value: float) -> void:
  shield = value
  EventBus.shield_changed.emit(self, shield, max_shield)

func set_role(role: int) -> void:
  current_role = role
  EventBus.role_changed.emit(self, current_role)

func set_target(new_target: Node3D) -> void:
  target = new_target
  EventBus.target_changed.emit(self, target)

func respawn() -> void:
  health = max_health
  shield = max_shield
  alive = true
  EventBus.health_changed.emit(self, health, max_health)
  EventBus.shield_changed.emit(self, shield, max_shield)
  EventBus.player_respawned.emit(self)

func save_cache() -> void:
  _cache = {
    "health": health,
    "max_health": max_health,
    "health_regen": health_regen,
    "shield": shield,
    "max_shield": max_shield,
    "shield_regen_delay": shield_regen_delay,
    "shield_regen_time": shield_regen_time,
    "alive": alive,
    "buff_damage": buff_damage,
    "buff_heal": buff_heal,
    "buff_shield": buff_shield,
  }

func clear_cache() -> void:
  _cache.clear()
  portal_position = Vector3.ZERO
  returning_from_dungeon = false
  dungeon_cleared = false

func reset_run() -> void:
  clear_cache()
  level = 1
  xp = 0
  xp_to_next = XP_PER_LEVEL
  level_scale = 1.0

func add_xp(amount: int) -> void:
  xp += amount
  EventBus.xp_gained.emit(self, amount)
  while xp >= xp_to_next:
    xp -= xp_to_next
    level_up()

func level_up() -> void:
  level += 1
  level_scale = float(_fibonacci(level))
  xp_to_next = XP_PER_LEVEL * _fibonacci(level)
  if base:
    max_health = base.max_health * level_scale
    max_shield = base.max_shield * level_scale
  else:
    max_health = 100.0 * level_scale
    max_shield = 50.0 * level_scale
  health = max_health
  shield = max_shield
  EventBus.health_changed.emit(self, health, max_health)
  EventBus.shield_changed.emit(self, shield, max_shield)
  EventBus.level_up.emit(self, level)

func _fibonacci(n: int) -> int:
  if n <= 1:
    return 1
  if n == 2:
    return 2
  var a := 1
  var b := 2
  for i in range(3, n + 1):
    var c := a + b
    a = b
    b = c
  return b

func _restore_cache() -> void:
  health = _cache.get("health", max_health)
  max_health = _cache.get("max_health", max_health)
  health_regen = _cache.get("health_regen", 0.0)
  shield = _cache.get("shield", 0.0)
  max_shield = _cache.get("max_shield", 0.0)
  shield_regen_delay = _cache.get("shield_regen_delay", 3.0)
  shield_regen_time = _cache.get("shield_regen_time", 5.0)
  alive = _cache.get("alive", true)
  buff_damage = _cache.get("buff_damage", 1.0)
  buff_heal = _cache.get("buff_heal", 1.0)
  buff_shield = _cache.get("buff_shield", 1.0)
  _cache.clear()
