extends Node

# Room Registry Client - Handles HTTP requests to room discovery server
# Allows hosts to register rooms and joiners to discover available rooms

# Logging - use LogManager for categorized logging
func log_print(message: String):
	LogManager.log(message, LogManager.CATEGORY_NETWORK)

func log_error(message: String):
	LogManager.log_error(message, LogManager.CATEGORY_NETWORK)

signal rooms_fetched(rooms: Array)
signal room_update_sent(success: bool)

const ROOM_LIST_URL = "https://ruinborn-rooms.thefirstboss.com/index.php"
const ROOM_UPDATE_URL = "https://ruinborn-rooms.thefirstboss.com/update.php"

var http_request_list: HTTPRequest = null
var http_request_update: HTTPRequest = null
var update_timer: Timer = null
var current_room: String = ""
var current_level: int = 1
var pending_update: Dictionary = {}  # Store pending update (player_count, level) when request is in progress
var is_update_requesting: bool = false  # Flag to track if an update request is in progress
var is_list_requesting: bool = false  # Flag to track if a room list request is in progress

func _ready():
	# Create HTTPRequest nodes for fetching and updating
	http_request_list = HTTPRequest.new()
	http_request_list.name = "HTTPRequestList"
	add_child(http_request_list)
	http_request_list.request_completed.connect(_on_room_list_received)
	
	http_request_update = HTTPRequest.new()
	http_request_update.name = "HTTPRequestUpdate"
	add_child(http_request_update)
	http_request_update.request_completed.connect(_on_room_update_received)
	
	# Create timer for periodic updates
	update_timer = Timer.new()
	update_timer.name = "UpdateTimer"
	update_timer.wait_time = 15.0  # Update every 15 seconds
	update_timer.timeout.connect(_on_update_timer_timeout)
	update_timer.autostart = false
	add_child(update_timer)

func fetch_available_rooms() -> bool:
	"""Fetch list of available rooms from the server"""
	# Check if a request is already in progress
	if is_list_requesting or http_request_list.get_http_client_status() == HTTPClient.STATUS_REQUESTING:
		log_print("RoomRegistry: Room list request already in progress, skipping duplicate request")
		return false
	
	# Mark that we're starting a request
	is_list_requesting = true
	
	log_print("RoomRegistry: Fetching available rooms...")
	var error = http_request_list.request(ROOM_LIST_URL)
	if error != OK:
		log_error("RoomRegistry: Failed to request room list: " + str(error))
		is_list_requesting = false  # Reset flag on error
		return false
	return true

func register_room(room_code: String, player_count: int, level: int) -> bool:
	"""Register a room and start sending keepalive updates"""
	current_room = room_code
	current_level = level
	log_print("RoomRegistry: Registering room: " + room_code + " with " + str(player_count) + " players, level " + str(level))
	
	# Send initial update
	send_room_update(player_count)
	
	# Start periodic updates
	update_timer.start()
	
	return true

func send_room_update(player_count: int, level: int = -1) -> bool:
	"""Send a keepalive update for the current room"""
	if current_room.is_empty():
		return false
	
	# Get level from game_world if not provided
	if level < 0:
		var game_world = get_tree().get_first_node_in_group("game_world")
		if game_world:
			level = game_world.current_level
		else:
			level = current_level
	else:
		current_level = level
	
	# Check if a request is already in progress - if so, queue this update
	# HTTPRequest can only handle one request at a time
	if is_update_requesting or http_request_update.get_http_client_status() == HTTPClient.STATUS_REQUESTING:
		log_print("RoomRegistry: Update request already in progress, queuing update")
		pending_update = {
			"player_count": player_count,
			"level": level
		}
		return true  # Return true to indicate update is queued
	
	# Clear any pending update since we're sending now
	pending_update = {}
	
	# Mark that we're starting a request
	is_update_requesting = true
	
	var json_data = {
		"data": {
			"room": current_room,
			"players": player_count,
			"level": level
		}
	}
	
	var json_string = JSON.stringify(json_data)
	var headers = ["Content-Type: application/json"]
	
	log_print("RoomRegistry: Sending room update (room: " + current_room + ", players: " + str(player_count) + ", level: " + str(level) + ")")
	var error = http_request_update.request(ROOM_UPDATE_URL, headers, HTTPClient.METHOD_POST, json_string)
	if error != OK:
		log_error("RoomRegistry: Failed to send room update: " + str(error))
		is_update_requesting = false  # Reset flag on error
		return false
	return true

func unregister_room():
	"""Stop sending updates and clear room registration"""
	log_print("RoomRegistry: Unregistering room: " + current_room)
	update_timer.stop()
	current_room = ""
	current_level = 1

func _on_room_list_received(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray):
	"""Handle response from room list request"""
	# Reset the requesting flag
	is_list_requesting = false
	
	if result != HTTPRequest.RESULT_SUCCESS:
		log_error("RoomRegistry: Failed to fetch rooms: HTTP result " + str(result))
		rooms_fetched.emit([])
		return
	
	if response_code != 200:
		log_error("RoomRegistry: HTTP error code: " + str(response_code))
		rooms_fetched.emit([])
		return
	
	var json = JSON.new()
	var parse_error = json.parse(body.get_string_from_utf8())
	if parse_error != OK:
		log_error("RoomRegistry: Failed to parse room list JSON: " + str(parse_error))
		rooms_fetched.emit([])
		return
	
	var data = json.data
	if not data.has("status") or data["status"] != "OK":
		log_error("RoomRegistry: Server returned error status")
		rooms_fetched.emit([])
		return
	
	var rooms = []
	if data.has("data") and data["data"] is Array:
		for room_data in data["data"]:
			if room_data.has("room"):
				rooms.append({
					"room": room_data["room"],
					"players": room_data.get("players", 0),
					"level": room_data.get("level", 1)
				})
	
	log_print("RoomRegistry: Found " + str(rooms.size()) + " available rooms")
	rooms_fetched.emit(rooms)

func _on_room_update_received(result: int, response_code: int, _headers: PackedStringArray, _body: PackedByteArray):
	"""Handle response from room update request"""
	# Reset the requesting flag
	is_update_requesting = false
	
	if result != HTTPRequest.RESULT_SUCCESS:
		log_error("RoomRegistry: Failed to send room update: HTTP result " + str(result))
		room_update_sent.emit(false)
		# Try to send pending update if any
		if not pending_update.is_empty():
			send_room_update(pending_update.get("player_count", 0), pending_update.get("level", -1))
		return
	
	if response_code != 200:
		log_error("RoomRegistry: Room update HTTP error code: " + str(response_code))
		room_update_sent.emit(false)
		# Try to send pending update if any
		if not pending_update.is_empty():
			send_room_update(pending_update.get("player_count", 0), pending_update.get("level", -1))
		return
	
	log_print("RoomRegistry: Room update sent successfully")
	room_update_sent.emit(true)
	
	# Send pending update if any
	if not pending_update.is_empty():
		var queued_player_count = pending_update.get("player_count", 0)
		var queued_level = pending_update.get("level", -1)
		pending_update = {}  # Clear pending update before sending
		send_room_update(queued_player_count, queued_level)

func _on_update_timer_timeout():
	"""Periodic timer callback to send keepalive updates"""
	if current_room.is_empty():
		return
	
	# Get current player count from NetworkManager
	var network_manager = get_node("/root/NetworkManager")
	if not network_manager:
		return
	
	var player_count = network_manager.get_all_player_ids().size()
	var level = current_level
	var game_world = get_tree().get_first_node_in_group("game_world")
	if game_world:
		level = game_world.current_level
		current_level = level
	
	send_room_update(player_count, level)
