## Game Manager - Centralized Scene Transition System
##
## Manages all scene transitions with race condition protection and input validation.
## Provides safe scene switching for different gameplay modes with error handling.
## Never call get_tree().change_scene_to_file() directly - use GameManager methods.

extends Node

const GAME_SCENE_PATH := "res://scenes/game/game.tscn"
const MAIN_SCENE_PATH := "res://scenes/main/main.tscn"

var pending_gameplay_mode: String = "match3"
var is_changing_scene: bool = false


func start_new_game() -> void:
	"""Start a new match-3 game with fresh save data"""
	SaveManager.start_new_game()
	start_game_with_mode("match3")


func continue_game() -> void:
	"""Continue existing match-3 game with saved score intact"""
	# Don't reset score
	start_game_with_mode("match3")


func start_match3_game() -> void:
	"""Start new match-3 gameplay mode"""
	SaveManager.start_new_game()
	start_game_with_mode("match3")


func start_clickomania_game() -> void:
	"""Start new clickomania gameplay mode"""
	SaveManager.start_new_game()
	start_game_with_mode("clickomania")


func start_game_with_mode(gameplay_mode: String) -> void:
	"""Load game scene with specified gameplay mode and safety validation"""
	# Input validation
	if not gameplay_mode or gameplay_mode.is_empty():
		DebugManager.log_error("Empty or null gameplay mode provided", "GameManager")
		return

	if not gameplay_mode is String:
		DebugManager.log_error(
			"Invalid gameplay mode type: " + str(typeof(gameplay_mode)), "GameManager"
		)
		return

	# Prevent concurrent scene changes (race condition protection)
	if is_changing_scene:
		DebugManager.log_warn("Scene change already in progress, ignoring request", "GameManager")
		return

	# Validate gameplay mode
	var valid_modes = ["match3", "clickomania"]
	if not gameplay_mode in valid_modes:
		DebugManager.log_error(
			"Invalid gameplay mode: '%s'. Valid modes: %s" % [gameplay_mode, str(valid_modes)],
			"GameManager"
		)
		return

	is_changing_scene = true
	pending_gameplay_mode = gameplay_mode

	var packed_scene := load(GAME_SCENE_PATH)
	if not packed_scene or not packed_scene is PackedScene:
		DebugManager.log_error("Failed to load Game scene at: %s" % GAME_SCENE_PATH, "GameManager")
		is_changing_scene = false
		return

	var result = get_tree().change_scene_to_packed(packed_scene)
	if result != OK:
		DebugManager.log_error(
			"Failed to change to game scene (Error code: %d)" % result, "GameManager"
		)
		is_changing_scene = false
		return

	# Wait for scene instantiation and tree addition
	await get_tree().process_frame
	await get_tree().process_frame  # Additional frame ensures complete initialization

	# Validate scene was loaded successfully
	if not get_tree().current_scene:
		DebugManager.log_error("Current scene is null after scene change", "GameManager")
		is_changing_scene = false
		return

	# Configure game scene with requested gameplay mode
	if get_tree().current_scene.has_method("set_gameplay_mode"):
		DebugManager.log_info("Setting gameplay mode to: %s" % pending_gameplay_mode, "GameManager")
		get_tree().current_scene.set_gameplay_mode(pending_gameplay_mode)

		# Load saved score
		if get_tree().current_scene.has_method("set_global_score"):
			var saved_score = SaveManager.get_current_score()
			DebugManager.log_info("Loading saved score: %d" % saved_score, "GameManager")
			get_tree().current_scene.set_global_score(saved_score)
	else:
		DebugManager.log_error("Game scene does not have set_gameplay_mode method", "GameManager")

	is_changing_scene = false


func save_game() -> void:
	"""Save current game state and score via SaveManager"""
	# Get current score from the active game scene
	var current_score = 0
	if get_tree().current_scene and get_tree().current_scene.has_method("get_global_score"):
		current_score = get_tree().current_scene.get_global_score()

	SaveManager.finish_game(current_score)
	DebugManager.log_info("Game saved with score: %d" % current_score, "GameManager")


func exit_to_main_menu() -> void:
	"""Exit to main menu with race condition protection"""
	# Prevent concurrent scene changes
	if is_changing_scene:
		DebugManager.log_warn(
			"Scene change already in progress, ignoring exit to main menu request", "GameManager"
		)
		return

	is_changing_scene = true
	DebugManager.log_info("Attempting to exit to main menu", "GameManager")

	var packed_scene := load(MAIN_SCENE_PATH)
	if not packed_scene or not packed_scene is PackedScene:
		DebugManager.log_error("Failed to load Main scene at: %s" % MAIN_SCENE_PATH, "GameManager")
		is_changing_scene = false
		return

	var result = get_tree().change_scene_to_packed(packed_scene)
	if result != OK:
		DebugManager.log_error(
			"Failed to change to main scene (Error code: %d)" % result, "GameManager"
		)
		is_changing_scene = false
		return

	DebugManager.log_info("Successfully loaded main scene", "GameManager")

	# Wait for scene to be ready, then mark scene change as complete
	await get_tree().process_frame
	is_changing_scene = false
