# Player.gd
# Steuert den Spielercharakter: Bewegung, Kamera, HP, Angriff, Zielauswahl
extends CharacterBody3D

const SPEED = 5.0
const JUMP_VELOCITY = 4.5
const GRAVITY = 9.8

var max_hp = 100
var current_hp = 100
var target = null          # Aktuell markierter Gegner
var equipped_weapon = null # Ausgerüstete Waffe (null = unbewaffnet, Schaden = 1)

# Global Cooldown System (GCD)
var global_cooldown = 0.0
const GLOBAL_COOLDOWN_TIME = 1.5  # GCD in Sekunden
var autoattack_active = false  # Ob Autoattack nach GCD weiterlaufen soll

# Skills System - individuelle Cooldowns (zusätzlich zum GCD)
var heavy_strike_cooldown = 0.0
const HEAVY_STRIKE_DAMAGE_MIN = 10
const HEAVY_STRIKE_DAMAGE_MAX = 15
const HEAVY_STRIKE_COOLDOWN = 3.0
const HEAVY_STRIKE_RANGE = 2.0

@onready var camera_pivot = $CameraPivot
@onready var camera = $CameraPivot/Camera3D
@onready var hud = $HUD

func _ready():
	hud.update_health(current_hp, max_hp)
	hud.set_active_slot(0)
	# Icons für Skills setzen
	hud.set_slot_icon(0, "res://icons/autoattack_icon.svg")  # Slot 1: Autoattack
	hud.set_slot_icon(1, "res://icons/heavy_strike_icon.svg")  # Slot 2: Heavy Strike

	# HUD-Klicks verbinden
	hud.slot_clicked.connect(_on_slot_clicked)

# Handler für HUD-Slot-Klicks
func _on_slot_clicked(slot_index: int):
	match slot_index:
		0:  # Autoattack manuell starten
			if target != null and global_cooldown <= 0:
				start_autoattack()
				perform_autoattack()
		1:  # Heavy Strike
			use_heavy_strike()

# Schaden am Spieler abziehen und HP-Leiste aktualisieren
func take_damage(amount):
	current_hp = clamp(current_hp - amount, 0, max_hp)
	hud.update_health(current_hp, max_hp)
	if current_hp <= 0:
		die()

# HP heilen und HP-Leiste aktualisieren
func heal(amount):
	current_hp = clamp(current_hp + amount, 0, max_hp)
	hud.update_health(current_hp, max_hp)

func die():
	print("Spieler gestorben!")

# Schaden basierend auf ausgerüsteter Waffe (unbewaffnet = 1)
func get_attack_damage() -> int:
	if equipped_weapon == null:
		return 1
	return randi_range(equipped_weapon.min_damage, equipped_weapon.max_damage)

# Reichweite basierend auf ausgerüsteter Waffe (unbewaffnet = 1.5)
func get_attack_range() -> float:
	if equipped_weapon == null:
		return 1.5
	return equipped_weapon.range

# Angriffsgeschwindigkeit basierend auf ausgerüsteter Waffe (unbewaffnet = 1.5s)
func get_attack_cooldown() -> float:
	if equipped_weapon == null:
		return 1.5
	return equipped_weapon.attack_speed

# Ziel markieren — start_attack=true startet sofort die Autoattack
func set_target(new_target, start_attack: bool = false):
	if target != null and is_instance_valid(target):
		target.hide_health()
	target = new_target
	target.show_health()
	print("Ziel markiert: ", target.name)
	if start_attack:
		start_autoattack()

# Autoattack aktivieren
func start_autoattack():
	autoattack_active = true
	print("Autoattack aktiviert")

# Autoattack deaktivieren
func stop_autoattack():
	autoattack_active = false
	print("Autoattack deaktiviert")

# Führt einen Autoattack aus (wird vom GCD-System aufgerufen)
func perform_autoattack():
	if target == null or not is_instance_valid(target):
		target = null
		autoattack_active = false
		return

	var distance = global_position.distance_to(target.global_position)
	if distance <= get_attack_range():
		var dmg = get_attack_damage()
		target.take_damage(dmg)
		print("Autoattack: ", dmg, " Schaden")
		trigger_global_cooldown()
	else:
		print("Ziel zu weit entfernt für Autoattack")

# Global Cooldown auslösen
func trigger_global_cooldown():
	global_cooldown = GLOBAL_COOLDOWN_TIME

