extends SceneTree

## Test suite for Scene Validation
##
## Validates all .tscn files in the project for loading and instantiation errors.
## Provides comprehensive scene validation to catch issues before runtime.

const TestHelperClass = preload("res://tests/helpers/TestHelper.gd")

var discovered_scenes: Array[String] = []
var validation_results: Dictionary = {}


func _initialize():
	# Wait for autoloads to initialize
	await process_frame
	await process_frame

	run_tests()

	# Exit after tests complete
	quit()


func run_tests():
	TestHelperClass.print_test_header("Scene Validation")

	# Run test suites
	test_scene_discovery()
	test_scene_loading()
	test_scene_instantiation()
	test_critical_scenes()

	# Print final summary
	print_validation_summary()

	TestHelperClass.print_test_footer("Scene Validation")


func test_scene_discovery():
	TestHelperClass.print_step("Scene Discovery")

	# Discover scenes in key directories
	var scene_directories = ["res://scenes/", "res://examples/"]

	for directory in scene_directories:
		discover_scenes_in_directory(directory)

	TestHelperClass.assert_true(discovered_scenes.size() > 0, "Found scenes in project")
	print("Discovered %d scene files" % discovered_scenes.size())

	# List discovered scenes for reference
	for scene_path in discovered_scenes:
		print("  - %s" % scene_path)


func discover_scenes_in_directory(directory_path: String):
	var dir = DirAccess.open(directory_path)
	if not dir:
		print("Warning: Could not access directory: %s" % directory_path)
		return

	dir.list_dir_begin()
	var file_name = dir.get_next()

	while file_name != "":
		var full_path = directory_path.path_join(file_name)

		if dir.current_is_dir() and not file_name.begins_with("."):
			# Recursively search subdirectories
			discover_scenes_in_directory(full_path)
		elif file_name.ends_with(".tscn"):
			# Add scene file to discovery list
			discovered_scenes.append(full_path)

		file_name = dir.get_next()


func test_scene_loading():
	TestHelperClass.print_step("Scene Loading Validation")

	for scene_path in discovered_scenes:
		validate_scene_loading(scene_path)


func validate_scene_loading(scene_path: String):
	var scene_name = scene_path.get_file()

	# Check if resource exists
	if not ResourceLoader.exists(scene_path):
		validation_results[scene_path] = "Resource does not exist"
		TestHelperClass.assert_false(true, "%s - Resource does not exist" % scene_name)
		return

	# Attempt to load the scene
	var packed_scene = load(scene_path)
	if not packed_scene:
		validation_results[scene_path] = "Failed to load scene"
		TestHelperClass.assert_false(true, "%s - Failed to load scene" % scene_name)
		return

	if not packed_scene is PackedScene:
		validation_results[scene_path] = "Resource is not a PackedScene"
		TestHelperClass.assert_false(true, "%s - Resource is not a PackedScene" % scene_name)
		return

	validation_results[scene_path] = "Loading successful"
	TestHelperClass.assert_true(true, "%s - Scene loads successfully" % scene_name)


func test_scene_instantiation():
	TestHelperClass.print_step("Scene Instantiation Testing")

	for scene_path in discovered_scenes:
		# Only test instantiation for scenes that loaded successfully
		if validation_results.get(scene_path, "") == "Loading successful":
			validate_scene_instantiation(scene_path)


func validate_scene_instantiation(scene_path: String):
	var scene_name = scene_path.get_file()

	# Load the scene (we know it loads from previous test)
	var packed_scene = load(scene_path)

	# Attempt to instantiate
	var scene_instance = packed_scene.instantiate()
	if not scene_instance:
		validation_results[scene_path] = "Failed to instantiate scene"
		TestHelperClass.assert_false(true, "%s - Failed to instantiate scene" % scene_name)
		return

	# Validate the instance
	TestHelperClass.assert_not_null(
		scene_instance, "%s - Scene instantiation creates valid node" % scene_name
	)

	# Clean up the instance
	scene_instance.queue_free()

	# Update validation status
	if validation_results[scene_path] == "Loading successful":
		validation_results[scene_path] = "Full validation successful"


func test_critical_scenes():
	TestHelperClass.print_step("Critical Scene Validation")

	# Define critical scenes that must work
	var critical_scenes = [
		"res://scenes/main/main.tscn",
		"res://scenes/game/game.tscn",
		"res://scenes/ui/MainMenu.tscn",
		"res://scenes/game/gameplays/match3_gameplay.tscn"
	]

	for scene_path in critical_scenes:
		if scene_path in discovered_scenes:
			var status = validation_results.get(scene_path, "Unknown")
			TestHelperClass.assert_equal(
				"Full validation successful",
				status,
				"Critical scene %s must pass all validation" % scene_path.get_file()
			)
		else:
			TestHelperClass.assert_false(true, "Critical scene missing: %s" % scene_path)


func print_validation_summary():
	print("\n=== Scene Validation Summary ===")

	var total_scenes = discovered_scenes.size()
	var successful_scenes = 0
	var failed_scenes = 0

	for scene_path in discovered_scenes:
		var status = validation_results.get(scene_path, "Not tested")
		if status == "Full validation successful" or status == "Loading successful":
			successful_scenes += 1
		else:
			failed_scenes += 1
			print("❌ %s: %s" % [scene_path.get_file(), status])

	print("\nTotal Scenes: %d" % total_scenes)
	print("Successful: %d" % successful_scenes)
	print("Failed: %d" % failed_scenes)

	if failed_scenes == 0:
		print("✅ All scenes passed validation!")
	else:
		print("❌ %d scene(s) failed validation" % failed_scenes)
