# Export operations module
# Handles: export_mesh_library, get_uid, resave_resources
# Corresponds to: test_export.py, test_e2e_export.py
class_name ExportOps


## Export a scene as a MeshLibrary resource
static func export_mesh_library(ctx: SceneTree, params: Dictionary) -> void:
	print("Exporting MeshLibrary from scene: " + params.scene_path)
	
	# Ensure the scene path starts with res:// for Godot's resource system
	var full_scene_path: String = params.scene_path
	if not full_scene_path.begins_with("res://"):
		full_scene_path = "res://" + full_scene_path
	
	if ctx.debug_mode:
		print("Full scene path (with res://): " + full_scene_path)
	
	# Ensure the output path starts with res:// for Godot's resource system
	var full_output_path: String = params.output_path
	if not full_output_path.begins_with("res://"):
		full_output_path = "res://" + full_output_path
	
	if ctx.debug_mode:
		print("Full output path (with res://): " + full_output_path)
	
	# Check if the scene file exists
	var file_check: bool = FileAccess.file_exists(full_scene_path)
	if ctx.debug_mode:
		print("Scene file exists check: " + str(file_check))
	
	if not file_check:
		printerr("Scene file does not exist at: " + full_scene_path)
		# Get the absolute path for reference
		var absolute_path: String = ProjectSettings.globalize_path(full_scene_path)
		printerr("Absolute file path that doesn't exist: " + absolute_path)
		ctx.quit(1)
	
	# Load the scene
	if ctx.debug_mode:
		print("Loading scene from: " + full_scene_path)
	var scene: PackedScene = load(full_scene_path)
	if not scene:
		printerr("Failed to load scene: " + full_scene_path)
		ctx.quit(1)
	
	if ctx.debug_mode:
		print("Scene loaded successfully")
	
	# Instance the scene
	var scene_root: Node = scene.instantiate()
	if ctx.debug_mode:
		print("Scene instantiated")
	
	# Create a new MeshLibrary
	var mesh_library: MeshLibrary = MeshLibrary.new()
	if ctx.debug_mode:
		print("Created new MeshLibrary")
	
	# Get mesh item names if provided
	var mesh_item_names: Array = params.mesh_item_names if params.has("mesh_item_names") else []
	var use_specific_items: bool = mesh_item_names.size() > 0
	
	if ctx.debug_mode:
		if use_specific_items:
			print("Using specific mesh items: " + str(mesh_item_names))
		else:
			print("Using all mesh items in the scene")
	
	# Process all child nodes
	var item_id: int = 0
	if ctx.debug_mode:
		print("Processing child nodes...")
	
	for child in scene_root.get_children():
		if ctx.debug_mode:
			print("Checking child node: " + child.name)
		
		# Skip if not using all items and this item is not in the list
		if use_specific_items and not (child.name in mesh_item_names):
			if ctx.debug_mode:
				print("Skipping node " + child.name + " (not in specified items list)")
			continue
			
		# Check if the child has a mesh
		var mesh_instance: MeshInstance3D = null
		if child is MeshInstance3D:
			mesh_instance = child
			if ctx.debug_mode:
				print("Node " + child.name + " is a MeshInstance3D")
		else:
			# Try to find a MeshInstance3D in the child's descendants
			if ctx.debug_mode:
				print("Searching for MeshInstance3D in descendants of " + child.name)
			for descendant in child.get_children():
				if descendant is MeshInstance3D:
					mesh_instance = descendant
					if ctx.debug_mode:
						print("Found MeshInstance3D in descendant: " + descendant.name)
					break
		
		if mesh_instance and mesh_instance.mesh:
			if ctx.debug_mode:
				print("Adding mesh: " + child.name)
			
			# Add the mesh to the library
			mesh_library.create_item(item_id)
			mesh_library.set_item_name(item_id, child.name)
			mesh_library.set_item_mesh(item_id, mesh_instance.mesh)
			if ctx.debug_mode:
				print("Added mesh to library with ID: " + str(item_id))
			
			# Add collision shape if available
			var collision_added: bool = false
			for collision_child in child.get_children():
				if collision_child is CollisionShape3D and collision_child.shape:
					mesh_library.set_item_shapes(item_id, [collision_child.shape])
					if ctx.debug_mode:
						print("Added collision shape from: " + collision_child.name)
					collision_added = true
					break
			
			if ctx.debug_mode and not collision_added:
				print("No collision shape found for mesh: " + child.name)
			
			# Note: set_item_preview requires a Texture2D, which cannot be generated
			# in headless mode. Preview generation is skipped.
			if ctx.debug_mode:
				print("Skipping preview generation for: " + child.name + " (requires rendering)")
			
			item_id += 1
		elif ctx.debug_mode:
			print("Node " + child.name + " has no valid mesh")
	
	if ctx.debug_mode:
		print("Processed " + str(item_id) + " meshes")
	
	# Create directory if it doesn't exist
	var dir: DirAccess = DirAccess.open("res://")
	if dir == null:
		printerr("Failed to open res:// directory")
		printerr("DirAccess error: " + str(DirAccess.get_open_error()))
		ctx.quit(1)
		
	var output_dir: String = full_output_path.get_base_dir()
	if ctx.debug_mode:
		print("Output directory: " + output_dir)
	
	if output_dir != "res://" and not dir.dir_exists(output_dir.substr(6)):  # Remove "res://" prefix
		if ctx.debug_mode:
			print("Creating directory: " + output_dir)
		var error: int = dir.make_dir_recursive(output_dir.substr(6))  # Remove "res://" prefix
		if error != OK:
			printerr("Failed to create directory: " + output_dir + ", error: " + str(error))
			ctx.quit(1)
	
	# Save the mesh library
	if item_id > 0:
		if ctx.debug_mode:
			print("Saving MeshLibrary to: " + full_output_path)
		var error: int = ResourceSaver.save(mesh_library, full_output_path)
		if ctx.debug_mode:
			print("Save result: " + str(error) + " (OK=" + str(OK) + ")")
		
		if error == OK:
			# Verify the file was actually created
			if ctx.debug_mode:
				var file_check_after: bool = FileAccess.file_exists(full_output_path)
				print("File exists check after save: " + str(file_check_after))
				
				if file_check_after:
					print("MeshLibrary exported successfully with " + str(item_id) + " items to: " + full_output_path)
					# Get the absolute path for reference
					var absolute_path: String = ProjectSettings.globalize_path(full_output_path)
					print("Absolute file path: " + absolute_path)
				else:
					printerr("File reported as saved but does not exist at: " + full_output_path)
			else:
				print("MeshLibrary exported successfully with " + str(item_id) + " items to: " + full_output_path)
		else:
			printerr("Failed to save MeshLibrary: " + str(error))
	else:
		printerr("No valid meshes found in the scene")


