#ifndef EDITSCENE_CHARACTER_CLASS_DATABASE_HPP
#define EDITSCENE_CHARACTER_CLASS_DATABASE_HPP
#pragma once

#include "Formula.hpp"
#include <Ogre.h>
#include <unordered_map>
#include <vector>

/**
 * Global character class database singleton.
 *
 * Holds the master list of stat/skill/need definitions and class templates.
 * This is a singleton accessible from anywhere in the codebase.
 * Persisted to character_class.json, read-only in game mode.
 */
class CharacterClassDatabase {
public:
	static CharacterClassDatabase &getSingleton();
	static CharacterClassDatabase *getSingletonPtr();

	// -----------------------------------------------------------------------
	// Definitions
	// -----------------------------------------------------------------------

	enum class StatKind {
		Attribute,   // permanent value (strength, agility)
		ResourcePool // depletable pool (health, stamina, mana)
	};

	struct StatDef {
		Ogre::String name;
		Ogre::String displayName;
		StatKind kind = StatKind::Attribute;
		int minValue = 1;
		int maxValue = 999;
	};

	struct SkillDef {
		Ogre::String name;
		Ogre::String displayName;
		int maxValue = 100;
	};

	struct NeedDef {
		Ogre::String name;
		Ogre::String displayName;
		int maxValue = 1000;
		float accumulationRate = 0.0f;
		int lowThreshold = 0;   // clear bit when need <= this
		int highThreshold = 1000; // set bit when need >= this
		Ogre::String bitName;   // GOAP blackboard bit (hysteresis)
	};

	struct ClassDef {
		Ogre::String name;
		Ogre::String description;
		std::vector<Ogre::String> primaryStats;
		std::unordered_map<Ogre::String, int> baseStats;
		std::unordered_map<Ogre::String, int> baseSkills;
		std::unordered_map<Ogre::String, int> baseNeeds;
		Formula xpForLevel;
		Formula pointsPerLevel;
		Formula statCost;
		std::unordered_map<Ogre::String, Formula> statGrowth;
		std::unordered_map<Ogre::String, Formula> skillGrowth;
	};

	// -----------------------------------------------------------------------
	// Lookup
	// -----------------------------------------------------------------------

	const StatDef *findStat(const Ogre::String &name) const;
	const SkillDef *findSkill(const Ogre::String &name) const;
	const NeedDef *findNeed(const Ogre::String &name) const;
	const ClassDef *findClass(const Ogre::String &name) const;

	StatDef *findStat(const Ogre::String &name);
	SkillDef *findSkill(const Ogre::String &name);
	NeedDef *findNeed(const Ogre::String &name);
	ClassDef *findClass(const Ogre::String &name);

	// -----------------------------------------------------------------------
	// Mutators
	// -----------------------------------------------------------------------

	void addOrReplaceStat(const StatDef &def);
	void addOrReplaceSkill(const SkillDef &def);
	void addOrReplaceNeed(const NeedDef &def);
	void addOrReplaceClass(const ClassDef &def);

	bool removeStat(const Ogre::String &name);
	bool removeSkill(const Ogre::String &name);
	bool removeNeed(const Ogre::String &name);
	bool removeClass(const Ogre::String &name);

	void clear();

	// -----------------------------------------------------------------------
	// Lists
	// -----------------------------------------------------------------------

	const std::vector<Ogre::String> &getStatNames() const
	{
		return m_statNames;
	}
	const std::vector<Ogre::String> &getSkillNames() const
	{
		return m_skillNames;
	}
	const std::vector<Ogre::String> &getNeedNames() const
	{
		return m_needNames;
	}
	const std::vector<Ogre::String> &getClassNames() const
	{
		return m_classNames;
	}

	// -----------------------------------------------------------------------
	// Persistence
	// -----------------------------------------------------------------------

	static bool saveToJson(const std::string &filename);
	static bool loadFromJson(const std::string &filename);

	// -----------------------------------------------------------------------
	// Runtime helpers
	// -----------------------------------------------------------------------

	int64_t computeXPForLevel(int level, const ClassDef &cls) const;
	int computePointsForLevel(int level, const ClassDef &cls) const;
	int computeStatGrowth(const Ogre::String &stat, int level,
			      const ClassDef &cls) const;
	int computeSkillGrowth(const Ogre::String &skill, int level,
			       const ClassDef &cls) const;
	int computeStatCost(int currentValue, const ClassDef &cls) const;

private:
	CharacterClassDatabase() = default;

	std::unordered_map<Ogre::String, StatDef> m_stats;
	std::unordered_map<Ogre::String, SkillDef> m_skills;
	std::unordered_map<Ogre::String, NeedDef> m_needs;
	std::unordered_map<Ogre::String, ClassDef> m_classes;

	std::vector<Ogre::String> m_statNames;
	std::vector<Ogre::String> m_skillNames;
	std::vector<Ogre::String> m_needNames;
	std::vector<Ogre::String> m_classNames;
};

#endif // EDITSCENE_CHARACTER_CLASS_DATABASE_HPP
