/**
 * @file component_lua_test.cpp
 * @brief Standalone test for the Lua Component API.
 *
 * Tests component manipulation functions exposed via the ecs.* Lua API:
 * add_component, remove_component, has_component, get_component,
 * set_component, get_field, set_field.
 *
 * Build with CMake (recommended):
 *   cmake --build <build-dir> --target component_lua_test
 *
 * Run:
 *   <build-dir>/src/features/editScene/component_lua_test
 */

#include <cstdio>
#include <cstring>
#include <cassert>
#include <string>
#include <vector>

// Ogre stub (provides Ogre::String, Ogre::Vector3, Ogre::LogManager)
#include "ogre_stub.h"

// Include Lua
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}

// Flecs stub for standalone testing
namespace flecs
{

struct entity {
	uint64_t m_id = 0;
	bool m_valid = false;

	entity()
		: m_id(0)
		, m_valid(false)
	{
	}
	explicit entity(uint64_t id)
		: m_id(id)
		, m_valid(true)
	{
	}

	uint64_t id() const
	{
		return m_id;
	}
	bool is_valid() const
	{
		return m_valid;
	}
	bool is_alive() const
	{
		return m_valid;
	}
	const char *name() const
	{
		return "";
	}
	void set_name(const char *)
	{
	}
	void destruct()
	{
		m_valid = false;
	}

	entity parent() const
	{
		return entity();
	}

	template <typename Func> void children(Func) const
	{
	}

	template <typename T> void add()
	{
	}

	template <typename T> bool has() const
	{
		return false;
	}

	template <typename T> const T *get() const
	{
		return nullptr;
	}

	template <typename T> void set(const T &)
	{
	}

	bool operator==(const entity &other) const
	{
		return m_id == other.m_id;
	}
};

using entity_t = uint64_t;

struct world {
	entity make_entity()
	{
		return entity(nextId++);
	}
	entity lookup(const char *)
	{
		return entity();
	}

	static world &get()
	{
		static world w;
		return w;
	}

private:
	uint64_t nextId = 1000;
};

} // namespace flecs

// Forward declare the registration function
namespace editScene
{
void registerLuaComponentApi(lua_State *L);
void registerLuaEntityApi(lua_State *L);
void registerLuaDialogueApi(lua_State *L);
}

// ---------------------------------------------------------------------------
// Test helpers
// ---------------------------------------------------------------------------

static int testCount = 0;
static int passCount = 0;

#define TEST(name)                                             \
	do {                                                   \
		testCount++;                                   \
		printf("  TEST %d: %s ... ", testCount, name); \
	} while (0)

#define PASS()                    \
	do {                      \
		passCount++;      \
		printf("PASS\n"); \
	} while (0)

#define FAIL(msg)                          \
	do {                               \
		printf("FAIL: %s\n", msg); \
		return 1;                  \
	} while (0)

// ---------------------------------------------------------------------------
// Helper: run a Lua string and check for errors
// ---------------------------------------------------------------------------

static bool runLua(lua_State *L, const char *code)
{
	if (luaL_dostring(L, code) != LUA_OK) {
		fprintf(stderr, "Lua error: %s\n", lua_tostring(L, -1));
		lua_pop(L, 1);
		return false;
	}
	return true;
}

// ---------------------------------------------------------------------------
// Test 1: has_component returns false for new entity
// ---------------------------------------------------------------------------

