"""Performance tests for {{ module_name }} API module."""

import pytest
import time
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import StaticPool

from {{ module_name }}.models import Base
from {{ module_name }}.services import {{ module_name_title }}Service
from {{ module_name }}.schemas import {{ module_name_title }}Create
from {{ module_name }}.routers import router


class Test{{ module_name_title }}APIPerformance:
    """Performance tests for {{ module_name_title }} API."""
    
    @pytest.fixture
    def db_session(self):
        """Create in-memory database session for testing."""
        engine = create_engine(
            "sqlite:///:memory:",
            connect_args={"check_same_thread": False},
            poolclass=StaticPool,
        )
        TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
        Base.metadata.create_all(bind=engine)
        
        session = TestingSessionLocal()
        try:
            yield session
        finally:
            session.close()
            Base.metadata.drop_all(bind=engine)
    
    @pytest.fixture
    def {{ module_name }}_service(self, db_session):
        """Create {{ module_name }} service with test database."""
        return {{ module_name_title }}Service(db_session)
    
    @pytest.fixture
    def client(self, {{ module_name }}_service):
        """Create test client with mocked dependencies."""
        from fastapi import FastAPI
        
        app = FastAPI()
        app.include_router(router, prefix="/{{ module_name }}s")
        
        # Override dependency
        app.dependency_overrides[get_{{ module_name }}_service] = lambda: {{ module_name }}_service
        
        return TestClient(app)
    
    def test_api_bulk_create_performance(self, client):
        """Test performance of bulk {{ module_name }} creation via API."""
        start_time = time.time()
        
        # Create 50 {{ module_name }}s via API
        for i in range(50):
            response = client.post(
                "/{{ module_name }}s/",
                json={"name": f"{{ module_name_title }} {i}", "description": f"Description {i}"}
            )
            assert response.status_code == 201
        
        end_time = time.time()
        creation_time = end_time - start_time
        
        # Should complete within 2 seconds
        assert creation_time < 2.0, f"API bulk creation took {creation_time:.2f}s, expected < 2.0s"
    
    def test_api_bulk_retrieval_performance(self, client, {{ module_name }}_service):
        """Test performance of bulk {{ module_name }} retrieval via API."""
        # Create test data
        for i in range(30):
            {{ module_name }}_data = {{ module_name_title }}Create(name=f"{{ module_name_title }} {i}", description=f"Desc {i}")
            {{ module_name }}_service.create({{ module_name }}_data)
        
        # Test API retrieval performance
        start_time = time.time()
        response = client.get("/{{ module_name }}s/")
        end_time = time.time()
        
        assert response.status_code == 200
        retrieval_time = end_time - start_time
        
        # Should complete within 1 second
        assert retrieval_time < 1.0, f"API retrieval took {retrieval_time:.2f}s, expected < 1.0s"
        
        data = response.json()
        assert len(data) == 30
    
    def test_api_search_performance(self, client, {{ module_name }}_service):
        """Test performance of {{ module_name }} search via API."""
        # Create test data
        searchable_names = ["apple", "banana", "cherry", "date", "elderberry"]
        for name in searchable_names:
            {{ module_name }}_data = {{ module_name_title }}Create(name=name, description=f"Description for {name}")
            {{ module_name }}_service.create({{ module_name }}_data)
        
        # Test search performance
        start_time = time.time()
        
        # Perform multiple searches (assuming search endpoint exists)
        for name in searchable_names:
            # For now, test get all and filter
            response = client.get("/{{ module_name }}s/")
            assert response.status_code == 200
            data = response.json()
            found = any(item["name"] == name for item in data)
            assert found
        
        end_time = time.time()
        search_time = end_time - start_time
        
        # Should complete within 0.5 seconds
        assert search_time < 0.5, f"API search took {search_time:.2f}s, expected < 0.5s"
    
    def test_api_concurrent_requests(self, client, {{ module_name }}_service):
        """Test API performance under concurrent requests."""
        import threading
        
        # Create test data
        for i in range(10):
            {{ module_name }}_data = {{ module_name_title }}Create(name=f"{{ module_name_title }} {i}", description=f"Desc {i}")
            {{ module_name }}_service.create({{ module_name }}_data)
        
        results = []
        errors = []
        
        def make_request():
            try:
                start_time = time.time()
                response = client.get("/{{ module_name }}s/")
                end_time = time.time()
                
                if response.status_code == 200:
                    results.append(end_time - start_time)
                else:
                    errors.append(f"Request failed with status {response.status_code}")
            except Exception as e:
                errors.append(str(e))
        
        # Create 5 concurrent threads
        threads = []
        for _ in range(5):
            thread = threading.Thread(target=make_request)
            threads.append(thread)
            thread.start()
        
        # Wait for all threads to complete
        for thread in threads:
            thread.join()
        
        # Verify no errors
        assert len(errors) == 0, f"Concurrent requests had errors: {errors}"
        
        # Verify all requests completed
        assert len(results) == 5, f"Expected 5 results, got {len(results)}"
        
        # Verify performance is reasonable
        avg_time = sum(results) / len(results)
        assert avg_time < 0.5, f"Average request time {avg_time:.2f}s, expected < 0.5s"
    
    def test_api_memory_usage(self, client, {{ module_name }}_service):
        """Test memory usage during API operations."""
        import psutil
        import os
        
        process = psutil.Process(os.getpid())
        initial_memory = process.memory_info().rss / 1024 / 1024  # MB
        
        # Create 500 {{ module_name }}s via API
        for i in range(500):
            response = client.post(
                "/{{ module_name }}s/",
                json={"name": f"{{ module_name_title }} {i}", "description": f"Description {i}"}
            )
            assert response.status_code == 201
        
        # Perform multiple retrievals
        for _ in range(10):
            response = client.get("/{{ module_name }}s/")
            assert response.status_code == 200
        
        final_memory = process.memory_info().rss / 1024 / 1024  # MB
        memory_increase = final_memory - initial_memory
        
        # Memory increase should be reasonable (< 200MB)
        assert memory_increase < 200, f"Memory increased by {memory_increase:.1f}MB, expected < 200MB"
