#pragma once

#include <frostbite2D/types/type_alias.h>
#include <json/json.hpp>
#include <optional>
#include <string>
#include <vector>

namespace frostbite2D {

/**
 * @brief Save system runtime configuration.
 */
struct SaveSystemConfig {
  int32 slotCount = 10;
  std::string saveRoot = ".save";
  std::string indexFile = "index.json";
  std::string slotPrefix = "slot_";
};

/**
 * @brief Optional display metadata stored in each slot document.
 */
struct SaveMeta {
  std::string displayName;
  double playTimeSeconds = 0.0;
  std::string userTag;
};

/**
 * @brief Cached per-slot summary used by save slot list UI.
 */
struct SaveSlotInfo {
  int32 slot = -1;
  bool exists = false;
  std::string updatedAtUtc;
  uint64 fileSize = 0;
  int32 schemaVersion = 1;
  SaveMeta meta;
};

/**
 * @brief Manual save/load service using Asset as the only filesystem backend.
 */
class SaveSystem {
public:
  /**
   * @brief Get singleton instance.
   */
  static SaveSystem& get();

  SaveSystem(const SaveSystem&) = delete;
  SaveSystem& operator=(const SaveSystem&) = delete;

  /**
   * @brief Initialize save root, slot cache and index file.
   */
  bool init(const SaveSystemConfig& config = SaveSystemConfig{});

  /**
   * @brief Save payload into a fixed slot and update slot index metadata.
   */
  bool saveSlot(int32 slot, const nlohmann::json& payload,
                const SaveMeta& meta = SaveMeta{});

  /**
   * @brief Load payload object from a slot.
   */
  std::optional<nlohmann::json> loadSlotPayload(int32 slot) const;

  /**
   * @brief Query summary info for one slot.
   */
  std::optional<SaveSlotInfo> getSlotInfo(int32 slot) const;

  /**
   * @brief List summary info of all slots.
   */
  std::vector<SaveSlotInfo> listSlots() const;

  /**
   * @brief Delete a slot file and clear its index entry.
   */
  bool deleteSlot(int32 slot);

  /**
   * @brief Check whether slot has an existing save file.
   */
  bool hasSlot(int32 slot) const;

private:
  SaveSystem() = default;
  ~SaveSystem() = default;

  bool isValidSlot(int32 slot) const;
  void resetSlots();
  bool ensureSaveDirectory() const;
  bool refreshSlotsFromDisk();
  bool tryReadSlotDocument(int32 slot, nlohmann::json& outDoc) const;
  bool writeIndexFile() const;

  std::string indexPath() const;
  std::string slotPath(int32 slot) const;
  std::string slotFileName(int32 slot) const;

  static std::string makeUtcTimestamp();
  static nlohmann::json toJson(const SaveMeta& meta);
  static SaveMeta fromJson(const nlohmann::json& json);

  SaveSystemConfig config_;
  std::vector<SaveSlotInfo> slots_;
  bool initialized_ = false;
};

} // namespace frostbite2D
