"""
Test Task 2.2: Token Count Caching

This test verifies that token count caching works correctly and improves performance.
"""

import time
from unittest.mock import patch, MagicMock
import pytest


def test_token_cache_hit_improves_performance():
    """
    Verify that cached token counts are significantly faster than computing them.
    """
    from backend.api.services.token_cache_service import cache_token_count, get_cached_token_count
    
    test_content = "This is a test message for token counting."
    test_model = "gpt-4"
    expected_tokens = 10  # Mock value
    
    # Cache the value
    cache_token_count(test_content, test_model, expected_tokens)
    
    # First retrieval (cache hit) should be very fast
    start_time = time.time()
    cached_result = get_cached_token_count(test_content, test_model)
    elapsed = time.time() - start_time
    
    assert cached_result == expected_tokens
    assert elapsed < 0.001, f"Cache retrieval took {elapsed*1000:.1f}ms, should be <1ms"


def test_token_cache_miss_computes_correctly():
    """
    Verify that cache misses compute token count correctly and cache the result.
    """
    from backend.api.token_utils import count_tokens_with_metadata
    from backend.api.services.token_cache_service import clear_token_cache, get_cached_token_count
    
    test_content = "This is another test message."
    test_model = "gpt-4"
    
    # Clear cache to ensure miss
    clear_token_cache()
    
    # First call should compute (cache miss)
    result1 = count_tokens_with_metadata(test_content, test_model)
    assert result1.tokens > 0
    assert result1.source != "cache"  # Should not be from cache
    
    # Verify it was cached
    cached = get_cached_token_count(test_content, test_model)
    assert cached == result1.tokens
    
    # Second call should hit cache
    result2 = count_tokens_with_metadata(test_content, test_model)
    assert result2.tokens == result1.tokens
    assert result2.source == "cache"  # Should be from cache


def test_token_cache_different_models():
    """
    Verify that different models have separate cache entries.
    """
    from backend.api.services.token_cache_service import cache_token_count, get_cached_token_count
    
    test_content = "Test content"
    
    # Cache different counts for different models
    cache_token_count(test_content, "gpt-4", 100)
    cache_token_count(test_content, "gpt-3.5-turbo", 95)
    
    # Verify separate entries
    assert get_cached_token_count(test_content, "gpt-4") == 100
    assert get_cached_token_count(test_content, "gpt-3.5-turbo") == 95


def test_token_cache_graceful_degradation():
    """
    Verify that token counting works even if Redis is unavailable.
    """
    from backend.api.token_utils import count_tokens_with_metadata
    
    # Mock Redis failure
    with patch('backend.api.services.token_cache_service.get_redis_client', return_value=None):
        # Should still work without caching
        result = count_tokens_with_metadata("Test message", "gpt-4")
        assert result.tokens > 0
        assert result.source != "cache"  # Should compute directly


def test_token_cache_stats():
    """
    Verify that cache stats are returned correctly.
    """
    from backend.api.services.token_cache_service import get_cache_stats, cache_token_count
    
    # Add some entries
    for i in range(5):
        cache_token_count(f"Test message {i}", "gpt-4", 10 + i)
    
    # Get stats
    stats = get_cache_stats()
    
    if stats.get("enabled"):
        assert stats["total_entries"] >= 5
        assert "memory_used_bytes" in stats
    else:
        # Redis not available, that's okay
        assert "error" in stats


def test_manual_performance_comparison():
    """
    Manual test instructions:
    
    1. Ensure Redis is running:
       docker run -d -p 6379:6379 redis
       OR
       redis-server
    
    2. Set REDIS_URL in environment:
       export REDIS_URL=redis://localhost:6379/0
    
    3. Run a request twice and compare times:
       
       First request (cache miss):
       time curl -X POST http://localhost:8000/api/complete \\
         -H "Authorization: Bearer YOUR_API_KEY" \\
         -H "Content-Type: application/json" \\
         -d '{"messages": [{"role": "user", "content": "Long message here..."}], "model": "gpt-4"}'
       
       Second request (cache hit - same content):
       time curl -X POST http://localhost:8000/api/complete \\
         -H "Authorization: Bearer YOUR_API_KEY" \\
         -H "Content-Type: application/json" \\
         -d '{"messages": [{"role": "user", "content": "Long message here..."}], "model": "gpt-4"}'
    
    4. Compare response times
    
    Expected Results:
    - Second request should be 10-15% faster
    - Logs should show "Token cache HIT" for second request
    - Redis should contain cached entries:
      redis-cli
      KEYS token_count:*
      GET token_count:<hash>:gpt-4
    """
    pass


if __name__ == "__main__":
    print("Task 2.2 Test Suite: Token Count Caching")
    print("=" * 60)
    print()
    print("Automated tests:")
    pytest.main([__file__, "-v"])
    print()
    print("Manual test instructions:")
    print(test_manual_performance_comparison.__doc__)
