#ifndef EDITSCENE_GOAP_PLANNER_HPP
#define EDITSCENE_GOAP_PLANNER_HPP
#pragma once

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

/**
 * GOAP Planner component.
 *
 * Holds a curated list of action and goal names from an ActionDatabase,
 * plus configuration for smart-object action discovery.
 * The planner resolves names against an ActionDatabase at runtime.
 *
 * The actionNames and goalNames lists act as external references:
 * prefabs can store them even when the ActionDatabase is not
 * part of the prefab itself.
 */
struct GoapPlannerComponent {
	// Selected action names from ActionDatabase
	std::vector<Ogre::String> actionNames;

	// Selected goal names from ActionDatabase
	std::vector<Ogre::String> goalNames;

	// Maximum distance to search for smart objects with matching actions
	float smartObjectDistance = 50.0f;

	// Whether to include smart object actions in planning
	bool includeSmartObjects = true;

	// Optional reference to an external ActionDatabase entity by name.
	Ogre::String actionDatabaseRef;

	// -----------------------------------------------------------------
	// Runtime plan queue (not serialized)
	// -----------------------------------------------------------------
	struct Plan {
		std::vector<Ogre::String> actions;
		int totalCost = 0;
		Ogre::String goalName;
	};
	std::vector<Plan> planQueue;

	// Planner status
	enum class Status {
		Idle, // No planning requested
		Planning, // Currently planning
		PlansAvailable, // One or more plans in queue
		NoPlanFound // Planning finished but no valid plan found
	};
	Status status = Status::Idle;

	// Goal name that was used for the current plan batch
	Ogre::String currentGoalName;

	// Planning control
	bool planDirty = true;
	int maxPlans = 3; // stop after generating this many plans

	// Planning progress (for status display)
	int plansGenerated = 0;
	int nodesExplored = 0;

	GoapPlannerComponent() = default;

	void clearPlans()
	{
		planQueue.clear();
		plansGenerated = 0;
		status = Status::Idle;
	}

	// Pop the cheapest plan from the queue
	Plan popCheapestPlan()
	{
		if (planQueue.empty())
			return Plan();
		size_t bestIdx = 0;
		for (size_t i = 1; i < planQueue.size(); i++) {
			if (planQueue[i].totalCost < planQueue[bestIdx].totalCost)
				bestIdx = i;
		}
		Plan result = std::move(planQueue[bestIdx]);
		planQueue.erase(planQueue.begin() + bestIdx);
		if (planQueue.empty() && status == Status::PlansAvailable)
			status = Status::Idle;
		return result;
	}

	bool hasPlans() const
	{
		return !planQueue.empty();
	}
};

#endif // EDITSCENE_GOAP_PLANNER_HPP
