# SaveLoadManager.gd
# Autoload Singleton
# 负责处理游戏的保存和加载流程。
# 与 GameState 交互以获取/恢复状态数据。
# 将游戏状态以 JSON 格式存储在 user:// 目录下。

extends Node

# --- 常量 ---
const SAVE_FILENAME_PREFIX = "save_"
const SAVE_FILENAME_EXTENSION = ".json"


# --- 核心方法 ---

# 保存当前游戏状态到指定的槽位
# slot_id: 整数，用于区分不同的存档文件 (例如 1, 2, 3)
# 返回: bool - 保存是否成功
func save_game(slot_id: int) -> bool:
	print("SaveLoadManager: Attempting to save game to slot", slot_id)
	
	# 1. 获取需要保存的数据
	if not GameState:
		printerr("SaveLoadManager: GameState Autoload not found!")
		return false
		
	var game_state_data: Dictionary = GameState.get_savable_state()
	if game_state_data.is_empty() and OS.is_debug_build():
		# 在调试模式下，如果保存的数据为空，可能是一个警告信号
		print("SaveLoadManager: Warning - Game state data to save is empty.")
		# 根据游戏逻辑，这里可能允许空状态保存，也可能返回 false
		# return false 

	# 2. 准备完整的存档结构 (包含元数据)
	var save_data = {
		"metadata": {
			# 使用 ISO 8601 标准格式记录时间，更通用
			"save_time_iso": Time.get_datetime_string_from_system(true, true), 
			"game_version": ProjectSettings.get_setting("application/config/version", "unknown") # 获取项目版本
			# 可以添加其他元数据，如游戏内日期、截图路径等
		},
		"game_state": game_state_data
	}

	# 3. 序列化为 JSON 字符串
	# 使用制表符缩进，提高可读性，发布版可考虑移除缩进减小体积
	var json_string = JSON.stringify(save_data, "\t") 
	if json_string.is_empty() and not save_data.is_empty():
		printerr("SaveLoadManager: Failed to serialize game data to JSON.")
		return false

	# 4. 获取存档文件路径
	var save_path = _get_save_path(slot_id)
	if save_path.is_empty():
		printerr("SaveLoadManager: Invalid slot_id provided:", slot_id)
		return false

	# 5. 写入文件
	# 使用 FileAccess.open 进行文件操作
	var file = FileAccess.open(save_path, FileAccess.WRITE)
	if file == null:
		# 获取文件操作错误信息
		var error_code = FileAccess.get_open_error() 
		printerr("SaveLoadManager: Failed to open save file for writing at '", save_path, "'. Error code:", error_code)
		return false
	
	# 写入 JSON 字符串
	file.store_string(json_string)
	# file.close() # FileAccess 会在变量超出作用域时自动关闭，但显式关闭是好习惯

	print("SaveLoadManager: Game successfully saved to '", save_path, "'")
	return true


# 从指定的槽位加载游戏状态
# slot_id: 整数，要加载的存档文件槽位
# 返回: Variant - 成功时返回 game_state 字典，失败时返回 null
func load_game(slot_id: int) -> Variant: # <--- 修改返回类型为 Variant
	print("SaveLoadManager: Attempting to load game data from slot", slot_id)

	# 1. 获取存档文件路径 (不变)
	var save_path = _get_save_path(slot_id)
	if save_path.is_empty():
		printerr("SaveLoadManager: Invalid slot_id provided:", slot_id)
		return null # <--- 失败返回 null

	# 2. 检查文件是否存在 (不变)
	if not FileAccess.file_exists(save_path):
		printerr("SaveLoadManager: Save file not found at '", save_path, "'")
		return null # <--- 失败返回 null

	# 3. 读取文件内容 (不变)
	var file = FileAccess.open(save_path, FileAccess.READ)
	if file == null:
		var error_code = FileAccess.get_open_error()
		printerr("SaveLoadManager: Failed to open save file for reading at '", save_path, "'. Error code:", error_code)
		return null # <--- 失败返回 null
	var json_string = file.get_as_text()
	if json_string.is_empty():
		printerr("SaveLoadManager: Save file is empty or failed to read content from '", save_path, "'")
		return null # <--- 失败返回 null

	# 4. 解析 JSON 字符串 (不变)
	var parse_result = JSON.parse_string(json_string)
	if parse_result == null:
		printerr("SaveLoadManager: Failed to parse JSON from save file '", save_path, "'. File might be corrupted.")
		return null # <--- 失败返回 null
	if not parse_result is Dictionary:
		printerr("SaveLoadManager: Parsed JSON data is not a Dictionary in '", save_path, "'. Invalid format.")
		return null # <--- 失败返回 null

	var loaded_data: Dictionary = parse_result

	# 5. 验证存档结构并提取游戏状态 (不变)
	if not loaded_data.has("game_state"):
		printerr("SaveLoadManager: Save file '", save_path, "' is missing the 'game_state' key. Invalid format.")
		return null # <--- 失败返回 null
	var game_state_data = loaded_data["game_state"]
	if not game_state_data is Dictionary:
		printerr("SaveLoadManager: 'game_state' data in '", save_path, "' is not a Dictionary. Invalid format.")
		return null # <--- 失败返回 null

	print("SaveLoadManager: Game data successfully loaded from '", save_path, "'")
	# 7. 返回提取到的 game_state 数据字典
	return game_state_data # <--- 成功时返回字典

# 检查指定槽位的存档文件是否存在
func does_save_exist(slot_id: int) -> bool:
	var save_path = _get_save_path(slot_id)
	if save_path.is_empty():
		return false
	return FileAccess.file_exists(save_path)


# --- 辅助方法 ---

# 根据槽位 ID 构建完整的存档文件路径
# 返回: String - 完整的 user:// 路径，如果 slot_id 无效则返回空字符串
func _get_save_path(slot_id: int) -> String:
	# 基础验证，确保 slot_id 是正整数
	if slot_id <= 0: 
		printerr("SaveLoadManager: Invalid slot_id:", slot_id, ". Must be a positive integer.")
		return ""
		
	var filename = SAVE_FILENAME_PREFIX + str(slot_id) + SAVE_FILENAME_EXTENSION
	# "user://" 是 Godot 指向用户数据目录的特殊路径
	return "user://" + filename
