extends Node

var is_owned: bool = false
var steam_app_id: int = 480
var steam_id: int = 0
var steam_username: String = ""

var lobby_id = 0
var lobby_max_members = 4
var lobby_members: Array = []

var steam_initialized: bool = false

var peer: SteamMultiplayerPeer


func _ready() -> void:
	OS.set_environment("SteamAppId", str(steam_app_id))
	OS.set_environment("SteamGameId", str(steam_app_id))
	steam_initialized = init_steam()
	
	if not steam_initialized:
		print("!!! Steam did not initialize. Multiplayer will be disabled.")
		return
	
	# Connect Steam lobby signals
	Steam.lobby_created.connect(_on_lobby_created)
	Steam.lobby_joined.connect(_on_lobby_joined)
	#Steam.lobby_match_list.connect(_on_lobby_match_list)
	Steam.lobby_chat_update.connect(_on_lobby_chat_update)
	Steam.lobby_data_update.connect(_on_lobby_data_update)
	#Steam.join_requested.connect(_on_lobby_join_requested)
	Steam.persona_state_change.connect(_on_persona_change)
	
	# Setup multiplayer signals
	multiplayer.peer_connected.connect(_on_peer_connected)
	multiplayer.peer_disconnected.connect(_on_peer_disconnected)
	multiplayer.connected_to_server.connect(_on_connected_to_server)
	multiplayer.connection_failed.connect(_on_connection_failed)
	multiplayer.server_disconnected.connect(_on_server_disconnected)
	Steam.p2p_session_request.connect(_on_p2p_session_request)
	
	check_command_line()


func _on_p2p_session_request(steam_id_remote: int) -> void:
	## ADDED: More detailed logging to confirm P2P acceptance.
	print("[P2P] ==> Session request from: %s. Accepting." % steam_id_remote)
	var accepted = Steam.acceptP2PSessionWithUser(steam_id_remote)
	if not accepted:
		print("[P2P] !!! Failed to accept P2P session with %s." % steam_id_remote)


func _process(delta):
	## ADDED: Guard clause in case Steam fails to initialize.
	if not steam_initialized:
		return
		
	Steam.run_callbacks()
	
	if Input.is_action_just_pressed("interact"):
		## ADDED: Replaced simple print with a detailed diagnostic function.
		log_multiplayer_info()


func check_command_line() -> void:
	var args: Array = OS.get_cmdline_args()
	if args.size() > 0:
		if args[0] == "+connect_lobby":
			if args.size() > 1 and int(args[1]) > 0:
				print("Command line lobby ID: %s" % args[1])
				join_lobby(int(args[1]))


func init_steam() -> bool:
	var response: Dictionary = Steam.steamInitEx()
	print("Steam init response: %s " % response)
	
	if response['status'] > 0:
		print("!!! Failed to init steam! Code: %s " % response)
		return false

	is_owned = Steam.isSubscribed()
	steam_id = Steam.getSteamID()
	steam_username = Steam.getPersonaName()
	
	print("Steam initialized successfully for %s (ID: %s)." % [steam_username, steam_id])
	
	if !is_owned:
		print("!!! WARNING: Steam reports you do not own App ID %s." % steam_app_id)
		# You might want to return false here in a real game
		# return false
	
	return true


func setup_multiplayer_peer(is_host: bool = false) -> void:
	## ADDED: Check if a peer is already active before creating a new one.
	if multiplayer.multiplayer_peer and multiplayer.multiplayer_peer.get_connection_status() != MultiplayerPeer.CONNECTION_DISCONNECTED:
		print("[Multiplayer] Peer already exists. Disconnecting old one.")
		multiplayer.multiplayer_peer.close()

	peer = SteamMultiplayerPeer.new()
	
	if is_host:
		print("[Multiplayer] Creating Host...")
		var err = peer.create_host(0) ## REMOVED: Channel is handled by the peer automatically now.
		if err != OK:
			print("[Multiplayer] !!! Failed to create host. Error: %s" % err)
			return
		
		multiplayer.multiplayer_peer = peer
		print("[Multiplayer] Host created successfully. My Peer ID: %s" % multiplayer.get_unique_id())
	else:
		if lobby_id == 0:
			print("[Multiplayer] !!! Cannot create client, not in a lobby.")
			return
		
		var host_id = Steam.getLobbyOwner(lobby_id)
		print("[Multiplayer] Creating Client, attempting to connect to host: %s" % host_id)
		var err = peer.create_client(host_id) ## REMOVED: Channel is handled by the peer automatically.
		if err != OK:
			print("[Multiplayer] !!! Failed to create client. Error: %s" % err)
			return
			
		multiplayer.multiplayer_peer = peer
		print("[Multiplayer] Client peer created. Waiting for connection...")


