## Client Main — Client entry point for testing.
##
## Connects to the server. Receives broadcast_spawn_player /
## broadcast_despawn_player RPCs from the server and creates
## visual player nodes locally so each client sees every other player.
##
## Phase 0: simple position replication via RPC + box mesh player nodes.

extends Node3D

# ---------------------------------------------------------------------------
# Exports
# ---------------------------------------------------------------------------
@export var server_host: String = "127.0.0.1"
@export var server_port: int = 34197
@export var player_scene: PackedScene = preload("res://scenes/player.tscn")

# ---------------------------------------------------------------------------
# State
# ---------------------------------------------------------------------------
# remote_players[peer_id] = Node3D — visual representation of other players
var remote_players: Dictionary = {}
var connected: bool = false

# ---------------------------------------------------------------------------
# Lifecycle
# ---------------------------------------------------------------------------
func _ready() -> void:
	# Connect to server after a short delay
	await get_tree().create_timer(0.5).timeout
	_connect_to_server()

func _connect_to_server() -> void:
	if OS.has_environment("SERVER_HOST"):
		server_host = OS.get_environment("SERVER_HOST")
	if OS.has_environment("SERVER_PORT"):
		server_port = int(OS.get_environment("SERVER_PORT"))
	
	print("[ClientMain] Connecting to %s:%d ..." % [server_host, server_port])
	
	var err: Error = NetworkManager.join_server(server_host, server_port)
	if err != OK:
		push_error("[ClientMain] Connection failed: %s" % error_string(err))
		await get_tree().create_timer(2.0).timeout
		_connect_to_server()
		return
	
	# Setup camera and lights
	_setup_scene()
	
	connected = true
	
	# Connect replication signals from NetworkManager
	# These fire when the server broadcasts spawn_player / despawn_player
	NetworkManager.remote_player_spawned.connect(_on_remote_player_spawned)
	NetworkManager.remote_player_despawned.connect(_on_remote_player_despawned)
	
	print("[ClientMain] Connected to server. Peer ID: %d" % multiplayer.get_unique_id())

func _setup_scene() -> void:
	# Simple 3/4 top-down camera for Phase 0 testing
	var camera := Camera3D.new()
	camera.current = true
	camera.position = Vector3(0, 16, 12)
	camera.rotation_degrees.x = -55
	add_child(camera)
	
	# Ambient light so we can see the box meshes
	var light := DirectionalLight3D.new()
	light.light_energy = 1.0
	light.shadow_enabled = true
	light.position = Vector3(10, 20, 10)
	light.look_at(Vector3.ZERO)
	add_child(light)

# ---------------------------------------------------------------------------
# Player replication handlers (called when server broadcasts via RPC)
# ---------------------------------------------------------------------------
func _on_remote_player_spawned(peer_id: int, pos: Vector3) -> void:
	if peer_id == multiplayer.get_unique_id():
		# This is OUR player — the server has authority over it,
		# but we don't need to create a duplicate. Our local player
		# node is managed by the server's authority system.
		# The player.gd script will handle input on this peer.
		return
	
	if peer_id in remote_players:
		push_warning("[ClientMain] Remote player %d already exists, skipping" % peer_id)
		return
	
	# Create a remote player node for visualization
	var player: Node3D
	if player_scene:
		player = player_scene.instantiate()
	else:
		player = Node3D.new()
		player.set_script(preload("res://scripts/network/player.gd"))
	
	player.name = "RemotePlayer_%d" % peer_id
	player.set_multiplayer_authority(peer_id)
	player.position = pos
	
	add_child(player, true)
	remote_players[peer_id] = player
	
	print("[ClientMain] Spawned remote player %d at (%.1f, %.1f)" % [peer_id, pos.x, pos.z])

func _on_remote_player_despawned(peer_id: int) -> void:
	if peer_id == multiplayer.get_unique_id():
		return
	
	if peer_id in remote_players:
		remote_players[peer_id].queue_free()
		remote_players.erase(peer_id)
		print("[ClientMain] Despawned remote player %d" % peer_id)

func _exit_tree() -> void:
	if connected:
		NetworkManager.stop()
	
	# Clean up any remaining remote players
	for p in remote_players.values():
		p.queue_free()
	remote_players.clear()
