## VFXManager — 视觉特效管理（Autoload: VFXManager）
## S4：程序化色块占位特效 + 对象池（P6-N72 one_shot=true）
extends Node2D

const MAX_ACTIVE_VFX: int = 200

var _vfx_pool:    Dictionary = {}  # { effect_id: Array[Node2D] }
var _active_count: int = 0

func _ready() -> void:
	EventBus.subscribe(EventID.STATUS_APPLIED, _on_status_applied)

func play(effect_id: String, world_pos: Vector2, override_scale: float = 1.0) -> void:
	if _active_count >= MAX_ACTIVE_VFX:
		return
	var node: Node2D = _pool_pop(effect_id)
	node.global_position = world_pos
	node.scale = Vector2.ONE * override_scale
	node.visible = true
	_active_count += 1
	# 触发一次性粒子爆发
	var p: GPUParticles2D = node.get_node_or_null("Particles")
	if p:
		p.restart()
		p.emitting = true
	var timer: Timer = node.get_node_or_null("AutoReturn")
	if timer:
		timer.start()

func _pool_pop(effect_id: String) -> Node2D:
	if _vfx_pool.has(effect_id) and not _vfx_pool[effect_id].is_empty():
		return _vfx_pool[effect_id].pop_back()
	return _instantiate_vfx(effect_id)

func _pool_return(effect_id: String, node: Node2D) -> void:
	node.visible = false
	_active_count = max(0, _active_count - 1)
	if not _vfx_pool.has(effect_id):
		_vfx_pool[effect_id] = []
	_vfx_pool[effect_id].append(node)

func _instantiate_vfx(effect_id: String) -> Node2D:
	# 程序化美术占位：GPUParticles2D 爆裂粒子（放 scenes/vfx/<id>.tscn 可整体替换）
	var node := Node2D.new()
	node.name = "VFX_" + effect_id
	var col: Color = _color_for(effect_id)
	var p := GPUParticles2D.new()
	p.name = "Particles"
	p.amount = _amount_for(effect_id)
	p.lifetime = 0.45
	p.one_shot = true              # P6-N72
	p.explosiveness = 0.9          # 一次性爆发
	p.local_coords = false
	var mat := ParticleProcessMaterial.new()
	mat.emission_shape = ParticleProcessMaterial.EMISSION_SHAPE_SPHERE
	mat.emission_sphere_radius = 4.0
	mat.direction = Vector3(0, 0, 0)
	mat.spread = 180.0
	mat.gravity = Vector3(0, 0, 0)
	mat.initial_velocity_min = _speed_for(effect_id) * 0.5
	mat.initial_velocity_max = _speed_for(effect_id)
	mat.scale_min = 1.5
	mat.scale_max = 4.0
	# 颜色随生命淡出
	var grad := Gradient.new()
	grad.set_color(0, Color(col.r, col.g, col.b, col.a))
	grad.set_color(1, Color(col.r, col.g, col.b, 0.0))
	var gtex := GradientTexture1D.new()
	gtex.gradient = grad
	mat.color_ramp = gtex
	p.process_material = mat
	node.add_child(p)
	# 自动回收（粒子播完）
	var timer := Timer.new()
	timer.name = "AutoReturn"
	timer.one_shot = true
	timer.wait_time = 0.55
	timer.timeout.connect(_pool_return.bind(effect_id, node))
	node.add_child(timer)
	add_child(node)
	node.visible = false
	return node

## 不同特效的粒子数 / 速度
func _amount_for(effect_id: String) -> int:
	match effect_id:
		"death_burst": return 24
		"hit_spark":   return 10
		"cast_flash":  return 8
		_:             return 12

func _speed_for(effect_id: String) -> float:
	match effect_id:
		"death_burst": return 220.0
		"hit_spark":   return 160.0
		_:             return 110.0

func _color_for(effect_id: String) -> Color:
	match effect_id:
		"hit_spark":     return Color(1.0, 0.9, 0.3, 0.9)
		"status_burn":   return Color(1.0, 0.4, 0.1, 0.8)
		"status_poison": return Color(0.3, 0.9, 0.2, 0.8)
		"cast_flash":    return Color(0.6, 0.8, 1.0, 0.7)
		"death_burst":   return Color(1.0, 0.2, 0.2, 0.8)
		_:               return Color(1, 1, 1, 0.6)

func _on_status_applied(payload: Dictionary) -> void:
	var status_type: int = int(payload.get("status_type", 0))
	var typedef: StatusTypeDef = StatusRegistry.get_type(status_type)
	if typedef and typedef.vfx_id != "":
		var eid: int = int(payload.get("target_id", -1))
		var pos: Vector2 = EnemyManager.get_pos_by_id(eid)
		if pos != Vector2(-9999.0, -9999.0):
			play(typedef.vfx_id, pos)

func get_active_count() -> int:
	return _active_count

func reset() -> void:
	for key in _vfx_pool:
		for n in _vfx_pool[key]:
			if is_instance_valid(n):
				n.queue_free()
	_vfx_pool.clear()
	_active_count = 0
