#ifndef EDITSCENE_ITEMREGISTRY_HPP
#define EDITSCENE_ITEMREGISTRY_HPP
#pragma once

#include <Ogre.h>
#include <nlohmann/json.hpp>
#include <string>
#include <unordered_map>
#include <vector>

class EditorApp;

/**
 * Global item definition registry.
 *
 * Stores authoritative item definitions keyed by itemId.
 * Auto-saves to items.json after mutations.
 * Loaded on initialization.
 */
class ItemRegistry {
public:
	static ItemRegistry &getSingleton();
	static ItemRegistry *getSingletonPtr();

private:
	static ItemRegistry *ms_singleton;

public:
	/* ------------------------------------------------------------------ */
	/*  Column schema                                                       */
	/* ------------------------------------------------------------------ */
	struct ColumnDef {
		enum Type { Int, Float, String };
		Type type;
		std::string name;
	};

	/* ------------------------------------------------------------------ */
	/*  Item definition                                                     */
	/* ------------------------------------------------------------------ */
	struct ItemDefinition {
		std::string itemId;
		std::string itemName;
		std::string itemType;
		int maxStackSize = 99;
		float weight = 0.1f;
		int value = 1;
		std::string useActionName;
		bool unique = false;

		/* Extensible custom columns */
		std::unordered_map<std::string, int64_t> intColumns;
		std::unordered_map<std::string, double> floatColumns;
		std::unordered_map<std::string, std::string> stringColumns;
	};

	/* ------------------------------------------------------------------ */
	/*  Life-cycle                                                          */
	/* ------------------------------------------------------------------ */
	ItemRegistry();
	~ItemRegistry() = default;

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

	void initialize();

	/* ------------------------------------------------------------------ */
	/*  Definitions                                                         */
	/* ------------------------------------------------------------------ */
	bool registerItem(const ItemDefinition &def);
	bool removeItem(const std::string &itemId);
	ItemDefinition *findDefinition(const std::string &itemId);
	const ItemDefinition *findDefinition(const std::string &itemId) const;
	const std::unordered_map<std::string, ItemDefinition> &getDefinitions() const
	{
		return m_definitions;
	}

	bool hasItem(const std::string &itemId) const
	{
		return m_definitions.find(itemId) != m_definitions.end();
	}

	bool isUnique(const std::string &itemId) const;

	/* Lookup helpers */
	std::string getItemName(const std::string &itemId) const;
	std::string getItemType(const std::string &itemId) const;
	int getMaxStackSize(const std::string &itemId) const;
	float getWeight(const std::string &itemId) const;
	int getValue(const std::string &itemId) const;
	std::string getUseActionName(const std::string &itemId) const;

	/* ------------------------------------------------------------------ */
	/*  Columns                                                             */
	/* ------------------------------------------------------------------ */
	void addColumn(const std::string &name, ColumnDef::Type type);
	void removeColumn(const std::string &name);
	const std::vector<ColumnDef> &getColumns() const
	{
		return m_columns;
	}

	/* ------------------------------------------------------------------ */
	/*  Persistence                                                         */
	/* ------------------------------------------------------------------ */
	nlohmann::json serialize() const;
	void deserialize(const nlohmann::json &j);

	bool saveToFile(const std::string &filepath);
	bool loadFromFile(const std::string &filepath);
	const std::string &getLastError() const
	{
		return m_lastError;
	}

	void autoSave();

	/* ------------------------------------------------------------------ */
	/*  ImGui editor                                                        */
	/* ------------------------------------------------------------------ */
	void drawEditor(bool *p_open = nullptr);

private:
	std::unordered_map<std::string, ItemDefinition> m_definitions;
	std::vector<ColumnDef> m_columns;
	mutable std::string m_lastError;
	std::string m_autoSavePath;

	/* UI state */
	int m_selectedItemIndex = -1;
	char m_newItemIdBuf[128] = {};
	char m_newItemNameBuf[128] = {};
};

#endif // EDITSCENE_ITEMREGISTRY_HPP