func create_lobby():
	if lobby_id == 0:
		print("Creating lobby...")
		Steam.createLobby(Steam.LOBBY_TYPE_FRIENDS_ONLY, lobby_max_members)


func _on_lobby_created(connect: int, this_lobby_id: int):
	if connect == 1:
		lobby_id = this_lobby_id
		print("Lobby created with id `%s`" % lobby_id)
		
		Steam.setLobbyJoinable(lobby_id, true)
		Steam.setLobbyData(lobby_id, "name", steam_username + "'s Lobby")
		Steam.setLobbyData(lobby_id, "mode", "Splunk")
		
		Steam.allowP2PPacketRelay(true)
		setup_multiplayer_peer(true) # Setup as host
	else :
		print("!!! Failed to create lobby.")


func join_lobby(this_lobby_id: int):
	print("Attempting to join lobby: %s" % this_lobby_id)
	lobby_members.clear()
	Steam.joinLobby(this_lobby_id)


func _on_lobby_joined(this_lobby_id: int, permissions: int, locked: bool, response: int):
	if response == Steam.CHAT_ROOM_ENTER_RESPONSE_SUCCESS:
		lobby_id = this_lobby_id
		print("Successfully joined lobby: %s" % lobby_id)
		get_lobby_members()
		
		# FIXED: Use Steam.getLobbyOwner() to determine if we should be host or client
		var lobby_owner_id = Steam.getLobbyOwner(lobby_id)
		var am_i_owner = (lobby_owner_id == steam_id)
		
		print("[Multiplayer] Lobby Owner: %s, My Steam ID: %s, Am I Owner?: %s" % [lobby_owner_id, steam_id, am_i_owner])
		
		if not am_i_owner:
			print("[Multiplayer] I am not the lobby owner, setting up as client...")
			setup_multiplayer_peer(false) # Setup as client
		else:
			print("[Multiplayer] I am the lobby owner, but multiplayer peer should already be set up as host.")
	else:
		## ADDED: Log the specific reason for the join failure.
		print("!!! Failed to join lobby. Reason: %s" % get_join_fail_reason(response))


func get_lobby_members() -> void:
	lobby_members.clear()
	if lobby_id == 0: return

	var num_members = Steam.getNumLobbyMembers(lobby_id)
	print("--- Refreshing Lobby Members (%s) ---" % num_members)
	for i in range(num_members):
		var member_id = Steam.getLobbyMemberByIndex(lobby_id, i)
		var member_name = Steam.getFriendPersonaName(member_id)
		lobby_members.append({
			"steam_id": member_id,
			"steam_name": member_name
		})
		print("  - %s (%s)" % [member_name, member_id])
	print("---------------------------------")


func _on_lobby_data_update(lobby: int, user: int, success: int) -> void:
	if success:
		if lobby == user:
			print("Lobby data for lobby %s has been updated." % lobby)
			var lobby_name = Steam.getLobbyData(lobby, "name")
			print("  > New lobby name: %s" % lobby_name)
		else:
			print("Data for member %s in lobby %s has been updated." % [user, lobby])


func _on_persona_change(steam_id_changed: int, flag: int) -> void:
	# This can be spammy, but useful for debugging name changes.
	# print("Persona state changed for %s. Refreshing lobby members." % steam_id_changed)
	get_lobby_members()


func leave_lobby() -> void:
	pass


