extends Node

signal connection_succeeded()
signal connection_failed()
signal server_started()
signal server_closed()
signal peer_connected(id: int)
signal peer_disconnected(id: int)

enum Mode { NONE, SOLO, HOST, CLIENT, DEDICATED }
var current_mode: Mode = Mode.NONE

const DEFAULT_PORT := 7777
const MAX_PLAYERS := 16

var peer: ENetMultiplayerPeer = null


func _ready() -> void:
	multiplayer.peer_connected.connect(_on_peer_connected)
	multiplayer.peer_disconnected.connect(_on_peer_disconnected)
	multiplayer.connected_to_server.connect(_on_connection_ok)
	multiplayer.connection_failed.connect(_on_connection_failed)
	multiplayer.server_disconnected.connect(_on_server_disconnected)

	# Auto-start from command line args
	var args := OS.get_cmdline_user_args()
	if "--server" in args:
		start_dedicated_server(DEFAULT_PORT)
	elif "--client" in args:
		var idx := args.find("--client")
		var address := "127.0.0.1"
		if idx + 1 < args.size():
			address = args[idx + 1]
		join_server(address, DEFAULT_PORT)


func start_dedicated_server(port: int = DEFAULT_PORT) -> bool:
	peer = ENetMultiplayerPeer.new()
	var err := peer.create_server(port, MAX_PLAYERS)
	if err != OK:
		push_error("NetworkManager: server creation failed — error %d" % err)
		peer = null
		return false
	multiplayer.multiplayer_peer = peer
	current_mode = Mode.DEDICATED
	print("[NET] Dedicated server listening on port %d" % port)
	server_started.emit()
	return true


func start_host(port: int = DEFAULT_PORT) -> bool:
	peer = ENetMultiplayerPeer.new()
	var err := peer.create_server(port, MAX_PLAYERS)
	if err != OK:
		push_error("NetworkManager: host creation failed — error %d" % err)
		peer = null
		return false
	multiplayer.multiplayer_peer = peer
	current_mode = Mode.HOST
	print("[NET] Host server listening on port %d" % port)
	server_started.emit()
	return true


func join_server(address: String, port: int = DEFAULT_PORT) -> bool:
	peer = ENetMultiplayerPeer.new()
	var err := peer.create_client(address, port)
	if err != OK:
		push_error("NetworkManager: client connection failed — error %d" % err)
		peer = null
		return false
	multiplayer.multiplayer_peer = peer
	current_mode = Mode.CLIENT
	print("[NET] Connecting to %s:%d" % [address, port])
	return true


func disconnect_from_server() -> void:
	if peer != null:
		peer.close()
		peer = null
	multiplayer.multiplayer_peer = null
	current_mode = Mode.NONE
	server_closed.emit()


func _on_peer_connected(id: int) -> void:
	print("[NET] Peer connected: %d" % id)
	peer_connected.emit(id)


func _on_peer_disconnected(id: int) -> void:
	print("[NET] Peer disconnected: %d" % id)
	peer_disconnected.emit(id)


func _on_connection_ok() -> void:
	print("[NET] Connected to server (my id: %d)" % multiplayer.get_unique_id())
	connection_succeeded.emit()


func _on_connection_failed() -> void:
	push_warning("[NET] Connection failed")
	peer = null
	multiplayer.multiplayer_peer = null
	current_mode = Mode.NONE
	connection_failed.emit()


func _on_server_disconnected() -> void:
	push_warning("[NET] Server disconnected")
	peer = null
	multiplayer.multiplayer_peer = null
	current_mode = Mode.NONE
	server_closed.emit()


func is_server() -> bool:
	return current_mode == Mode.HOST or current_mode == Mode.DEDICATED


func is_client() -> bool:
	return current_mode == Mode.CLIENT


func is_solo() -> bool:
	return current_mode == Mode.SOLO or current_mode == Mode.NONE


func get_my_id() -> int:
	return multiplayer.get_unique_id()
