extends Node2D

# Frostspike spell — instant damage, no debuff. Frames 4413–4416, blue PointLight2D.
# If is_center: spawn center spike, then 0.5s later spawn 4 adjacent, then third-wave center (2x scale, 2x damage).

var player_owner: Node = null
var damage: float = 15.0
var damage_mult: float = 1.0
var is_center: bool = false
var skip_sfx: bool = false
var damage_dealt: bool = false
var elapsed: float = 0.0
var _frames: Array = [4413, 4414, 4415, 4416]

@onready var sprite: Sprite2D = $Sprite2D
@onready var spike_light: PointLight2D = $SpikeLight
@onready var hit_area: Area2D = $Area2D

func _ready() -> void:
	if spike_light:
		spike_light.color = Color(0.35, 0.6, 1.0)
		spike_light.energy = 1.0
		spike_light.enabled = true
	if sprite:
		sprite.frame = _frames[0]
		sprite.modulate = Color(0.6, 0.8, 1.0)
	if not skip_sfx and has_node("SfxSpike"):
		$SfxSpike.play()
	if is_center:
		_spawn_adjacent_after_delay()

func setup(target_pos: Vector2, owner_player: Node, damage_value: float, center: bool, scale_mult: float = 1.0, dmg_mult: float = 1.0, _skip_sfx: bool = false) -> void:
	global_position = target_pos
	player_owner = owner_player
	damage = damage_value
	damage_mult = dmg_mult
	is_center = center
	skip_sfx = _skip_sfx
	if scale_mult != 1.0:
		scale = Vector2(scale_mult, scale_mult)

func _spawn_adjacent_after_delay() -> void:
	await get_tree().create_timer(0.5).timeout
	if not is_instance_valid(self):
		return
	# Round 2: play spike SFX when the 4 adjacent spikes appear
	if has_node("SfxSpike"):
		$SfxSpike.play()
	var gw = get_tree().get_first_node_in_group("game_world")
	if not gw or not gw.has_method("_get_adjacent_valid_spell_tile_centers"):
		_finish_center_spike()
		return
	var player_pos = player_owner.global_position if player_owner else global_position
	var adjacent = gw._get_adjacent_valid_spell_tile_centers(global_position, player_pos)
	var scene = load("res://scenes/attack_spell_frostspike.tscn") as PackedScene
	if not scene:
		_finish_center_spike()
		return
	var par = get_parent()
	for pos in adjacent:
		var sp = scene.instantiate()
		sp.setup(pos, player_owner, damage, false, 1.0, 1.0, true)
		par.add_child(sp)
	# Wait for the 4 adjacent spikes to finish (0.25s), then spawn third-wave center
	await get_tree().create_timer(0.25).timeout
	if not is_instance_valid(self):
		return
	# Third wave: center again, 2x scale, 2x damage (most damage). Use skip_sfx=false so the
	# big spike plays SfxSpike in its _ready() — we can't play on self here because we're about to queue_free().
	var third = scene.instantiate()
	third.setup(global_position, player_owner, damage, false, 2.0, 2.0, false)
	par.add_child(third)
	_finish_center_spike()

func _finish_center_spike() -> void:
	if hit_area:
		hit_area.set_deferred("monitoring", false)
	queue_free()

func _process(delta: float) -> void:
	elapsed += delta
	if not damage_dealt and player_owner and player_owner.is_multiplayer_authority() and elapsed >= 0.05:
		_deal_damage_once()
		damage_dealt = true
	if sprite and _frames.size() > 0:
		var idx = min(int(elapsed / 0.05), _frames.size() - 1)
		sprite.frame = _frames[idx]
	# Non-center spikes: short lifetime. Center spike freed after spawning adjacent (in coroutine).
	if not is_center and elapsed >= 0.25:
		if hit_area:
			hit_area.set_deferred("monitoring", false)
		queue_free()

func _deal_damage_once() -> void:
	if not hit_area:
		return
	for body in hit_area.get_overlapping_bodies():
		if body == player_owner:
			continue
		var final_damage = damage * damage_mult
		if player_owner and player_owner.character_stats:
			var int_stat = player_owner.character_stats.baseStats.int + player_owner.character_stats.get_pass("int")
			final_damage += int_stat * 0.5
		var attacker_pos = player_owner.global_position if player_owner else global_position
		if body.is_in_group("player") and body.has_method("rpc_take_damage"):
			var pid = body.get_multiplayer_authority()
			if pid != 0:
				if multiplayer.get_unique_id() == pid:
					body.take_damage(final_damage, attacker_pos, false, false)
				else:
					body.rpc_take_damage.rpc_id(pid, final_damage, attacker_pos, false, false)
			else:
				body.rpc_take_damage.rpc(final_damage, attacker_pos, false, false)
		elif body.is_in_group("enemy") and body.has_method("rpc_take_damage"):
			var eid = body.get_multiplayer_authority()
			if eid != 0:
				if multiplayer.get_unique_id() == eid:
					body.take_damage(final_damage, attacker_pos, false, false, false)
				else:
					body.rpc_take_damage.rpc_id(eid, final_damage, attacker_pos, false, false, false)
			else:
				body.rpc_take_damage.rpc(final_damage, attacker_pos, false, false, false)
		elif body.has_method("can_be_destroyed") and body.can_be_destroyed() and body.has_method("take_damage"):
			body.take_damage(final_damage, attacker_pos)
