#ifndef EDITSCENE_ACTION_DATABASE_HPP
#define EDITSCENE_ACTION_DATABASE_HPP
#pragma once

#include "GoapAction.hpp"
#include "GoapGoal.hpp"
#include <vector>
#include <unordered_map>
#include <string>

// Forward declaration for reloadFromSceneComponents
namespace flecs
{
class world;
}

/**
 * Global action database singleton.
 *
 * Holds the master list of GOAP actions and goals that characters can use.
 * This is a singleton accessible from anywhere in the codebase.
 * The ActionDatabaseComponent on a scene entity stores the actions/goals
 * and syncs them to the singleton on scene load.
 */
class ActionDatabase {
public:
	/** Get the singleton instance */
	static ActionDatabase &getSingleton();
	static ActionDatabase *getSingletonPtr();

	std::vector<GoapAction> actions;
	std::vector<GoapGoal> goals;

	// Find an action by name
	const GoapAction *findAction(const Ogre::String &name) const;
	GoapAction *findAction(const Ogre::String &name);

	// Find a goal by name
	const GoapGoal *findGoal(const Ogre::String &name) const;
	GoapGoal *findGoal(const Ogre::String &name);

	// Add or replace an action by name
	void addOrReplaceAction(const GoapAction &action);

	// Add or replace a goal by name
	void addOrReplaceGoal(const GoapGoal &goal);

	// Remove an action by name
	bool removeAction(const Ogre::String &name);

	// Remove a goal by name
	bool removeGoal(const Ogre::String &name);

	// Select the best valid goal for a given blackboard
	// Returns nullptr if no valid goal exists
	const GoapGoal *selectBestGoal(const GoapBlackboard &blackboard) const;

	// Build a list of actions that can run from a given blackboard state
	std::vector<const GoapAction *>
	getValidActions(const GoapBlackboard &blackboard) const;

	// Clear all actions and goals
	void clear();

	/**
	 * Save the action database to a JSON file.
	 * Creates a backup of the existing file (if any) by appending ".bak".
	 * The file is written to the filesystem path resolved from the
	 * "General" resource group.
	 *
	 * @param filename The filename (e.g. "actions.json").
	 * @return true on success.
	 */
	static bool saveToJson(const std::string &filename);

	/**
	 * Load the action database from a JSON file.
	 * The file is located via the "General" resource group.
	 * On failure (file not found, parse error) the error is logged
	 * and the database is left unchanged.
	 *
	 * @param filename The filename (e.g. "actions.json").
	 * @return true on success.
	 */
	static bool loadFromJson(const std::string &filename);

	/**
	 * Re-process all ActionDatabaseComponent entities in the given
	 * Flecs world: clear the singleton and re-sync from every entity
	 * that carries the component.  This is used after a reload so
	 * scene-defined actions are re-applied on top of the file.
	 */
	static void reloadFromSceneComponents(flecs::world &world);

private:
	ActionDatabase() = default;
	~ActionDatabase() = default;
	ActionDatabase(const ActionDatabase &) = delete;
	ActionDatabase &operator=(const ActionDatabase &) = delete;
};

/**
 * Flecs component that stores action database data on a scene entity.
 * When set on an entity, it syncs its contents to the ActionDatabase singleton.
 */
struct ActionDatabaseComponent {
	std::vector<GoapAction> actions;
	std::vector<GoapGoal> goals;

	/** Sync this component's data to the ActionDatabase singleton */
	void syncToSingleton() const;
};

#endif // EDITSCENE_ACTION_DATABASE_HPP
