import unittest
import time
from aiva_core.scaling_manager import ScalingManager

class TestScalingManager(unittest.TestCase):

    def test_should_scale_up(self):
        manager = ScalingManager(scale_up_threshold=0.8, scale_down_threshold=0.2)
        self.assertTrue(manager.should_scale_up(0.9))
        self.assertFalse(manager.should_scale_up(0.7))

    def test_should_scale_down_no_hysteresis(self):
        manager = ScalingManager(scale_up_threshold=0.8, scale_down_threshold=0.2, scaling_hysteresis=0)
        self.assertFalse(manager.should_scale_down(0.3)) # Initially above
        self.assertFalse(manager.should_scale_down(0.19)) # Below threshold, but no time passed
        time.sleep(0.1) #Simulate time passing, but scaling_manager uses time.time()
        manager.below_threshold_since = time.time() - 10 # Simulate it being below the threshold for a long time
        self.assertTrue(manager.should_scale_down(0.19))

    def test_should_scale_down_with_hysteresis(self):
        manager = ScalingManager(scale_up_threshold=0.8, scale_down_threshold=0.2, scaling_hysteresis=0.1)
        self.assertFalse(manager.should_scale_down(0.3)) # Initially above
        self.assertFalse(manager.should_scale_down(0.19)) # Below threshold, but not below hysteresis threshold
        time.sleep(0.1)
        manager.below_threshold_since = time.time() - 10
        self.assertFalse(manager.should_scale_down(0.19)) #Below threshold, but not below hysteresis threshold
        self.assertTrue(manager.should_scale_down(0.17)) #Below hysteresis threshold

    def test_scale_down_cooldown(self):
        manager = ScalingManager(scale_up_threshold=0.8, scale_down_threshold=0.2, cooldown_period=1)
        manager.record_scale_down()
        self.assertFalse(manager.should_scale_down(0.1))
        time.sleep(1.1)
        manager.below_threshold_since = time.time() - 10
        self.assertTrue(manager.should_scale_down(0.1))

    def test_reset_below_threshold_since(self):
        manager = ScalingManager(scale_up_threshold=0.8, scale_down_threshold=0.2)
        manager.should_scale_down(0.1) # First time below threshold
        self.assertIsNotNone(manager.below_threshold_since)
        manager.should_scale_down(0.3) # Back above threshold
        self.assertIsNone(manager.below_threshold_since)
        manager.record_scale_down()
        self.assertIsNone(manager.below_threshold_since)

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