@tool
extends RefCounted
## Manages the conversation history in OpenAI message format.

const SAVE_PATH := "user://golem_chat.json"

const DEFAULT_SYSTEM_PROMPT := """You are Golem, an AI assistant embedded in the Godot 4.x editor. You help game developers build, debug, and optimize their projects.

You have direct access to the Godot editor via tools. Use them to inspect, build, and modify scenes live. Prefer tool calls over code suggestions when you can act directly.
Key workflow: get_scene_tree → add_nodes/update_property → save_scene → play_scene → get_logs/get_game_screenshot → stop_scene.
Always call save_scene after modifying nodes. Never edit .tscn files — use the scene tools instead.

Rules:
- Use GDScript 4.x syntax (typed variables, @onready, @export, signal keyword)
- Be concise. Code first, explain after. No boilerplate preambles
- Use ```gdscript fences for code blocks
- Use **bold** for emphasis, bullet lists for steps
- If a question is ambiguous, ask one clarifying question before guessing
- Common pitfalls to flag: := on Variant sources, global_position before add_child, add_child during physics flush, create_tween on dying nodes, queue_free is end-of-frame"""

var _messages: Array[Dictionary] = []


func _init() -> void:
	_messages.append({"role": "system", "content": DEFAULT_SYSTEM_PROMPT})


func add_user_message(content: String) -> void:
	_messages.append({"role": "user", "content": content})


func add_assistant_message(content: String) -> void:
	_messages.append({"role": "assistant", "content": content})


func add_assistant_tool_calls(tool_calls: Array) -> void:
	## Store an assistant message that contains tool_calls (no text content).
	_messages.append({"role": "assistant", "content": null, "tool_calls": tool_calls})


func add_tool_result(tool_call_id: String, content: String) -> void:
	## Store a tool result message.
	_messages.append({"role": "tool", "tool_call_id": tool_call_id, "content": content})


func set_system_prompt(content: String) -> void:
	if _messages.size() > 0 and _messages[0].get("role") == "system":
		_messages[0]["content"] = content
	else:
		_messages.insert(0, {"role": "system", "content": content})


func get_messages() -> Array:
	return _messages


func clear() -> void:
	var system := DEFAULT_SYSTEM_PROMPT
	if _messages.size() > 0 and _messages[0].get("role") == "system":
		system = _messages[0]["content"]
	_messages.clear()
	_messages.append({"role": "system", "content": system})


func message_count() -> int:
	return _messages.size()


func save_to_file() -> void:
	var to_save: Array = []
	for i in range(1, _messages.size()):
		to_save.append(_messages[i])
	if to_save.is_empty():
		return
	var file := FileAccess.open(SAVE_PATH, FileAccess.WRITE)
	if file:
		file.store_string(JSON.stringify(to_save))


func load_from_file() -> bool:
	if not FileAccess.file_exists(SAVE_PATH):
		return false
	var file := FileAccess.open(SAVE_PATH, FileAccess.READ)
	if not file:
		return false
	var json := JSON.new()
	if json.parse(file.get_as_text()) != OK:
		return false
	var data: Variant = json.data
	if not data is Array:
		return false
	for msg in data:
		if msg is Dictionary and msg.has("role") and msg.has("content"):
			_messages.append(msg)
	return _messages.size() > 1


func delete_save() -> void:
	if FileAccess.file_exists(SAVE_PATH):
		DirAccess.remove_absolute(
			ProjectSettings.globalize_path(SAVE_PATH)
		)
