"""
Unit tests for Spatial Grid (AOI - Area of Interest) in FreeExile World Cluster.
Verifies entity cell placement, proximity queries, neighbor cell broadcasts, and boundary crossings.
"""

import unittest
import sys
import os

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../server")))

from world.spatial_grid import SpatialGrid, Entity


class TestSpatialGrid(unittest.TestCase):
    def setUp(self):
        # 64m cell size
        self.grid = SpatialGrid(cell_size=64.0)

    def test_entity_registration_and_cell_indexing(self):
        """Entity placed at (100, 100) should be in cell (1, 1)."""
        e1 = Entity(entity_id=1, x=100.0, y=100.0)
        self.grid.add_entity(e1)

        cell_coords = self.grid.get_cell_coords(100.0, 100.0)
        self.assertEqual(cell_coords, (1, 1))
        self.assertIn(1, self.grid.cells[(1, 1)])

    def test_aoi_proximity_query(self):
        """Player at (100, 100) should see neighbor at (120, 120), but not distant entity at (500, 500)."""
        player = Entity(entity_id=1, x=100.0, y=100.0)
        nearby_enemy = Entity(entity_id=2, x=120.0, y=120.0)
        distant_enemy = Entity(entity_id=3, x=500.0, y=500.0)

        self.grid.add_entity(player)
        self.grid.add_entity(nearby_enemy)
        self.grid.add_entity(distant_enemy)

        visible_ids = self.grid.get_entities_in_aoi(player.x, player.y, radius_cells=1)
        self.assertIn(1, visible_ids)
        self.assertIn(2, visible_ids)
        self.assertNotIn(3, visible_ids)

    def test_entity_boundary_crossing(self):
        """Entity moving from (60, 60) [cell 0,0] to (70, 70) [cell 1,1] updates cell membership cleanly."""
        e = Entity(entity_id=10, x=60.0, y=60.0)
        self.grid.add_entity(e)
        self.assertIn(10, self.grid.cells[(0, 0)])

        # Move to (70, 70)
        self.grid.update_entity_position(e, 70.0, 70.0)
        self.assertNotIn(10, self.grid.cells.get((0, 0), set()))
        self.assertIn(10, self.grid.cells[(1, 1)])


if __name__ == "__main__":
    unittest.main()
