import sys
import os
import time

# Ensure project root is in path
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src")))

from performance_monitor import PerformanceMonitor

def test_perf_monitor_basic_timing() -> None:
 pm = PerformanceMonitor()
 pm.start_frame()
 time.sleep(0.02) # 20ms
 pm.end_frame()
 metrics = pm.get_metrics()
 assert metrics['last_frame_time_ms'] >= 20.0
 pm.stop()

def test_perf_monitor_component_timing() -> None:
 pm = PerformanceMonitor()
 pm.enabled = True
 pm.start_component("test_comp")
 time.sleep(0.01)
 pm.end_component("test_comp")
 metrics = pm.get_metrics()
 assert metrics['time_test_comp_ms'] >= 10.0
 pm.stop()

def test_perf_monitor_scope_context_manager() -> None:
 pm = PerformanceMonitor()
 pm.enabled = True
 
 # Test normal usage
 with pm.scope("test_scope"):
  time.sleep(0.01)
 
 metrics = pm.get_metrics()
 assert metrics['time_test_scope_ms'] >= 10.0
 
 # Test exception handling
 try:
  with pm.scope("test_error"):
   time.sleep(0.01)
   raise ValueError("test error")
 except ValueError:
  pass
 
 metrics = pm.get_metrics()
 # Component should still be finished, so timing should be recorded
 assert metrics['time_test_error_ms'] >= 10.0
 
 pm.stop()

def test_perf_monitor_extended_metrics() -> None:
 pm = PerformanceMonitor()
 pm.enabled = True
 
 # 1st call: 10ms
 pm.start_component("test_comp")
 time.sleep(0.01)
 pm.end_component("test_comp")
 
 # 2nd call: 30ms
 pm.start_component("test_comp")
 time.sleep(0.03)
 pm.end_component("test_comp")
 
 # 3rd call: 20ms
 pm.start_component("test_comp")
 time.sleep(0.02)
 pm.end_component("test_comp")
 
 metrics = pm.get_metrics()
 assert metrics['count_test_comp'] == 3.0
 assert metrics['max_test_comp_ms'] >= 30.0
 assert metrics['min_test_comp_ms'] >= 10.0
 assert metrics['min_test_comp_ms'] < 20.0
 
 pm.stop()


