#include "ContainerStateRegistry.hpp"
#include <OgreLogManager.h>
#include <fstream>

ContainerStateRegistry &ContainerStateRegistry::getInstance()
{
	static ContainerStateRegistry instance;
	return instance;
}

ContainerStateRegistry::ContainerStateRegistry()
{
	m_autoSavePath = "container_state.json";
}

void ContainerStateRegistry::loadState(const std::string &containerId,
				       const std::vector<ContainerSlot> &slots)
{
	ContainerState &state = m_states[containerId];
	state.containerId = containerId;
	state.slots = slots;
	autoSave();
}

std::vector<ContainerStateRegistry::ContainerSlot>
ContainerStateRegistry::getState(const std::string &containerId) const
{
	auto it = m_states.find(containerId);
	if (it != m_states.end())
		return it->second.slots;
	return {};
}

bool ContainerStateRegistry::hasState(const std::string &containerId) const
{
	return m_states.find(containerId) != m_states.end();
}

void ContainerStateRegistry::clearState(const std::string &containerId)
{
	m_states.erase(containerId);
	autoSave();
}

nlohmann::json ContainerStateRegistry::serialize() const
{
	nlohmann::json j;
	j["version"] = "1.0";
	for (const auto &pair : m_states) {
		const ContainerState &state = pair.second;
		nlohmann::json stateJson;
		stateJson["containerId"] = state.containerId;
		nlohmann::json slotsJson = nlohmann::json::array();
		for (const auto &slot : state.slots) {
			nlohmann::json slotJson;
			slotJson["itemId"] = slot.itemId;
			slotJson["stackSize"] = slot.stackSize;
			slotsJson.push_back(slotJson);
		}
		stateJson["slots"] = slotsJson;
		j["states"].push_back(stateJson);
	}
	return j;
}

void ContainerStateRegistry::deserialize(const nlohmann::json &j)
{
	m_states.clear();
	if (!j.contains("states"))
		return;
	for (const auto &stateJson : j["states"]) {
		ContainerState state;
		state.containerId = stateJson.value("containerId", "");
		if (stateJson.contains("slots") && stateJson["slots"].is_array()) {
			for (const auto &slotJson : stateJson["slots"]) {
				ContainerSlot slot;
				slot.itemId = slotJson.value("itemId", "");
				slot.stackSize = slotJson.value("stackSize", 0);
				state.slots.push_back(slot);
			}
		}
		if (!state.containerId.empty())
			m_states[state.containerId] = state;
	}
}

bool ContainerStateRegistry::saveToFile(const std::string &filepath)
{
	try {
		std::ofstream file(filepath);
		if (!file.is_open()) {
			m_lastError = "Cannot open " + filepath;
			return false;
		}
		file << serialize().dump(4);
		return true;
	} catch (const std::exception &e) {
		m_lastError = std::string("Save error: ") + e.what();
		return false;
	}
}

bool ContainerStateRegistry::loadFromFile(const std::string &filepath)
{
	try {
		std::ifstream file(filepath);
		if (!file.is_open()) {
			m_lastError = "Cannot open " + filepath;
			return false;
		}
		nlohmann::json j;
		file >> j;
		deserialize(j);
		return true;
	} catch (const std::exception &e) {
		m_lastError = std::string("Load error: ") + e.what();
		return false;
	}
}

void ContainerStateRegistry::autoSave()
{
	if (!m_autoSavePath.empty())
		saveToFile(m_autoSavePath);
}
