#ifndef EDITSCENE_BEHAVIOR_TREE_HPP
#define EDITSCENE_BEHAVIOR_TREE_HPP
#pragma once

#include <Ogre.h>
#include <vector>

/**
 * Data-driven behavior tree node for AI action execution.
 *
 * Node types:
 *   "sequence"         - Execute children in order until one fails
 *   "selector"         - Execute children in order until one succeeds
 *   "invert"           - Invert the result of a single child
 *   "task"             - Leaf action (references a named task)
 *   "check"            - Leaf condition (references a named check)
 *   "debugPrint"       - Leaf: prints 'name' to console once when active
 *   "setAnimationState"- Leaf: sets animation state (name="SM/State")
 *   "isAnimationEnded" - Leaf check: true if anim in state machine ended
 *   "setBit"           - Leaf: sets blackboard bit (name=bit, params=0/1)
 *   "checkBit"         - Leaf check: true if blackboard bit is set
 *   "setValue"         - Leaf: sets blackboard value (name=key, params=val)
 *   "checkValue"       - Leaf check: blackboard comparison (name=key, params="op val")
 *   "blackboardDump"   - Leaf: dumps entire blackboard to log
 *   "delay"            - Leaf: waits for N seconds (params=seconds as float)
 *   "teleportToChild"  - Leaf: teleports character to a named child entity
 *                        of the Smart Object being interacted with.
 *                        name = child entity name to teleport to.
 *                        The character is positioned at the child's absolute
 *                        world transform (position + orientation).
 *   "disablePhysics"   - Leaf: removes character's JPH::BodyID from physics
 *                        system so physics no longer interferes with animation.
 *   "enablePhysics"    - Leaf: re-adds character's JPH::BodyID to physics
 *                        system to restore physics simulation.
 *
 *   --- Item / Inventory nodes ---
 *   "hasItem"          - Leaf check: true if character's inventory has an item
 *                        matching the given itemId (name=itemId).
 *   "hasItemByName"    - Leaf check: true if character's inventory has an item
 *                        matching the given itemName (name=itemName).
 *   "countItem"        - Leaf check: true if character's inventory has at least
 *                        N of itemId (name=itemId, params=count as int).
 *   "pickupItem"       - Leaf: picks up the nearest ItemComponent entity within
 *                        range into the character's inventory.
 *                        name=itemId filter (optional, empty = any).
 *   "dropItem"         - Leaf: drops an item from inventory into the world.
 *                        name=itemId, params=count (optional, default 1).
 *   "useItem"          - Leaf: uses an item from inventory (executes its
 *                        useAction behavior tree). name=itemId.
 *   "addItemToInventory"- Leaf: adds an item directly to character's inventory
 *                        (for quest rewards, etc.).
 *                        params="itemId,itemName,itemType,count,weight,value"
 *
 *   --- Lua node ---
 *   "luaTask"          - Leaf: calls a registered Lua function.
 *                        name = registered node handler name.
 *                        params = "key=val,key2=val2" passed to the Lua function.
 *                        The Lua function receives (entity_id, params_table)
 *                        and must return "success", "failure", or "running".
 *                        Register handlers via:
 *                          ecs.behavior_tree.register_node("name", function)
 */
struct BehaviorTreeNode {
	Ogre::String type = "task";
	Ogre::String name; // Action/condition name, or message, or SM/State
	Ogre::String params; // Optional extra parameters
	std::vector<BehaviorTreeNode> children;

	BehaviorTreeNode() = default;

	BehaviorTreeNode *findChild(const Ogre::String &childName)
	{
		for (auto &child : children) {
			if (child.name == childName)
				return &child;
		}
		return nullptr;
	}

	const BehaviorTreeNode *findChild(const Ogre::String &childName) const
	{
		for (const auto &child : children) {
			if (child.name == childName)
				return &child;
		}
		return nullptr;
	}

	bool canHaveChildren() const
	{
		return type == "sequence" || type == "selector" ||
		       type == "invert";
	}

	bool isLeaf() const
	{
		return type == "task" || type == "check" ||
		       type == "debugPrint" || type == "setAnimationState" ||
		       type == "isAnimationEnded" || type == "setBit" ||
		       type == "checkBit" || type == "setValue" ||
		       type == "checkValue" || type == "blackboardDump" ||
		       type == "delay" || type == "teleportToChild" ||
		       type == "disablePhysics" || type == "enablePhysics" ||
		       type == "sendEvent" || type == "hasItem" ||
		       type == "hasItemByName" || type == "countItem" ||
		       type == "pickupItem" || type == "dropItem" ||
		       type == "useItem" || type == "addItemToInventory" ||
		       type == "luaTask";
	}
};

/**
 * Behavior tree asset component.
 *
 * Can be attached to an entity to define a reusable behavior tree,
 * or referenced by name from a GoapAction.
 */
struct BehaviorTreeComponent {
	BehaviorTreeNode root;
	Ogre::String treeName;
	bool enabled = true;
	bool dirty = true;

	void markDirty()
	{
		dirty = true;
	}
};

#endif // EDITSCENE_BEHAVIOR_TREE_HPP
