#ifndef EDITSCENE_NAVMESH_SYSTEM_HPP
#define EDITSCENE_NAVMESH_SYSTEM_HPP
#pragma once

#include <flecs.h>
#include <Ogre.h>
#include <memory>
#include <unordered_map>
#include <vector>

// Forward declarations
class TileCacheNavMesh;
class CellGridSystem;

/**
 * System that builds and maintains a DetourTileCache navmesh.
 *
 * - Collects geometry from static rigid bodies, StaticGeometry members,
 *   and NavMeshGeometrySource-marked entities.
 * - Builds a tiled navmesh on demand.
 * - Supports partial tile rebuild when tracked geometry changes.
 * - Provides Detour pathfinding.
 * - Can debug-draw the navmesh and paths.
 */
class NavMeshSystem {
public:
	NavMeshSystem(flecs::world &world, Ogre::SceneManager *sceneMgr);
	~NavMeshSystem();

	static NavMeshSystem *getInstance() { return s_instance; }

	void update(float deltaTime);

	// --- Pathfinding ---
	bool findPath(flecs::entity navmeshEntity,
		      Ogre::Vector3 start, Ogre::Vector3 end,
		      std::vector<Ogre::Vector3> &path);
	bool findNearestPoint(flecs::entity navmeshEntity,
			      Ogre::Vector3 pos,
			      Ogre::Vector3 &out);
	Ogre::Vector3 getRandomPoint(flecs::entity navmeshEntity);

	// --- Manual rebuild ---
	void rebuild(flecs::entity navmeshEntity);

	// --- Debug ---
	void setDebugDraw(flecs::entity navmeshEntity, bool enable);

	// --- CellGrid integration ---
	void setCellGridSystem(CellGridSystem *system);

private:
	struct NavMeshState {
		std::unique_ptr<TileCacheNavMesh> navmesh;
		bool debugDraw = false;
		bool firstBuild = true;
		// Track transform versions for rebuild
		std::unordered_map<flecs::entity_t, unsigned int> lastTransformVersions;
	};

	flecs::world &m_world;
	Ogre::SceneManager *m_sceneMgr;
	CellGridSystem *m_cellGridSystem = nullptr;
	std::unordered_map<flecs::entity_t, NavMeshState> m_states;
	static NavMeshSystem *s_instance;

	// Helpers
	void buildOrUpdate(flecs::entity_t e,
			   struct NavMeshComponent &comp,
			   NavMeshState &state);
	void collectStaticEntities(std::vector<Ogre::Entity *> &out,
				   std::vector<Ogre::Entity *> &outTemp);
	void destroyTempEntities(std::vector<Ogre::Entity *> &entities);
	Ogre::Entity *createTempEntity(const Ogre::String &meshName,
				       const Ogre::Vector3 &pos,
				       const Ogre::Quaternion &rot,
				       const Ogre::Vector3 &scale);
	Ogre::AxisAlignedBox getEntityBounds(flecs::entity e);
};

#endif // EDITSCENE_NAVMESH_SYSTEM_HPP