# Heavy Strike: Starker Angriff mit Cooldown
func use_heavy_strike():
	if target == null or not is_instance_valid(target):
		print("Kein Ziel für Heavy Strike!")
		return

	# GCD Check
	if global_cooldown > 0:
		print("Global Cooldown aktiv: ", "%.1f" % global_cooldown, "s")
		return

	# Skill-eigener Cooldown Check
	if heavy_strike_cooldown > 0:
		print("Heavy Strike noch im Cooldown: ", "%.1f" % heavy_strike_cooldown, "s")
		return

	var distance = global_position.distance_to(target.global_position)
	if distance > HEAVY_STRIKE_RANGE:
		print("Ziel zu weit entfernt für Heavy Strike!")
		return

	var damage = randi_range(HEAVY_STRIKE_DAMAGE_MIN, HEAVY_STRIKE_DAMAGE_MAX)
	target.take_damage(damage)
	heavy_strike_cooldown = HEAVY_STRIKE_COOLDOWN
	trigger_global_cooldown()
	start_autoattack()  # Autoattack nach Skill automatisch aktivieren
	print("Heavy Strike! ", damage, " Schaden")

# Raycast von der Kamera auf Mausposition — trifft Gegner mit take_damage()
func _try_select_target(start_attack: bool = false):
	var space_state = get_world_3d().direct_space_state
	var viewport = get_viewport()
	var mouse_pos = viewport.get_mouse_position()
	var ray_origin = camera.project_ray_origin(mouse_pos)
	var ray_end = ray_origin + camera.project_ray_normal(mouse_pos) * 100.0
	var query = PhysicsRayQueryParameters3D.create(ray_origin, ray_end)
	query.exclude = [self]
	var result = space_state.intersect_ray(query)
	if result and result.collider.has_method("take_damage"):
		set_target(result.collider, start_attack)

func _physics_process(delta):
	# Global Cooldown herunterzählen
	var gcd_was_active = global_cooldown > 0
	if global_cooldown > 0:
		global_cooldown -= delta

	# Wenn GCD gerade abgelaufen ist und Autoattack aktiv, führe Autoattack aus
	if gcd_was_active and global_cooldown <= 0 and autoattack_active:
		perform_autoattack()

	# Skill-Cooldowns herunterzählen
	if heavy_strike_cooldown > 0:
		heavy_strike_cooldown -= delta

	# HUD Cooldowns aktualisieren
	hud.set_slot_cooldown(0, global_cooldown)  # Slot 1: GCD für Autoattack
	hud.set_slot_cooldown(1, max(global_cooldown, heavy_strike_cooldown))  # Slot 2: max(GCD, Skill-CD)

	# Schwerkraft
	if not is_on_floor():
		velocity.y -= GRAVITY * delta

	# Springen
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY

	# Linksklick: nur markieren
	if Input.is_action_just_pressed("select_target"):
		_try_select_target(false)

	# Rechtsklick: markieren + angreifen
	if Input.is_action_just_pressed("ui_right_mouse"):
		_try_select_target(true)

	# Aktionsleiste 1-9
	if Input.is_action_just_pressed("action_1"):
		hud.set_active_slot(0)
		if target != null and global_cooldown <= 0:
			start_autoattack()
			perform_autoattack()
	if Input.is_action_just_pressed("action_2"):
		hud.set_active_slot(1)
		use_heavy_strike()
	if Input.is_action_just_pressed("action_3"):
		hud.set_active_slot(2)
	if Input.is_action_just_pressed("action_4"):
		hud.set_active_slot(3)
	if Input.is_action_just_pressed("action_5"):
		hud.set_active_slot(4)
	if Input.is_action_just_pressed("action_6"):
		hud.set_active_slot(5)
	if Input.is_action_just_pressed("action_7"):
		hud.set_active_slot(6)
	if Input.is_action_just_pressed("action_8"):
		hud.set_active_slot(7)
	if Input.is_action_just_pressed("action_9"):
		hud.set_active_slot(8)

	# TEST: T drücken = 10 Schaden
	if Input.is_action_just_pressed("test_damage"):
		take_damage(10)

	# Eingabe
	var input_dir = Vector2.ZERO
	if Input.is_action_pressed("move_forward"):
		input_dir.y -= 1
	if Input.is_action_pressed("move_back"):
		input_dir.y += 1
	if Input.is_action_pressed("move_left"):
		input_dir.x -= 1
	if Input.is_action_pressed("move_right"):
		input_dir.x += 1

	# Bewegung relativ zur Kamera
	var world_yaw = rotation.y + camera_pivot.rotation.y
	var forward = Vector3(-sin(world_yaw), 0, -cos(world_yaw)).normalized()
	var right = Vector3(cos(world_yaw), 0, -sin(world_yaw)).normalized()
	var direction = (forward * -input_dir.y + right * input_dir.x)

	velocity.x = direction.x * SPEED
	velocity.z = direction.z * SPEED

	# RMB gehalten: Spieler schaut in Kamerarichtung
	if Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT):
		rotation.y = world_yaw
		camera_pivot.rotation.y = 0

	move_and_slide()