static int testHasComponent(lua_State *L)
{
	TEST("has_component returns false for new entity");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"local has = ecs.has_component(id, 'EntityName');"
		"assert(has == false, 'new entity should not have EntityName')");
	if (!ok)
		FAIL("has_component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 2: add_component and has_component
// ---------------------------------------------------------------------------

static int testAddComponent(lua_State *L)
{
	TEST("add_component and has_component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.add_component(id, 'EntityName');"
		"local has = ecs.has_component(id, 'EntityName');"
		"assert(has == true, 'entity should have EntityName after add')");
	if (!ok)
		FAIL("add_component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 3: set_component and get_component
// ---------------------------------------------------------------------------

static int testSetGetComponent(lua_State *L)
{
	TEST("set_component and get_component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_component(id, 'EntityName', { name = 'hero' });"
		"local c = ecs.get_component(id, 'EntityName');"
		"assert(c ~= nil, 'component should exist');"
		"assert(c.name == 'hero', 'expected hero, got ' .. tostring(c.name))");
	if (!ok)
		FAIL("set/get component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 4: remove_component
// ---------------------------------------------------------------------------

static int testRemoveComponent(lua_State *L)
{
	TEST("remove_component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.add_component(id, 'EntityName');"
		"assert(ecs.has_component(id, 'EntityName') == true, 'should have before remove');"
		"ecs.remove_component(id, 'EntityName');"
		"assert(ecs.has_component(id, 'EntityName') == false, 'should not have after remove')");
	if (!ok)
		FAIL("remove_component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 5: get_field and set_field
// ---------------------------------------------------------------------------

static int testGetSetField(lua_State *L)
{
	TEST("get_field and set_field");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_field(id, 'EntityName', 'name', 'field_hero');"
		"local name = ecs.get_field(id, 'EntityName', 'name');"
		"assert(name == 'field_hero', 'expected field_hero, got ' .. tostring(name))");
	if (!ok)
		FAIL("get/set field assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 6: Transform component with vector fields
// ---------------------------------------------------------------------------

static int testTransformComponent(lua_State *L)
{
	TEST("Transform component with position/rotation/scale");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_component(id, 'Transform', {"
		"  position = { 10, 20, 30 },"
		"  rotation = { 1, 0, 0, 0 },"
		"  scale = { 2, 2, 2 }"
		"});"
		"local t = ecs.get_component(id, 'Transform');"
		"assert(t ~= nil, 'Transform should exist');"
		"assert(t.position[1] == 10, 'expected pos.x=10, got ' .. t.position[1]);"
		"assert(t.position[2] == 20, 'expected pos.y=20');"
		"assert(t.position[3] == 30, 'expected pos.z=30');"
		"assert(t.scale[1] == 2, 'expected scale.x=2');"
		"assert(t.rotation[1] == 1, 'expected rot.w=1')");
	if (!ok)
		FAIL("Transform component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 7: Renderable component
// ---------------------------------------------------------------------------

static int testRenderableComponent(lua_State *L)
{
	TEST("Renderable component with mesh name");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'Renderable', {"
		   "  meshName = 'cube.mesh',"
		   "  visible = true"
		   "});"
		   "local r = ecs.get_component(id, 'Renderable');"
		   "assert(r ~= nil, 'Renderable should exist');"
		   "assert(r.meshName == 'cube.mesh', 'expected cube.mesh');"
		   "assert(r.visible == true, 'expected visible=true')");
	if (!ok)
		FAIL("Renderable component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 8: Light component
// ---------------------------------------------------------------------------

static int testLightComponent(lua_State *L)
{
	TEST("Light component with color and intensity");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_component(id, 'Light', {"
		"  lightType = 0,"
		"  diffuseColor = { 1, 1, 1, 1 },"
		"  intensity = 1.5,"
		"  range = 100,"
		"  castShadows = true"
		"});"
		"local l = ecs.get_component(id, 'Light');"
		"assert(l ~= nil, 'Light should exist');"
		"assert(l.lightType == 0, 'expected point light');"
		"assert(l.intensity == 1.5, 'expected intensity 1.5');"
		"assert(l.range == 100, 'expected range 100');"
		"assert(l.castShadows == true, 'expected castShadows=true')");
	if (!ok)
		FAIL("Light component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 9: RigidBody component
// ---------------------------------------------------------------------------

static int testRigidBodyComponent(lua_State *L)
{
	TEST("RigidBody component with physics properties");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'RigidBody', {"
		   "  bodyType = 1,"
		   "  mass = 10.0,"
		   "  friction = 0.5,"
		   "  restitution = 0.2,"
		   "  enabled = true"
		   "});"
		   "local rb = ecs.get_component(id, 'RigidBody');"
		   "assert(rb ~= nil, 'RigidBody should exist');"
		   "assert(rb.bodyType == 1, 'expected dynamic body');"
		   "assert(rb.mass == 10.0, 'expected mass 10');"
		   "assert(rb.friction == 0.5, 'expected friction 0.5');"
		   "assert(rb.restitution == 0.2, 'expected restitution 0.2')");
	if (!ok)
		FAIL("RigidBody component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 10: EditorMarker tag component
// ---------------------------------------------------------------------------

static int testEditorMarkerTag(lua_State *L)
{
	TEST("EditorMarker tag component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "local has = ecs.has_component(id, 'EditorMarker');"
		   "assert(has == true, 'new entity should have EditorMarker');"
		   "ecs.remove_component(id, 'EditorMarker');"
		   "has = ecs.has_component(id, 'EditorMarker');"
		   "assert(has == false, 'should not have after remove');"
		   "ecs.add_component(id, 'EditorMarker');"
		   "has = ecs.has_component(id, 'EditorMarker');"
		   "assert(has == true, 'should have after re-add')");
	if (!ok)
		FAIL("EditorMarker tag assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 11: InWater tag component
// ---------------------------------------------------------------------------

static int testInWaterTag(lua_State *L)
{
	TEST("InWater tag component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "local has = ecs.has_component(id, 'InWater');"
		   "assert(has == false, 'new entity should not have InWater');"
		   "ecs.add_component(id, 'InWater');"
		   "has = ecs.has_component(id, 'InWater');"
		   "assert(has == true, 'should have InWater after add');"
		   "ecs.remove_component(id, 'InWater');"
		   "has = ecs.has_component(id, 'InWater');"
		   "assert(has == false, 'should not have after remove')");
	if (!ok)
		FAIL("InWater tag assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 12: GeneratedPhysicsTag tag component
// ---------------------------------------------------------------------------

static int testGeneratedPhysicsTag(lua_State *L)
{
	TEST("GeneratedPhysicsTag tag component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"local has = ecs.has_component(id, 'GeneratedPhysicsTag');"
		"assert(has == false, 'new entity should not have GeneratedPhysicsTag');"
		"ecs.add_component(id, 'GeneratedPhysicsTag');"
		"has = ecs.has_component(id, 'GeneratedPhysicsTag');"
		"assert(has == true, 'should have after add');"
		"ecs.remove_component(id, 'GeneratedPhysicsTag');"
		"has = ecs.has_component(id, 'GeneratedPhysicsTag');"
		"assert(has == false, 'should not have after remove')");
	if (!ok)
		FAIL("GeneratedPhysicsTag tag assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 13: ParentComponent tag component
// ---------------------------------------------------------------------------

static int testParentComponentTag(lua_State *L)
{
	TEST("ParentComponent tag component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"local has = ecs.has_component(id, 'ParentComponent');"
		"assert(has == false, 'new entity should not have ParentComponent');"
		"ecs.add_component(id, 'ParentComponent');"
		"has = ecs.has_component(id, 'ParentComponent');"
		"assert(has == true, 'should have after add');"
		"ecs.remove_component(id, 'ParentComponent');"
		"has = ecs.has_component(id, 'ParentComponent');"
		"assert(has == false, 'should not have after remove')");
	if (!ok)
		FAIL("ParentComponent tag assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 14: ModifiedComponent with field
// ---------------------------------------------------------------------------

static int testModifiedComponent(lua_State *L)
{
	TEST("ModifiedComponent with modified field");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"local c = ecs.get_component(id, 'ModifiedComponent');"
		"assert(c == nil, 'new entity should not have ModifiedComponent');"
		"ecs.set_component(id, 'ModifiedComponent', { modified = true });"
		"c = ecs.get_component(id, 'ModifiedComponent');"
		"assert(c ~= nil, 'should exist after set');"
		"assert(c.modified == true, 'expected modified=true');"
		"ecs.set_field(id, 'ModifiedComponent', 'modified', false);"
		"local mod = ecs.get_field(id, 'ModifiedComponent', 'modified');"
		"assert(mod == false, 'expected modified=false after set_field')");
	if (!ok)
		FAIL("ModifiedComponent assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 15: NavMeshGeometrySource tag component
// ---------------------------------------------------------------------------

static int testNavMeshGeometrySourceTag(lua_State *L)
{
	TEST("NavMeshGeometrySource tag component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"local has = ecs.has_component(id, 'NavMeshGeometrySource');"
		"assert(has == false, 'new entity should not have NavMeshGeometrySource');"
		"ecs.add_component(id, 'NavMeshGeometrySource');"
		"has = ecs.has_component(id, 'NavMeshGeometrySource');"
		"assert(has == true, 'should have after add');"
		"ecs.remove_component(id, 'NavMeshGeometrySource');"
		"has = ecs.has_component(id, 'NavMeshGeometrySource');"
		"assert(has == false, 'should not have after remove')");
	if (!ok)
		FAIL("NavMeshGeometrySource tag assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 16: Item component with all fields
// ---------------------------------------------------------------------------

static int testItemComponent(lua_State *L)
{
	TEST("Item component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity(); "
		"ecs.set_component(id, 'Item', {"
		"  itemId = 'potion_health',"
		"  stackSize = 5,"
		"  action = 'drink_potion',"
		"  instanceId = 'potion_001',"
		"  disabled = true"
		"}); "
		"local item = ecs.get_component(id, 'Item'); "
		"assert(item ~= nil, 'Item should exist'); "
		"assert(item.itemId == 'potion_health', 'wrong id'); "
		"assert(item.stackSize == 5, 'wrong stackSize'); "
		"assert(item.action == 'drink_potion', 'wrong action'); "
		"assert(item.instanceId == 'potion_001', 'wrong instanceId'); "
		"assert(item.disabled == true, 'wrong disabled')");
	if (!ok)
		FAIL("Item component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 17: Inventory component
// ---------------------------------------------------------------------------

static int testInventoryComponent(lua_State *L)
{
	TEST("Inventory component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'Inventory', {"
		   "  maxSlots = 20,"
		   "  maxWeight = 50.0,"
		   "  isContainer = true"
		   "});"
		   "local inv = ecs.get_component(id, 'Inventory');"
		   "assert(inv ~= nil, 'Inventory should exist');"
		   "assert(inv.maxSlots == 20, 'wrong maxSlots');"
		   "assert(inv.maxWeight == 50.0, 'wrong maxWeight');"
		   "assert(inv.isContainer == true, 'wrong isContainer')");
	if (!ok)
		FAIL("Inventory component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 18: Character component
// ---------------------------------------------------------------------------

static int testCharacterComponent(lua_State *L)
{
	TEST("Character component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'Character', {"
			    "  radius = 0.4,"
			    "  height = 1.8,"
			    "  offset = { 0, 0.9, 0 },"
			    "  enabled = true,"
			    "  useGravity = true"
			    "});"
			    "local c = ecs.get_component(id, 'Character');"
			    "assert(c ~= nil, 'Character should exist');"
			    "assert(c.radius == 0.4, 'wrong radius');"
			    "assert(c.height == 1.8, 'wrong height');"
			    "assert(c.enabled == true, 'wrong enabled');"
			    "assert(c.useGravity == true, 'wrong useGravity')");
	if (!ok)
		FAIL("Character component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 19: Camera component
// ---------------------------------------------------------------------------

static int testCameraComponent(lua_State *L)
{
	TEST("Camera component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'Camera', {"
		   "  fovY = 60,"
		   "  nearClip = 0.1,"
		   "  farClip = 1000,"
		   "  orthographic = false"
		   "});"
		   "local cam = ecs.get_component(id, 'Camera');"
		   "assert(cam ~= nil, 'Camera should exist');"
		   "assert(cam.fovY == 60, 'wrong fovY');"
		   "assert(cam.nearClip == 0.1, 'wrong nearClip');"
		   "assert(cam.farClip == 1000, 'wrong farClip');"
		   "assert(cam.orthographic == false, 'wrong orthographic')");
	if (!ok)
		FAIL("Camera component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 20: Sun component
// ---------------------------------------------------------------------------

static int testSunComponent(lua_State *L)
{
	TEST("Sun component");

	bool ok = runLua(L,
			 "local id = ecs.create_entity();"
			 "ecs.set_component(id, 'Sun', {"
			 "  enabled = true,"
			 "  timeOfDay = 12.0,"
			 "  timeSpeed = 1.0,"
			 "  intensity = 1.0,"
			 "  castShadows = true"
			 "});"
			 "local s = ecs.get_component(id, 'Sun');"
			 "assert(s ~= nil, 'Sun should exist');"
			 "assert(s.enabled == true, 'wrong enabled');"
			 "assert(s.timeOfDay == 12.0, 'wrong timeOfDay');"
			 "assert(s.timeSpeed == 1.0, 'wrong timeSpeed');"
			 "assert(s.intensity == 1.0, 'wrong intensity');"
			 "assert(s.castShadows == true, 'wrong castShadows')");
	if (!ok)
		FAIL("Sun component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 21: Skybox component
// ---------------------------------------------------------------------------

static int testSkyboxComponent(lua_State *L)
{
	TEST("Skybox component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'Skybox', {"
		   "  enabled = true,"
		   "  size = 500,"
		   "  starsEnabled = true"
		   "});"
		   "local s = ecs.get_component(id, 'Skybox');"
		   "assert(s ~= nil, 'Skybox should exist');"
		   "assert(s.enabled == true, 'wrong enabled');"
		   "assert(s.size == 500, 'wrong size');"
		   "assert(s.starsEnabled == true, 'wrong starsEnabled')");
	if (!ok)
		FAIL("Skybox component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 22: WaterPlane component
// ---------------------------------------------------------------------------

static int testWaterPlaneComponent(lua_State *L)
{
	TEST("WaterPlane component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'WaterPlane', {"
		   "  enabled = true,"
		   "  waterSurfaceY = 0.0,"
		   "  planeSize = 1000,"
		   "  reflectivity = 0.5,"
		   "  waveSpeed = 1.0"
		   "});"
		   "local w = ecs.get_component(id, 'WaterPlane');"
		   "assert(w ~= nil, 'WaterPlane should exist');"
		   "assert(w.enabled == true, 'wrong enabled');"
		   "assert(w.waterSurfaceY == 0.0, 'wrong waterSurfaceY');"
		   "assert(w.planeSize == 1000, 'wrong planeSize');"
		   "assert(w.reflectivity == 0.5, 'wrong reflectivity')");
	if (!ok)
		FAIL("WaterPlane component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 23: BuoyancyInfo component
// ---------------------------------------------------------------------------

static int testBuoyancyInfoComponent(lua_State *L)
{
	TEST("BuoyancyInfo component");

	bool ok = runLua(L,
			 "local id = ecs.create_entity();"
			 "ecs.set_component(id, 'BuoyancyInfo', {"
			 "  enabled = true,"
			 "  buoyancy = 1.0,"
			 "  linearDrag = 0.5,"
			 "  angularDrag = 0.3"
			 "});"
			 "local b = ecs.get_component(id, 'BuoyancyInfo');"
			 "assert(b ~= nil, 'BuoyancyInfo should exist');"
			 "assert(b.enabled == true, 'wrong enabled');"
			 "assert(b.buoyancy == 1.0, 'wrong buoyancy');"
			 "assert(b.linearDrag == 0.5, 'wrong linearDrag');"
			 "assert(b.angularDrag == 0.3, 'wrong angularDrag')");
	if (!ok)
		FAIL("BuoyancyInfo component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 24: PlayerController component
// ---------------------------------------------------------------------------

static int testPlayerControllerComponent(lua_State *L)
{
	TEST("PlayerController component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_component(id, 'PlayerController', {"
		"  cameraMode = 1,"
		"  tpsDistance = 5.0,"
		"  tpsHeight = 2.0,"
		"  mouseSensitivity = 0.5"
		"});"
		"local p = ecs.get_component(id, 'PlayerController');"
		"assert(p ~= nil, 'PlayerController should exist');"
		"assert(p.cameraMode == 1, 'wrong cameraMode');"
		"assert(p.tpsDistance == 5.0, 'wrong tpsDistance');"
		"assert(p.tpsHeight == 2.0, 'wrong tpsHeight');"
		"assert(p.mouseSensitivity == 0.5, 'wrong mouseSensitivity')");
	if (!ok)
		FAIL("PlayerController component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 25: Dialogue singleton API (via LuaDialogueApi stub)
// ---------------------------------------------------------------------------
// DialogueSystem is no longer an ECS component. It is a singleton accessed
// via ecs.dialogue.show(), ecs.dialogue.get_settings(), etc.
// The full API is tested in integration tests; component_lua_test only
// verifies that the stub table exists and is callable.

static int testDialogueSingletonApi(lua_State *L)
{
	TEST("Dialogue singleton API stub");

	bool ok = runLua(L,
			 "local s = ecs.dialogue.get_settings();"
			 "assert(s ~= nil, 'settings should exist');"
			 "assert(s.font_name ~= nil, 'font_name should exist');"
			 "ecs.dialogue.show('Hello', {}, 'NPC');"
			 "ecs.dialogue.hide();"
			 "local active = ecs.dialogue.is_active();"
			 "assert(active == false, 'should not be active after hide')");
	if (!ok)
		FAIL("Dialogue singleton API assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 26: NavMesh component
// ---------------------------------------------------------------------------

static int testNavMeshComponent(lua_State *L)
{
	TEST("NavMesh component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'NavMesh', {"
		   "  cellSize = 0.3,"
		   "  cellHeight = 0.2,"
		   "  agentHeight = 2.0,"
		   "  agentRadius = 0.5,"
		   "  agentMaxClimb = 0.5,"
		   "  agentMaxSlope = 45.0,"
		   "  enabled = true"
		   "});"
		   "local n = ecs.get_component(id, 'NavMesh');"
		   "assert(n ~= nil, 'NavMesh should exist');"
		   "assert(n.cellSize == 0.3, 'wrong cellSize');"
		   "assert(n.cellHeight == 0.2, 'wrong cellHeight');"
		   "assert(n.agentHeight == 2.0, 'wrong agentHeight');"
		   "assert(n.agentRadius == 0.5, 'wrong agentRadius');"
		   "assert(n.agentMaxClimb == 0.5, 'wrong agentMaxClimb');"
		   "assert(n.agentMaxSlope == 45.0, 'wrong agentMaxSlope');"
		   "assert(n.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("NavMesh component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 27: SmartObject component
// ---------------------------------------------------------------------------

static int testSmartObjectComponent(lua_State *L)
{
	TEST("SmartObject component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'SmartObject', {"
		   "  radius = 1.0,"
		   "  height = 2.0,"
		   "  actionNames = { 'sit', 'talk' }"
		   "});"
		   "local s = ecs.get_component(id, 'SmartObject');"
		   "assert(s ~= nil, 'SmartObject should exist');"
		   "assert(s.radius == 1.0, 'wrong radius');"
		   "assert(s.height == 2.0, 'wrong height');"
		   "assert(#s.actionNames == 2, 'expected 2 action names');"
		   "assert(s.actionNames[1] == 'sit', 'wrong action 1');"
		   "assert(s.actionNames[2] == 'talk', 'wrong action 2')");
	if (!ok)
		FAIL("SmartObject component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 28: Actuator component
// ---------------------------------------------------------------------------

static int testActuatorComponent(lua_State *L)
{
	TEST("Actuator component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'Actuator', {"
		   "  radius = 2.0,"
		   "  height = 3.0,"
		   "  actionNames = { 'interact' }"
		   "});"
		   "local a = ecs.get_component(id, 'Actuator');"
		   "assert(a ~= nil, 'Actuator should exist');"
		   "assert(a.radius == 2.0, 'wrong radius');"
		   "assert(a.height == 3.0, 'wrong height');"
		   "assert(#a.actionNames == 1, 'expected 1 action name');"
		   "assert(a.actionNames[1] == 'interact', 'wrong action')");
	if (!ok)
		FAIL("Actuator component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 29: EventHandler component
// ---------------------------------------------------------------------------

static int testEventHandlerComponent(lua_State *L)
{
	TEST("EventHandler component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_component(id, 'EventHandler', {"
		"  eventName = 'collision',"
		"  actionName = 'handle_collision',"
		"  enabled = true"
		"});"
		"local e = ecs.get_component(id, 'EventHandler');"
		"assert(e ~= nil, 'EventHandler should exist');"
		"assert(e.eventName == 'collision', 'wrong eventName');"
		"assert(e.actionName == 'handle_collision', 'wrong actionName');"
		"assert(e.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("EventHandler component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 30: GoapBlackboard component
// ---------------------------------------------------------------------------

static int testGoapBlackboardComponent(lua_State *L)
{
	TEST("GoapBlackboard component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'GoapBlackboard', {"
		   "  values = { health = 100, stamina = 50 },"
		   "  floatValues = { hunger = 75.5 },"
		   "  stringValues = { state = 'idle' }"
		   "});"
		   "local g = ecs.get_component(id, 'GoapBlackboard');"
		   "assert(g ~= nil, 'GoapBlackboard should exist');"
		   "assert(g.values.health == 100, 'wrong health');"
		   "assert(g.values.stamina == 50, 'wrong stamina');"
		   "assert(g.floatValues.hunger == 75.5, 'wrong hunger');"
		   "assert(g.stringValues.state == 'idle', 'wrong state')");
	if (!ok)
		FAIL("GoapBlackboard component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 31: PrefabInstance component
// ---------------------------------------------------------------------------

static int testPrefabInstanceComponent(lua_State *L)
{
	TEST("PrefabInstance component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'PrefabInstance', {"
		   "  prefabPath = 'prefabs/house.json',"
		   "  instantiated = false"
		   "});"
		   "local p = ecs.get_component(id, 'PrefabInstance');"
		   "assert(p ~= nil, 'PrefabInstance should exist');"
		   "assert(p.prefabPath == 'prefabs/house.json', 'wrong path');"
		   "assert(p.instantiated == false, 'wrong instantiated')");
	if (!ok)
		FAIL("PrefabInstance component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 32: CellGrid component
// ---------------------------------------------------------------------------

static int testCellGridComponent(lua_State *L)
{
	TEST("CellGrid component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'CellGrid', {"
			    "  width = 10,"
			    "  height = 5,"
			    "  depth = 10,"
			    "  cellSize = 1.0,"
			    "  cellHeight = 0.5"
			    "});"
			    "local c = ecs.get_component(id, 'CellGrid');"
			    "assert(c ~= nil, 'CellGrid should exist');"
			    "assert(c.width == 10, 'wrong width');"
			    "assert(c.height == 5, 'wrong height');"
			    "assert(c.depth == 10, 'wrong depth');"
			    "assert(c.cellSize == 1.0, 'wrong cellSize');"
			    "assert(c.cellHeight == 0.5, 'wrong cellHeight')");
	if (!ok)
		FAIL("CellGrid component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 33: Room component
// ---------------------------------------------------------------------------

static int testRoomComponent(lua_State *L)
{
	TEST("Room component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'Room', {"
			    "  roomName = 'Kitchen',"
			    "  roomType = 'kitchen',"
			    "  floor = 0"
			    "});"
			    "local r = ecs.get_component(id, 'Room');"
			    "assert(r ~= nil, 'Room should exist');"
			    "assert(r.roomName == 'Kitchen', 'wrong roomName');"
			    "assert(r.roomType == 'kitchen', 'wrong roomType');"
			    "assert(r.floor == 0, 'wrong floor')");
	if (!ok)
		FAIL("Room component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 34: Lot component
// ---------------------------------------------------------------------------

static int testLotComponent(lua_State *L)
{
	TEST("Lot component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'Lot', {"
		   "  lotName = 'Residential 1',"
		   "  lotType = 'residential',"
		   "  width = 20,"
		   "  depth = 30"
		   "});"
		   "local l = ecs.get_component(id, 'Lot');"
		   "assert(l ~= nil, 'Lot should exist');"
		   "assert(l.lotName == 'Residential 1', 'wrong lotName');"
		   "assert(l.lotType == 'residential', 'wrong lotType');"
		   "assert(l.width == 20, 'wrong width');"
		   "assert(l.depth == 30, 'wrong depth')");
	if (!ok)
		FAIL("Lot component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 35: District component
// ---------------------------------------------------------------------------

static int testDistrictComponent(lua_State *L)
{
	TEST("District component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_component(id, 'District', {"
		"  districtName = 'Market District',"
		"  districtType = 'commercial'"
		"});"
		"local d = ecs.get_component(id, 'District');"
		"assert(d ~= nil, 'District should exist');"
		"assert(d.districtName == 'Market District', 'wrong districtName');"
		"assert(d.districtType == 'commercial', 'wrong districtType')");
	if (!ok)
		FAIL("District component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 36: Town component
// ---------------------------------------------------------------------------

static int testTownComponent(lua_State *L)
{
	TEST("Town component");

	bool ok = runLua(L,
			 "local id = ecs.create_entity();"
			 "ecs.set_component(id, 'Town', {"
			 "  townName = 'Rivendell',"
			 "  population = 500"
			 "});"
			 "local t = ecs.get_component(id, 'Town');"
			 "assert(t ~= nil, 'Town should exist');"
			 "assert(t.townName == 'Rivendell', 'wrong townName');"
			 "assert(t.population == 500, 'wrong population')");
	if (!ok)
		FAIL("Town component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 37: FurnitureTemplate component
// ---------------------------------------------------------------------------

static int testFurnitureTemplateComponent(lua_State *L)
{
	TEST("FurnitureTemplate component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_component(id, 'FurnitureTemplate', {"
		"  templateName = 'wooden_chair',"
		"  meshName = 'chair.mesh',"
		"  category = 'seating'"
		"});"
		"local f = ecs.get_component(id, 'FurnitureTemplate');"
		"assert(f ~= nil, 'FurnitureTemplate should exist');"
		"assert(f.templateName == 'wooden_chair', 'wrong templateName');"
		"assert(f.meshName == 'chair.mesh', 'wrong meshName');"
		"assert(f.category == 'seating', 'wrong category')");
	if (!ok)
		FAIL("FurnitureTemplate component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 38: StartupMenu component
// ---------------------------------------------------------------------------

static int testStartupMenuComponent(lua_State *L)
{
	TEST("StartupMenu component");

	bool ok = runLua(L,
			 "local id = ecs.create_entity();"
			 "ecs.set_component(id, 'StartupMenu', {"
			 "  enabled = true,"
			 "  showOnStart = true"
			 "});"
			 "local s = ecs.get_component(id, 'StartupMenu');"
			 "assert(s ~= nil, 'StartupMenu should exist');"
			 "assert(s.enabled == true, 'wrong enabled');"
			 "assert(s.showOnStart == true, 'wrong showOnStart')");
	if (!ok)
		FAIL("StartupMenu component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 39: Lod component
// ---------------------------------------------------------------------------

static int testLodComponent(lua_State *L)
{
	TEST("Lod component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'Lod', {"
			    "  lodLevel = 0,"
			    "  distance = 100.0"
			    "});"
			    "local l = ecs.get_component(id, 'Lod');"
			    "assert(l ~= nil, 'Lod should exist');"
			    "assert(l.lodLevel == 0, 'wrong lodLevel');"
			    "assert(l.distance == 100.0, 'wrong distance')");
	if (!ok)
		FAIL("Lod component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 40: LodSettings component
// ---------------------------------------------------------------------------

static int testLodSettingsComponent(lua_State *L)
{
	TEST("LodSettings component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'LodSettings', {"
			    "  enabled = true,"
			    "  lodBias = 1.0"
			    "});"
			    "local l = ecs.get_component(id, 'LodSettings');"
			    "assert(l ~= nil, 'LodSettings should exist');"
			    "assert(l.enabled == true, 'wrong enabled');"
			    "assert(l.lodBias == 1.0, 'wrong lodBias')");
	if (!ok)
		FAIL("LodSettings component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 41: StaticGeometry component
// ---------------------------------------------------------------------------

static int testStaticGeometryComponent(lua_State *L)
{
	TEST("StaticGeometry component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'StaticGeometry', {"
		   "  batchName = 'forest_batch',"
		   "  enabled = true"
		   "});"
		   "local s = ecs.get_component(id, 'StaticGeometry');"
		   "assert(s ~= nil, 'StaticGeometry should exist');"
		   "assert(s.batchName == 'forest_batch', 'wrong batchName');"
		   "assert(s.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("StaticGeometry component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 42: ProceduralTexture component
// ---------------------------------------------------------------------------

static int testProceduralTextureComponent(lua_State *L)
{
	TEST("ProceduralTexture component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'ProceduralTexture', {"
		   "  textureName = 'grass',"
		   "  width = 512,"
		   "  height = 512"
		   "});"
		   "local p = ecs.get_component(id, 'ProceduralTexture');"
		   "assert(p ~= nil, 'ProceduralTexture should exist');"
		   "assert(p.textureName == 'grass', 'wrong textureName');"
		   "assert(p.width == 512, 'wrong width');"
		   "assert(p.height == 512, 'wrong height')");
	if (!ok)
		FAIL("ProceduralTexture component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 43: ProceduralMaterial component
// ---------------------------------------------------------------------------

static int testProceduralMaterialComponent(lua_State *L)
{
	TEST("ProceduralMaterial component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_component(id, 'ProceduralMaterial', {"
		"  materialName = 'ground_mat',"
		"  baseColor = { 0.5, 0.5, 0.5, 1.0 }"
		"});"
		"local p = ecs.get_component(id, 'ProceduralMaterial');"
		"assert(p ~= nil, 'ProceduralMaterial should exist');"
		"assert(p.materialName == 'ground_mat', 'wrong materialName')");
	if (!ok)
		FAIL("ProceduralMaterial component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 44: Primitive component
// ---------------------------------------------------------------------------

static int testPrimitiveComponent(lua_State *L)
{
	TEST("Primitive component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'Primitive', {"
		   "  primitiveType = 'box',"
		   "  size = { 1, 2, 1 }"
		   "});"
		   "local p = ecs.get_component(id, 'Primitive');"
		   "assert(p ~= nil, 'Primitive should exist');"
		   "assert(p.primitiveType == 'box', 'wrong primitiveType');"
		   "assert(p.size[1] == 1, 'wrong size.x');"
		   "assert(p.size[2] == 2, 'wrong size.y')");
	if (!ok)
		FAIL("Primitive component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 45: TriangleBuffer component
// ---------------------------------------------------------------------------

static int testTriangleBufferComponent(lua_State *L)
{
	TEST("TriangleBuffer component");

	bool ok = runLua(L,
			 "local id = ecs.create_entity();"
			 "ecs.set_component(id, 'TriangleBuffer', {"
			 "  enabled = true,"
			 "  vertexCount = 100"
			 "});"
			 "local t = ecs.get_component(id, 'TriangleBuffer');"
			 "assert(t ~= nil, 'TriangleBuffer should exist');"
			 "assert(t.enabled == true, 'wrong enabled');"
			 "assert(t.vertexCount == 100, 'wrong vertexCount')");
	if (!ok)
		FAIL("TriangleBuffer component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 46: CharacterSpawner component
// ---------------------------------------------------------------------------

static int testCharacterSpawnerComponent(lua_State *L)
{
	TEST("CharacterSpawner component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'CharacterSpawner', {"
			    "  registryId = 42,"
			    "  spawnDistanceSq = 10000,"
			    "  despawnDistanceSq = 40000"
			    "});"
			    "local c = ecs.get_component(id, 'CharacterSpawner');"
			    "assert(c ~= nil, 'CharacterSpawner should exist');"
			    "assert(c.registryId == 42, 'wrong registryId');"
			    "assert(c.spawnDistanceSq == 10000, 'wrong spawnDistanceSq');"
			    "assert(c.despawnDistanceSq == 40000, 'wrong despawnDistanceSq')");
	if (!ok)
		FAIL("CharacterSpawner component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 47: AnimationTree component
// ---------------------------------------------------------------------------

static int testAnimationTreeComponent(lua_State *L)
{
	TEST("AnimationTree component");

	bool ok = runLua(L,
			 "local id = ecs.create_entity();"
			 "ecs.set_component(id, 'AnimationTree', {"
			 "  treeName = 'humanoid',"
			 "  enabled = true"
			 "});"
			 "local a = ecs.get_component(id, 'AnimationTree');"
			 "assert(a ~= nil, 'AnimationTree should exist');"
			 "assert(a.treeName == 'humanoid', 'wrong treeName');"
			 "assert(a.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("AnimationTree component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 48: AnimationTreeTemplate component
// ---------------------------------------------------------------------------

static int testAnimationTreeTemplateComponent(lua_State *L)
{
	TEST("AnimationTreeTemplate component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_component(id, 'AnimationTreeTemplate', {"
		"  templateName = 'humanoid_base',"
		"  blendTime = 0.2"
		"});"
		"local a = ecs.get_component(id, 'AnimationTreeTemplate');"
		"assert(a ~= nil, 'AnimationTreeTemplate should exist');"
		"assert(a.templateName == 'humanoid_base', 'wrong templateName');"
		"assert(a.blendTime == 0.2, 'wrong blendTime')");
	if (!ok)
		FAIL("AnimationTreeTemplate component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 49: BehaviorTree component
// ---------------------------------------------------------------------------

static int testBehaviorTreeComponent(lua_State *L)
{
	TEST("BehaviorTree component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'BehaviorTree', {"
		   "  treeName = 'idle_behavior',"
		   "  enabled = true"
		   "});"
		   "local b = ecs.get_component(id, 'BehaviorTree');"
		   "assert(b ~= nil, 'BehaviorTree should exist');"
		   "assert(b.treeName == 'idle_behavior', 'wrong treeName');"
		   "assert(b.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("BehaviorTree component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 50: GoapAction component
// ---------------------------------------------------------------------------

static int testGoapActionComponent(lua_State *L)
{
	TEST("GoapAction component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'GoapAction', {"
		   "  actionName = 'chop_wood',"
		   "  cost = 5,"
		   "  enabled = true"
		   "});"
		   "local g = ecs.get_component(id, 'GoapAction');"
		   "assert(g ~= nil, 'GoapAction should exist');"
		   "assert(g.actionName == 'chop_wood', 'wrong actionName');"
		   "assert(g.cost == 5, 'wrong cost');"
		   "assert(g.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("GoapAction component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 51: GoapGoal component
// ---------------------------------------------------------------------------

static int testGoapGoalComponent(lua_State *L)
{
	TEST("GoapGoal component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'GoapGoal', {"
			    "  goalName = 'survive',"
			    "  priority = 100,"
			    "  enabled = true"
			    "});"
			    "local g = ecs.get_component(id, 'GoapGoal');"
			    "assert(g ~= nil, 'GoapGoal should exist');"
			    "assert(g.goalName == 'survive', 'wrong goalName');"
			    "assert(g.priority == 100, 'wrong priority');"
			    "assert(g.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("GoapGoal component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 52: GoapPlanner component
// ---------------------------------------------------------------------------

static int testGoapPlannerComponent(lua_State *L)
{
	TEST("GoapPlanner component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'GoapPlanner', {"
		   "  enabled = true,"
		   "  maxIterations = 100"
		   "});"
		   "local g = ecs.get_component(id, 'GoapPlanner');"
		   "assert(g ~= nil, 'GoapPlanner should exist');"
		   "assert(g.enabled == true, 'wrong enabled');"
		   "assert(g.maxIterations == 100, 'wrong maxIterations')");
	if (!ok)
		FAIL("GoapPlanner component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 53: GoapRunner component
// ---------------------------------------------------------------------------

static int testGoapRunnerComponent(lua_State *L)
{
	TEST("GoapRunner component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'GoapRunner', {"
		   "  enabled = true,"
		   "  currentAction = 'idle'"
		   "});"
		   "local g = ecs.get_component(id, 'GoapRunner');"
		   "assert(g ~= nil, 'GoapRunner should exist');"
		   "assert(g.enabled == true, 'wrong enabled');"
		   "assert(g.currentAction == 'idle', 'wrong currentAction')");
	if (!ok)
		FAIL("GoapRunner component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 54: PathFollowing component
// ---------------------------------------------------------------------------

static int testPathFollowingComponent(lua_State *L)
{
	TEST("PathFollowing component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'PathFollowing', {"
			    "  enabled = true,"
			    "  speed = 1.5"
			    "});"
			    "local p = ecs.get_component(id, 'PathFollowing');"
			    "assert(p ~= nil, 'PathFollowing should exist');"
			    "assert(p.enabled == true, 'wrong enabled');"
			    "assert(p.speed == 1.5, 'wrong speed')");
	if (!ok)
		FAIL("PathFollowing component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 55: NavMeshAgent component
// ---------------------------------------------------------------------------

static int testNavMeshAgentComponent(lua_State *L)
{
	TEST("NavMeshAgent component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'NavMeshAgent', {"
			    "  enabled = true,"
			    "  radius = 0.5,"
			    "  height = 2.0"
			    "});"
			    "local n = ecs.get_component(id, 'NavMeshAgent');"
			    "assert(n ~= nil, 'NavMeshAgent should exist');"
			    "assert(n.enabled == true, 'wrong enabled');"
			    "assert(n.radius == 0.5, 'wrong radius');"
			    "assert(n.height == 2.0, 'wrong height')");
	if (!ok)
		FAIL("NavMeshAgent component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 56: ActionDatabase component
// ---------------------------------------------------------------------------

static int testActionDatabaseComponent(lua_State *L)
{
	TEST("ActionDatabase component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'ActionDatabase', {"
			    "  enabled = true"
			    "});"
			    "local a = ecs.get_component(id, 'ActionDatabase');"
			    "assert(a ~= nil, 'ActionDatabase should exist');"
			    "assert(a.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("ActionDatabase component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 57: ActionDebug component
// ---------------------------------------------------------------------------

static int testActionDebugComponent(lua_State *L)
{
	TEST("ActionDebug component");

	bool ok = runLua(
		L, "local id = ecs.create_entity();"
		   "ecs.set_component(id, 'ActionDebug', {"
		   "  enabled = true,"
		   "  showDebugInfo = true"
		   "});"
		   "local a = ecs.get_component(id, 'ActionDebug');"
		   "assert(a ~= nil, 'ActionDebug should exist');"
		   "assert(a.enabled == true, 'wrong enabled');"
		   "assert(a.showDebugInfo == true, 'wrong showDebugInfo')");
	if (!ok)
		FAIL("ActionDebug component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 58: WaterPhysics component
// ---------------------------------------------------------------------------

static int testWaterPhysicsComponent(lua_State *L)
{
	TEST("WaterPhysics component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'WaterPhysics', {"
			    "  enabled = true,"
			    "  waveHeight = 0.5"
			    "});"
			    "local w = ecs.get_component(id, 'WaterPhysics');"
			    "assert(w ~= nil, 'WaterPhysics should exist');"
			    "assert(w.enabled == true, 'wrong enabled');"
			    "assert(w.waveHeight == 0.5, 'wrong waveHeight')");
	if (!ok)
		FAIL("WaterPhysics component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 59: ClearArea component
// ---------------------------------------------------------------------------

static int testClearAreaComponent(lua_State *L)
{
	TEST("ClearArea component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'ClearArea', {"
			    "  radius = 5.0,"
			    "  enabled = true"
			    "});"
			    "local c = ecs.get_component(id, 'ClearArea');"
			    "assert(c ~= nil, 'ClearArea should exist');"
			    "assert(c.radius == 5.0, 'wrong radius');"
			    "assert(c.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("ClearArea component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 60: Roof component
// ---------------------------------------------------------------------------

static int testRoofComponent(lua_State *L)
{
	TEST("Roof component");

	bool ok = runLua(L, "local id = ecs.create_entity();"
			    "ecs.set_component(id, 'Roof', {"
			    "  roofType = 'gable',"
			    "  height = 2.5,"
			    "  enabled = true"
			    "});"
			    "local r = ecs.get_component(id, 'Roof');"
			    "assert(r ~= nil, 'Roof should exist');"
			    "assert(r.roofType == 'gable', 'wrong roofType');"
			    "assert(r.height == 2.5, 'wrong height');"
			    "assert(r.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("Roof component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 61: StaticGeometryMember component
// ---------------------------------------------------------------------------

static int testStaticGeometryMemberComponent(lua_State *L)
{
	TEST("StaticGeometryMember component");

	bool ok = runLua(
		L,
		"local id = ecs.create_entity();"
		"ecs.set_component(id, 'StaticGeometryMember', {"
		"  parentBatch = 'forest_batch',"
		"  enabled = true"
		"});"
		"local s = ecs.get_component(id, 'StaticGeometryMember');"
		"assert(s ~= nil, 'StaticGeometryMember should exist');"
		"assert(s.parentBatch == 'forest_batch', 'wrong parentBatch');"
		"assert(s.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("StaticGeometryMember component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Test 62: PhysicsCollider component
// ---------------------------------------------------------------------------

static int testPhysicsColliderComponent(lua_State *L)
{
	TEST("PhysicsCollider component");

	bool ok = runLua(L,
			 "local id = ecs.create_entity();"
			 "ecs.set_component(id, 'PhysicsCollider', {"
			 "  shapeType = 'box',"
			 "  size = { 1, 1, 1 },"
			 "  enabled = true"
			 "});"
			 "local p = ecs.get_component(id, 'PhysicsCollider');"
			 "assert(p ~= nil, 'PhysicsCollider should exist');"
			 "assert(p.shapeType == 'box', 'wrong shapeType');"
			 "assert(p.enabled == true, 'wrong enabled')");
	if (!ok)
		FAIL("PhysicsCollider component assertion failed");

	PASS();
	return 0;
}

// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------

int main()
{
	printf("Component Lua API Tests\n");
	printf("=======================\n\n");

	// Create Lua state
	lua_State *L = luaL_newstate();
	if (!L) {
		fprintf(stderr, "Failed to create Lua state\n");
		return 1;
	}
	luaL_openlibs(L);

	// Register the entity and component APIs
	editScene::registerLuaEntityApi(L);
	editScene::registerLuaComponentApi(L);
	editScene::registerLuaDialogueApi(L);

	// Run tests
	int failures = 0;
	failures += testHasComponent(L);
	failures += testAddComponent(L);
	failures += testSetGetComponent(L);
	failures += testRemoveComponent(L);
	failures += testGetSetField(L);
	failures += testTransformComponent(L);
	failures += testRenderableComponent(L);
	failures += testLightComponent(L);
	failures += testRigidBodyComponent(L);
	failures += testEditorMarkerTag(L);
	failures += testInWaterTag(L);
	failures += testGeneratedPhysicsTag(L);
	failures += testParentComponentTag(L);
	failures += testModifiedComponent(L);
	failures += testNavMeshGeometrySourceTag(L);
	failures += testItemComponent(L);
	failures += testInventoryComponent(L);
	failures += testCharacterComponent(L);
	failures += testCameraComponent(L);
	failures += testSunComponent(L);
	failures += testSkyboxComponent(L);
	failures += testWaterPlaneComponent(L);
	failures += testBuoyancyInfoComponent(L);
	failures += testPlayerControllerComponent(L);
	failures += testDialogueSingletonApi(L);
	failures += testNavMeshComponent(L);
	failures += testSmartObjectComponent(L);
	failures += testActuatorComponent(L);
	failures += testEventHandlerComponent(L);
	failures += testGoapBlackboardComponent(L);
	failures += testPrefabInstanceComponent(L);
	failures += testCellGridComponent(L);
	failures += testRoomComponent(L);
	failures += testLotComponent(L);
	failures += testDistrictComponent(L);
	failures += testTownComponent(L);
	failures += testFurnitureTemplateComponent(L);
	failures += testStartupMenuComponent(L);
	failures += testLodComponent(L);
	failures += testLodSettingsComponent(L);
	failures += testStaticGeometryComponent(L);
	failures += testProceduralTextureComponent(L);
	failures += testProceduralMaterialComponent(L);
	failures += testPrimitiveComponent(L);
	failures += testTriangleBufferComponent(L);
	failures += testCharacterSpawnerComponent(L);
	failures += testAnimationTreeComponent(L);
	failures += testAnimationTreeTemplateComponent(L);
	failures += testBehaviorTreeComponent(L);
	failures += testGoapActionComponent(L);
	failures += testGoapGoalComponent(L);
	failures += testGoapPlannerComponent(L);
	failures += testGoapRunnerComponent(L);
	failures += testPathFollowingComponent(L);
	failures += testNavMeshAgentComponent(L);
	failures += testActionDatabaseComponent(L);
	failures += testActionDebugComponent(L);
	failures += testWaterPhysicsComponent(L);
	failures += testClearAreaComponent(L);
	failures += testRoofComponent(L);
	failures += testStaticGeometryMemberComponent(L);
	failures += testPhysicsColliderComponent(L);

	// Cleanup
	lua_close(L);

	printf("\nResults: %d/%d passed, %d failed\n", passCount, testCount,
	       failures);

	return failures > 0 ? 1 : 0;
}
