import pytest
import time
import random
from threading import Thread
from security.rbac_engine import RBACEngine, Role
from cryptography.fernet import Fernet

@pytest.fixture
def rbac_engine():
    """Fixture providing initialized RBAC engine"""
    key = Fernet.generate_key()
    engine = RBACEngine(key)
    
    # Setup test roles and permissions
    for i in range(100):
        email = f"user{i}@example.com"
        role = random.choice(list(Role))
        engine.assign_role(email, role, "example.com")
    
    return engine

def test_role_resolution_latency(benchmark, rbac_engine):
    """Benchmark role resolution time"""
    def resolve_role():
        email = f"user{random.randint(0,99)}@example.com"
        return rbac_engine.get_user_roles(email)
    
    benchmark(resolve_role)

def test_permission_check_throughput(benchmark, rbac_engine):
    """Benchmark permission validation throughput"""
    def check_permission():
        email = f"user{random.randint(0,99)}@example.com"
        resource = random.choice(["tasks", "logs", "admin"])
        action = random.choice(["read", "write", "delete"])
        return rbac_engine.validate_permission(email, resource, action)
    
    benchmark.pedantic(check_permission, rounds=1000, iterations=10)

def test_concurrent_sessions(rbac_engine):
    """Test concurrent session handling"""
    results = []
    
    def worker():
        start = time.time()
        email = f"user{random.randint(0,99)}@example.com"
        roles = rbac_engine.get_user_roles(email)
        results.append(time.time() - start)
    
    threads = [Thread(target=worker) for _ in range(1000)]
    [t.start() for t in threads]
    [t.join() for t in threads]
    
    avg_latency = sum(results) / len(results)
    assert avg_latency < 0.05  # 50ms threshold

def test_memory_usage(rbac_engine):
    """Test memory growth under sustained load"""
    import tracemalloc
    
    tracemalloc.start()
    
    # Take initial snapshot
    snapshot1 = tracemalloc.take_snapshot()
    
    # Perform sustained operations
    for _ in range(10000):
        email = f"user{random.randint(0,99)}@example.com"
        rbac_engine.validate_permission(email, "tasks", "read")
    
    # Take final snapshot and compare
    snapshot2 = tracemalloc.take_snapshot()
    top_stats = snapshot2.compare_to(snapshot1, 'lineno')
    
    # Check memory growth is within limits
    total_growth = sum(stat.size_diff for stat in top_stats)
    assert total_growth < 5 * 1024 * 1024  # 5MB threshold