## Get UID for a specific file
static func get_uid(ctx: SceneTree, params: Dictionary) -> void:
	if not params.has("file_path"):
		printerr("File path is required")
		ctx.quit(1)
	
	# Ensure the file path starts with res:// for Godot's resource system
	var file_path: String = params.file_path
	if not file_path.begins_with("res://"):
		file_path = "res://" + file_path
	
	print("Getting UID for file: " + file_path)
	if ctx.debug_mode:
		print("Full file path (with res://): " + file_path)
	
	# Get the absolute path for reference
	var absolute_path: String = ProjectSettings.globalize_path(file_path)
	if ctx.debug_mode:
		print("Absolute file path: " + absolute_path)
	
	# Ensure the file exists
	var file_check: bool = FileAccess.file_exists(file_path)
	if ctx.debug_mode:
		print("File exists check: " + str(file_check))
	
	if not file_check:
		printerr("File does not exist at: " + file_path)
		printerr("Absolute file path that doesn't exist: " + absolute_path)
		ctx.quit(1)
	
	# Check if the UID file exists
	var uid_path: String = file_path + ".uid"
	if ctx.debug_mode:
		print("UID file path: " + uid_path)
	
	var uid_check: bool = FileAccess.file_exists(uid_path)
	if ctx.debug_mode:
		print("UID file exists check: " + str(uid_check))
	
	var f: FileAccess = FileAccess.open(uid_path, FileAccess.READ)
	
	if f:
		# Read the UID content
		var uid_content: String = f.get_as_text()
		f.close()
		if ctx.debug_mode:
			print("UID content read successfully")
		
		# Return the UID content
		var result: Dictionary = {
			"file": file_path,
			"absolutePath": absolute_path,
			"uid": uid_content.strip_edges(),
			"exists": true
		}
		if ctx.debug_mode:
			print("UID result: " + JSON.stringify(result))
		print(JSON.stringify(result))
	else:
		if ctx.debug_mode:
			print("UID file does not exist or could not be opened")
		
		# UID file doesn't exist
		var result: Dictionary = {
			"file": file_path,
			"absolutePath": absolute_path,
			"exists": false,
			"message": "UID file does not exist for this file. Use resave_resources to generate UIDs."
		}
		if ctx.debug_mode:
			print("UID result: " + JSON.stringify(result))
		print(JSON.stringify(result))