func _on_lobby_chat_update(lobby_id_update: int, user_changed_id: int, user_making_change_id: int, chat_state: int):
	var state_string = "UNKNOWN"
	match chat_state:
		Steam.CHAT_MEMBER_STATE_CHANGE_ENTERED: state_string = "ENTERED"
		Steam.CHAT_MEMBER_STATE_CHANGE_LEFT: state_string = "LEFT"
		Steam.CHAT_MEMBER_STATE_CHANGE_DISCONNECTED: state_string = "DISCONNECTED"
		Steam.CHAT_MEMBER_STATE_CHANGE_KICKED: state_string = "KICKED"
		Steam.CHAT_MEMBER_STATE_CHANGE_BANNED: state_string = "BANNED"

	print("[Lobby] Chat Update: User %s has %s." % [user_changed_id, state_string])
	
	# Any change in lobby membership should trigger a refresh.
	get_lobby_members()


func _on_peer_connected(id: int) -> void:
	print("[Multiplayer] ✅ Peer connected: %s" % id)
	# It's good practice to re-check lobby members when a peer connects successfully.
	get_lobby_members()

func _on_peer_disconnected(id: int) -> void:
	print("[Multiplayer] ❌ Peer disconnected: %s" % id)

func _on_connected_to_server() -> void:
	print("[Multiplayer] ✅ Successfully connected to the host.")
	print("[Multiplayer]   - My Peer ID is now: %s" % multiplayer.get_unique_id())

func _on_connection_failed() -> void:
	print("[Multiplayer] ❌ Connection to the host failed.")

func _on_server_disconnected() -> void:
	print("[Multiplayer] ❌ Disconnected from the host.")


## ADDED: New function to log all relevant multiplayer and lobby information.
func log_multiplayer_info():
	print("\n--- DIAGNOSTIC INFO ---")
	print("## Multiplayer Status:")
	if multiplayer.multiplayer_peer:
		print("  - Peer State: Active")
		print("  - Connection Status: %s" % get_connection_status_string(multiplayer.multiplayer_peer.get_connection_status()))
		print("  - Is Server?: %s" % multiplayer.is_server())
		print("  - My Peer ID: %s" % multiplayer.get_unique_id())
		print("  - Connected Peer IDs: %s" % multiplayer.get_peers())
	else:
		print("  - Peer State: Inactive (null)")
	
	print("\n## Steam Lobby Info:")
	print("  - In Lobby?: %s" % (lobby_id != 0))
	print("  - Lobby ID: %s" % lobby_id)
	if lobby_id != 0:
		print("  - Lobby Owner Steam ID: %s" % Steam.getLobbyOwner(lobby_id))
	print("  - My Steam ID: %s" % steam_id)
	print("  - Lobby Members Array (%s):" % lobby_members.size())
	for member in lobby_members:
		print("    - %s (%s)" % [member.steam_name, member.steam_id])
	print("-------------------------\n")


## ADDED: Helper function to get a human-readable string for connection status.
func get_connection_status_string(status: int) -> String:
	match status:
		MultiplayerPeer.CONNECTION_DISCONNECTED: return "Disconnected"
		MultiplayerPeer.CONNECTION_CONNECTING: return "Connecting"
		MultiplayerPeer.CONNECTION_CONNECTED: return "Connected"
		_: return "Unknown Status"


func get_join_fail_reason(response: int) -> String:
	match response:
		Steam.CHAT_ROOM_ENTER_RESPONSE_DOESNT_EXIST: return "Lobby no longer exists"
		Steam.CHAT_ROOM_ENTER_RESPONSE_NOT_ALLOWED: return "Not allowed to join"
		Steam.CHAT_ROOM_ENTER_RESPONSE_FULL: return "Lobby is full"
		Steam.CHAT_ROOM_ENTER_RESPONSE_ERROR: return "Unknown error"
		Steam.CHAT_ROOM_ENTER_RESPONSE_BANNED: return "You are banned"
		Steam.CHAT_ROOM_ENTER_RESPONSE_LIMITED: return "Limited account"
		Steam.CHAT_ROOM_ENTER_RESPONSE_CLAN_DISABLED: return "Lobby is locked"
		Steam.CHAT_ROOM_ENTER_RESPONSE_COMMUNITY_BAN: return "Community locked"
		Steam.CHAT_ROOM_ENTER_RESPONSE_MEMBER_BLOCKED_YOU: return "A member blocked you"
		Steam.CHAT_ROOM_ENTER_RESPONSE_YOU_BLOCKED_MEMBER: return "You blocked a member"
		_: return "Unknown reason"
