@tool
extends Node

## Handles play/stop scene, error/log collection from the running game.
## Game logs are captured by the GolemCapture autoload and written to
## user://golem_game_logs.txt. This handler reads that file.

const GAME_LOG_PATH := "user://golem_game_logs.txt"
const ENGINE_LOG_SUFFIX := "/logs/godot.log"

var _errors: Array[String] = []
var _engine_log_path: String = ""
var _engine_log_position: int = 0


func register(server: Node) -> void:
	server.register_handler("play_scene", _play_scene)
	server.register_handler("stop_scene", _stop_scene)
	server.register_handler("get_errors", _get_errors)
	server.register_handler("get_logs", _get_logs)
	server.register_handler("clear_logs", _clear_logs)


func _ready() -> void:
	if Engine.is_editor_hint():
		_engine_log_path = OS.get_user_data_dir() + ENGINE_LOG_SUFFIX


func _play_scene(args: Dictionary) -> Dictionary:
	var scene_path: String = args.get("path", "")

	if EditorInterface.is_playing_scene():
		return {"ok": false, "error": "A scene is already running. Stop it first."}

	# Mark engine log position and clear game logs
	_mark_engine_log_position()
	_clear_game_logs()

	if scene_path.is_empty():
		EditorInterface.play_current_scene()
	else:
		if not FileAccess.file_exists(scene_path):
			return {"ok": false, "error": "Scene file not found: %s" % scene_path}
		EditorInterface.play_custom_scene(scene_path)

	return {"ok": true, "type": "text", "result": "Scene started: %s" % (scene_path if scene_path else "current scene")}


func _stop_scene(_args: Dictionary) -> Dictionary:
	if not EditorInterface.is_playing_scene():
		return {"ok": false, "error": "No scene is currently running"}

	EditorInterface.stop_playing_scene()
	return {"ok": true, "type": "text", "result": "Scene stopped"}


func _get_errors(_args: Dictionary) -> Dictionary:
	if _errors.size() == 0:
		return {"ok": true, "type": "text", "result": "No errors recorded."}
	return {"ok": true, "type": "text", "result": "\n".join(_errors)}


func _get_logs(args: Dictionary) -> Dictionary:
	var max_lines: int = args.get("max_lines", 100)
	var source: String = args.get("source", "game")  # "game", "engine", or "all"

	var sections: PackedStringArray = []

	# Game logs (from GolemCapture autoload)
	if source == "game" or source == "all":
		var game_logs := _read_game_logs(max_lines)
		if not game_logs.is_empty():
			if source == "all":
				sections.append("=== Game Logs ===")
			sections.append(game_logs)

	# Engine logs (from godot.log)
	if source == "engine" or source == "all":
		var engine_logs := _read_engine_logs(max_lines)
		if not engine_logs.is_empty():
			if source == "all":
				sections.append("\n=== Engine Logs ===")
			sections.append(engine_logs)

	if sections.size() == 0:
		if source == "game":
			return {"ok": true, "type": "text", "result": "No game logs. Use GolemCapture.log() in your scripts instead of print() to capture output."}
		return {"ok": true, "type": "text", "result": "No logs available."}

	return {"ok": true, "type": "text", "result": "\n".join(sections)}


func _clear_logs(_args: Dictionary) -> Dictionary:
	_errors.clear()
	_clear_game_logs()
	_mark_engine_log_position()
	return {"ok": true, "type": "text", "result": "Logs cleared"}


# ------------------------------------------------------------------
# Game logs (from GolemCapture autoload file)
# ------------------------------------------------------------------

func _read_game_logs(max_lines: int) -> String:
	var abs_path := ProjectSettings.globalize_path(GAME_LOG_PATH)
	if not FileAccess.file_exists(abs_path) and not FileAccess.file_exists(GAME_LOG_PATH):
		return ""

	var file := FileAccess.open(GAME_LOG_PATH, FileAccess.READ)
	if file == null:
		return ""

	var content := file.get_as_text().strip_edges()
	file.close()

	if content.is_empty():
		return ""

	var lines := content.split("\n")
	if lines.size() > max_lines:
		lines = lines.slice(lines.size() - max_lines, lines.size())

	return "\n".join(lines)


func _clear_game_logs() -> void:
	# Truncate the game log file
	var file := FileAccess.open(GAME_LOG_PATH, FileAccess.WRITE)
	if file:
		file.store_string("")
		file.close()


# ------------------------------------------------------------------
# Engine logs (from godot.log)
# ------------------------------------------------------------------

func _read_engine_logs(max_lines: int) -> String:
	if _engine_log_path.is_empty() or not FileAccess.file_exists(_engine_log_path):
		return ""

	var file := FileAccess.open(_engine_log_path, FileAccess.READ)
	if file == null:
		return ""

	if _engine_log_position > 0:
		file.seek(_engine_log_position)

	var content := file.get_as_text().strip_edges()
	file.close()

	if content.is_empty():
		return ""

	var lines := content.split("\n")
	if lines.size() > max_lines:
		lines = lines.slice(lines.size() - max_lines, lines.size())

	return "\n".join(lines)


func _mark_engine_log_position() -> void:
	if _engine_log_path.is_empty() or not FileAccess.file_exists(_engine_log_path):
		return
	var file := FileAccess.open(_engine_log_path, FileAccess.READ)
	if file:
		file.seek_end()
		_engine_log_position = file.get_position()
		file.close()


# Called externally to feed errors in
func push_error_message(msg: String) -> void:
	_errors.append(msg)
