extends Node

## NEO-25: fetches `GET /game/world/interactables`; exposes descriptor rows for world build and
## glow preview.

signal catalog_ready(descriptors: Array)
signal catalog_failed(reason: String)

@export var base_url: String = "http://127.0.0.1:5253"

var _http: HTTPRequest
var _busy: bool = false


func _ready() -> void:
	_http = HTTPRequest.new()
	add_child(_http)
	_http.timeout = 30.0
	_http.request_completed.connect(_on_request_completed)


func request_catalog() -> void:
	if _busy:
		return
	_busy = true
	var url := "%s/game/world/interactables" % _base_root()
	var err: Error = _http.request(url)
	if err != OK:
		_busy = false
		var msg := "InteractablesCatalogClient: GET failed to start (%s)" % err
		push_error(msg)
		catalog_failed.emit(msg)


func _base_root() -> String:
	return base_url.strip_edges().rstrip("/")


func _on_request_completed(
	_result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray
) -> void:
	_busy = false
	var text := body.get_string_from_utf8()
	if response_code != 200:
		var msg := "InteractablesCatalogClient: HTTP %s body=%s" % [response_code, text]
		push_error(msg)
		catalog_failed.emit(msg)
		return
	var parsed: Variant = JSON.parse_string(text)
	if not parsed is Dictionary:
		var msg := "InteractablesCatalogClient: expected JSON object"
		push_error(msg)
		catalog_failed.emit(msg)
		return
	var root: Dictionary = parsed
	var descriptors: Array = _parse_interactables_array(root)
	if descriptors.is_empty():
		var msg2 := "InteractablesCatalogClient: interactables missing or empty"
		push_error(msg2)
		catalog_failed.emit(msg2)
		return
	catalog_ready.emit(descriptors)


## Returns an [Array] of [Dictionary] rows: [code]interactableId[/code], [code]kind[/code],
## [code]anchor[/code] ([Dictionary] x,y,z), [code]interactionRadius[/code] ([float]).
static func parse_catalog_json(text: String) -> Array:
	var parsed: Variant = JSON.parse_string(text)
	if not parsed is Dictionary:
		return []
	return _parse_interactables_array(parsed)


static func _parse_interactables_array(root: Variant) -> Array:
	if not root is Dictionary:
		return []
	var d: Dictionary = root
	var raw: Variant = d.get("interactables", null)
	if raw == null or not raw is Array:
		return []
	var out_arr: Array = []
	for item in raw as Array:
		if item is Dictionary:
			out_arr.append(item)
	return out_arr