## Resave all resources to update UID references
static func resave_resources(ctx: SceneTree, params: Dictionary) -> void:
	print("Resaving all resources to update UID references...")
	
	# Get project path if provided
	var project_path: String = "res://"
	if params.has("project_path"):
		project_path = params.project_path
		if not project_path.begins_with("res://"):
			project_path = "res://" + project_path
		if not project_path.ends_with("/"):
			project_path += "/"
	
	if ctx.debug_mode:
		print("Using project path: " + project_path)
	
	# Get all .tscn files
	if ctx.debug_mode:
		print("Searching for scene files in: " + project_path)
	var scenes: Array = ctx.find_files(project_path, ".tscn")
	if ctx.debug_mode:
		print("Found " + str(scenes.size()) + " scenes")
	
	# Resave each scene
	var success_count: int = 0
	var error_count: int = 0
	
	for scene_path in scenes:
		if ctx.debug_mode:
			print("Processing scene: " + scene_path)
		
		# Check if the scene file exists
		var file_check: bool = FileAccess.file_exists(scene_path)
		if ctx.debug_mode:
			print("Scene file exists check: " + str(file_check))
		
		if not file_check:
			printerr("Scene file does not exist at: " + scene_path)
			error_count += 1
			continue
		
		# Load the scene
		var scene: Resource = load(scene_path)
		if scene:
			if ctx.debug_mode:
				print("Scene loaded successfully, saving...")
			var error: int = ResourceSaver.save(scene, scene_path)
			if ctx.debug_mode:
				print("Save result: " + str(error) + " (OK=" + str(OK) + ")")
			
			if error == OK:
				success_count += 1
				if ctx.debug_mode:
					print("Scene saved successfully: " + scene_path)
				
					# Verify the file was actually updated
					var file_check_after: bool = FileAccess.file_exists(scene_path)
					print("File exists check after save: " + str(file_check_after))
				
					if not file_check_after:
						printerr("File reported as saved but does not exist at: " + scene_path)
			else:
				error_count += 1
				printerr("Failed to save: " + scene_path + ", error: " + str(error))
		else:
			error_count += 1
			printerr("Failed to load: " + scene_path)
	
	# Get all .gd and .shader files
	if ctx.debug_mode:
		print("Searching for script and shader files in: " + project_path)
	var scripts: Array = ctx.find_files(project_path, ".gd") + ctx.find_files(project_path, ".shader") + ctx.find_files(project_path, ".gdshader")
	if ctx.debug_mode:
		print("Found " + str(scripts.size()) + " scripts/shaders")
	
	# Check for missing .uid files
	var missing_uids: int = 0
	var generated_uids: int = 0
	
	for script_path in scripts:
		if ctx.debug_mode:
			print("Checking UID for: " + script_path)
		var uid_path: String = script_path + ".uid"
		
		var uid_check: bool = FileAccess.file_exists(uid_path)
		if ctx.debug_mode:
			print("UID file exists check: " + str(uid_check))
		
		var f: FileAccess = FileAccess.open(uid_path, FileAccess.READ)
		if not f:
			missing_uids += 1
			if ctx.debug_mode:
				print("Missing UID file for: " + script_path + ", generating...")
			
			# Force a save to generate UID
			var res: Resource = load(script_path)
			if res:
				var error: int = ResourceSaver.save(res, script_path)
				if ctx.debug_mode:
					print("Save result: " + str(error) + " (OK=" + str(OK) + ")")
				
				if error == OK:
					generated_uids += 1
					if ctx.debug_mode:
						print("Generated UID for: " + script_path)
					
						# Verify the UID file was actually created
						var uid_check_after: bool = FileAccess.file_exists(uid_path)
						print("UID file exists check after save: " + str(uid_check_after))
					
						if not uid_check_after:
							printerr("UID file reported as generated but does not exist at: " + uid_path)
				else:
					printerr("Failed to generate UID for: " + script_path + ", error: " + str(error))
			else:
				printerr("Failed to load resource: " + script_path)
		elif ctx.debug_mode:
			print("UID file already exists for: " + script_path)
	
	if ctx.debug_mode:
		print("Summary:")
		print("- Scenes processed: " + str(scenes.size()))
		print("- Scenes successfully saved: " + str(success_count))
		print("- Scenes with errors: " + str(error_count))
		print("- Scripts/shaders missing UIDs: " + str(missing_uids))
		print("- UIDs successfully generated: " + str(generated_uids))
	print("Resave operation complete")
