extends Object

## NEO-25: spawns walkable interactable props + glow marker pairs from server descriptor dicts.
## Returns glow groups for [method InteractionRadiusIndicators.setup_glow_groups].

const _PROP_SIZE := Vector3(0.9, 1.0, 0.4)
const _MARKER_MESH_SIZE := Vector3(0.22, 0.35, 0.22)
const _MARKER_OFFSET_A := Vector3(1.1, 0.25, 0.9)
const _MARKER_OFFSET_B := Vector3(-0.95, 0.22, -1.05)


static func build_from_catalog(
	descriptors: Array, interactables_root: Node3D, markers_root: Node3D
) -> Array:
	for c in interactables_root.get_children():
		c.free()
	for c in markers_root.get_children():
		c.free()

	var glow_groups: Array = []

	for row in descriptors:
		if not row is Dictionary:
			continue
		var rd: Dictionary = row
		var id: String = str(rd.get("interactableId", ""))
		var kind: String = str(rd.get("kind", ""))
		var anchor: Vector3 = _anchor_from_row(rd)
		var radius: float = float(rd.get("interactionRadius", 0.0))

		var body := StaticBody3D.new()
		body.name = "Interactable_%s" % id
		body.collision_mask = 3
		body.add_to_group("walkable")
		interactables_root.add_child(body)
		body.global_position = anchor

		var prop_mesh := MeshInstance3D.new()
		var box_mesh := BoxMesh.new()
		box_mesh.size = _PROP_SIZE
		prop_mesh.mesh = box_mesh
		prop_mesh.position = Vector3.ZERO
		var prop_mat := StandardMaterial3D.new()
		if kind == "resource_node":
			prop_mat.albedo_color = Color(0.18, 0.55, 0.32, 1.0)
		else:
			prop_mat.albedo_color = Color(0.28, 0.38, 0.45, 1.0)
		prop_mesh.material_override = prop_mat
		body.add_child(prop_mesh)

		var col := CollisionShape3D.new()
		var box_shape := BoxShape3D.new()
		box_shape.size = _PROP_SIZE
		col.shape = box_shape
		body.add_child(col)

		var marker_parent := Node3D.new()
		marker_parent.name = "Markers_%s" % id
		markers_root.add_child(marker_parent)
		marker_parent.global_position = anchor

		var mi_a := _make_marker_mesh()
		mi_a.position = _MARKER_OFFSET_A
		marker_parent.add_child(mi_a)
		var mi_b := _make_marker_mesh()
		mi_b.position = _MARKER_OFFSET_B
		marker_parent.add_child(mi_b)

		var glow_mat := StandardMaterial3D.new()
		glow_mat.albedo_color = Color(0.15, 0.4, 1.0, 1.0)
		glow_mat.emission_enabled = true
		glow_mat.emission = Color(0.3, 0.6, 1.0)
		glow_mat.emission_energy_multiplier = 0.12
		mi_a.material_override = glow_mat
		mi_b.material_override = glow_mat

		glow_groups.append(
			{"anchor": anchor, "radius": radius, "material": glow_mat, "markers": [mi_a, mi_b]}
		)

	return glow_groups


static func _anchor_from_row(rd: Dictionary) -> Vector3:
	var a: Variant = rd.get("anchor", null)
	if not a is Dictionary:
		return Vector3.ZERO
	var ad: Dictionary = a
	return Vector3(
		float(ad.get("x", 0.0)),
		float(ad.get("y", 0.0)),
		float(ad.get("z", 0.0)),
	)


static func _make_marker_mesh() -> MeshInstance3D:
	var mi := MeshInstance3D.new()
	var m := BoxMesh.new()
	m.size = _MARKER_MESH_SIZE
	mi.mesh = m
	return mi
