#ifndef EDITSCENE_CHARACTER_CLASS_SYSTEM_HPP
#define EDITSCENE_CHARACTER_CLASS_SYSTEM_HPP
#pragma once

#include <flecs.h>
#include <Ogre.h>
#include <unordered_set>
#include <string>
#include <nlohmann/json.hpp>

class EditorApp;

/**
 * Configuration for the character sheet / inventory dialog.
 * Loaded from / saved to inventory_config.json.
 */
struct InventoryDialogConfig {
	std::string fontPath = "";
	float fontSize = 16.0f;

	nlohmann::json serialize() const
	{
		nlohmann::json j;
		j["fontPath"] = fontPath;
		j["fontSize"] = fontSize;
		return j;
	}

	void deserialize(const nlohmann::json &j)
	{
		if (j.contains("fontPath") && j["fontPath"].is_string())
			fontPath = j["fontPath"].get<std::string>();
		if (j.contains("fontSize") && j["fontSize"].is_number())
			fontSize = j["fontSize"].get<float>();
	}

	bool loadFromFile(const std::string &filepath);
	bool saveToFile(const std::string &filepath);

	/**
	 * Load the configured font into ImGui via Ogre's ImGuiOverlay.
	 * Should be called once during setup, before the overlay is shown.
	 */
	void prepareFont(class EditorApp *editorApp);
};

/**
 * System that manages character progression, need accumulation,
 * and level-up logic.
 *
 * - Accumulates needs each frame based on class database rates.
 * - Sets/clears GOAP blackboard bits when needs cross thresholds.
 * - Checks XP and triggers level-ups.
 * - AI entities auto-distribute stat points.
 * - Player entities get a level-up dialog.
 *
 * All mutable RPG data lives in the CharacterRegistry table;
 * this system looks it up via CharacterIdentityComponent.
 */
class CharacterClassSystem {
public:
	CharacterClassSystem(flecs::world &world, EditorApp *editorApp);
	~CharacterClassSystem();

	/** Call every frame. Handles need ticks, level-up checks, dialog. */
	void update(float deltaTime);

	/** Render level-up and character-sheet dialogs (inside ImGui frame). */
	void renderDialogs();

	/** Manually add XP to an entity. Returns true if a level up occurred. */
	bool addXP(flecs::entity entity, int64_t amount);

	/** Distribute one point to a stat (player manual or scripted). */
	bool distributePoint(flecs::entity entity,
			     const Ogre::String &statName);

	/** Toggle character sheet for the given entity. */
	void toggleCharacterSheet(flecs::entity entity);

	/** Check if the character sheet is currently open for any entity. */
	bool isSheetOpen() const
	{
		return !m_sheets.empty();
	}

	/** Get the inventory dialog configuration. */
	InventoryDialogConfig &getConfig()
	{
		return m_config;
	}

	/** Set the inventory dialog configuration (from editor UI). */
	void setConfig(const InventoryDialogConfig &cfg)
	{
		m_config = cfg;
	}

private:
	void accumulateNeeds(float deltaTime);
	void updateNeedBits(flecs::entity entity);
	void checkLevelUps();
	void applyLevelUp(flecs::entity entity);
	void applyLevelUpGrowthAndPoints(flecs::entity entity);
	void distributePointsAI(flecs::entity entity);
	void renderLevelUpDialog(flecs::entity entity);
	void renderCharacterSheet(flecs::entity entity);

	flecs::world &m_world;
	EditorApp *m_editorApp;

	// Track which entities have an open level-up dialog
	std::unordered_set<flecs::entity_t> m_levelUpDialogs;
	// Track which entities have an open character sheet
	std::unordered_set<flecs::entity_t> m_sheets;

	// Inventory dialog configuration
	InventoryDialogConfig m_config;
};

#endif // EDITSCENE_CHARACTER_CLASS_SYSTEM_HPP
