#ifndef EDITSCENE_GOAP_ACTION_HPP
#define EDITSCENE_GOAP_ACTION_HPP
#pragma once

#include "GoapBlackboard.hpp"
#include "BehaviorTree.hpp"
#include <Ogre.h>

/**
 * A GOAP action definition.
 *
 * Actions live in the ActionDatabase and can be executed by any character.
 * Each action has preconditions (required blackboard state),
 * effects (resulting blackboard state), a cost, and a behavior tree.
 */
struct GoapAction {
	Ogre::String name;
	int cost = 1;

	// GOAP preconditions and effects
	GoapBlackboard preconditions;
	GoapBlackboard effects;

	// Bitmask for precondition checking. Only bits set here are compared.
	// Defaults to all 1s (check all bits).
	uint64_t preconditionMask = ~0ULL;

	// Behavior tree to execute when this action is selected
	BehaviorTreeNode behaviorTree;

	// Optional: reference to a named behavior tree asset
	Ogre::String behaviorTreeName;

	GoapAction() = default;

	explicit GoapAction(const Ogre::String &name_, int cost_ = 1)
		: name(name_)
		, cost(cost_)
	{
	}

	// Check if the given blackboard satisfies this action's preconditions.
	// Only bits in preconditionMask are compared.
	bool canRun(const GoapBlackboard &blackboard) const
	{
		// Fast-path: if mask covers all set bits, use standard check
		if (preconditionMask == ~0ULL)
			return blackboard.satisfies(preconditions);

		// Masked check: only compare bits in preconditionMask
		uint64_t relevantBits = preconditionMask;
		uint64_t bbBits = blackboard.bits & relevantBits;
		uint64_t preBits = preconditions.bits & relevantBits;
		uint64_t bbMask = blackboard.mask & relevantBits;
		uint64_t preMask = preconditions.mask & relevantBits;

		// All precondition bits must be present in blackboard
		if ((bbMask & preMask) != preMask)
			return false;
		if ((bbBits & preMask) != preBits)
			return false;

		// Check integer values
		for (const auto &kv : preconditions.values) {
			if (!blackboard.hasValue(kv.first))
				return false;
			if (blackboard.getValue(kv.first) != kv.second)
				return false;
		}
		return true;
	}
};

#endif // EDITSCENE_GOAP_ACTION_HPP
