"""Load testing with Locust for RateRight system performance"""
from locust import HttpUser, task, between
import random
import json


class RateRightUser(HttpUser):
    """Simulate realistic user behavior on RateRight platform"""
    
    wait_time = between(1, 5)  # Wait 1-5 seconds between requests
    
    def on_start(self):
        """Set up user session on start"""
        self.login()
    
    def login(self):
        """Log in as a test user"""
        # Try to login as test user
        response = self.client.post("/login", data={
            "email": "load_test_user@example.com",
            "password": "loadtest123"
        }, catch_response=True)
        
        if response.status_code != 200:
            # If user doesn't exist, create one via registration
            self.client.post("/register", data={
                "email": "load_test_user@example.com",
                "password": "loadtest123", 
                "confirm_password": "loadtest123",
                "first_name": "Load",
                "last_name": "Test",
                "role": "worker",
                "phone_number": "0400000000",
                "location": "Sydney, NSW",
                "abn_number": "12345678901"
            })
    
    @task(3)
    def browse_jobs(self):
        """Browse available jobs (most common action)"""
        self.client.get("/jobs")
    
    @task(2)
    def view_dashboard(self):
        """View user dashboard"""
        self.client.get("/dashboard")
    
    @task(2)
    def browse_workers(self):
        """Browse worker profiles"""
        self.client.get("/workers")
    
    @task(1)
    def view_profile(self):
        """View user profile"""
        self.client.get("/profile")
    
    @task(1)
    def check_notifications(self):
        """Check notification center"""
        self.client.get("/api/notifications/")
    
    @task(1)
    def poll_messages(self):
        """Poll for new messages (simulates real-time updates)"""
        self.client.get("/api/messages/poll")
    
    @task(1)
    def get_conversations(self):
        """Get user conversations"""
        self.client.get("/api/messages/conversations")


class ContractorUser(HttpUser):
    """Simulate contractor-specific behavior"""
    
    wait_time = between(2, 6)
    
    def on_start(self):
        """Login as contractor"""
        response = self.client.post("/login", data={
            "email": "contractor_load@example.com",
            "password": "contractor123"
        }, catch_response=True)
    
    @task(3)
    def view_contractor_dashboard(self):
        """View contractor dashboard"""
        self.client.get("/dashboard/contractor")
    
    @task(2)
    def view_applications(self):
        """Check job applications"""
        self.client.get("/applications")
    
    @task(2)
    def view_contracts(self):
        """View active contracts"""
        self.client.get("/contracts")
    
    @task(1)
    def post_job_form(self):
        """View job posting form"""
        self.client.get("/jobs/post")
    
    @task(1)
    def check_leaderboard(self):
        """Check gamification leaderboard"""
        self.client.get("/api/gamification/leaderboard/weekly")


class WorkerUser(HttpUser):
    """Simulate worker-specific behavior"""
    
    wait_time = between(1, 4)
    
    def on_start(self):
        """Login as worker"""
        self.client.post("/login", data={
            "email": "worker_load@example.com", 
            "password": "worker123"
        })
    
    @task(4)
    def search_jobs(self):
        """Search for jobs"""
        self.client.get("/jobs")
        self.client.get("/search")
    
    @task(2)
    def view_worker_dashboard(self):
        """View worker dashboard"""
        self.client.get("/dashboard/worker")
    
    @task(2)
    def view_job_details(self):
        """View specific job details"""
        job_id = random.randint(1, 50)  # Assume 50 test jobs exist
        self.client.get(f"/jobs/{job_id}")
    
    @task(1)
    def view_my_applications(self):
        """View my job applications"""
        self.client.get("/applications")
    
    @task(1)
    def check_points_and_level(self):
        """Check gamification progress"""
        self.client.get("/api/gamification/user-stats")


class APIUser(HttpUser):
    """Test API endpoints specifically"""
    
    wait_time = between(0.5, 2)
    
    def on_start(self):
        """Login to get session"""
        self.client.post("/login", data={
            "email": "api_test@example.com",
            "password": "apitest123"
        })
    
    @task(5)
    def api_health_check(self):
        """Check API health"""
        self.client.get("/api/health")
    
    @task(3)
    def api_notifications(self):
        """Get notifications via API"""
        self.client.get("/api/notifications/")
    
    @task(3)
    def api_messages_poll(self):
        """Message polling API"""
        self.client.get("/api/messages/poll")
    
    @task(2)
    def api_gamification_stats(self):
        """Get gamification statistics"""
        self.client.get("/api/gamification/leaderboard/weekly")
    
    @task(2)
    def send_test_message(self):
        """Send message via API"""
        self.client.post("/api/messages/", json={
            "receiver_id": random.randint(1, 10),
            "content": f"Load test message {random.randint(1, 1000)}",
            "message_type": "text"
        })
    
    @task(1)
    def submit_test_rating(self):
        """Submit rating via API"""
        contract_id = random.randint(1, 20)
        rating = random.randint(3, 5)
        
        self.client.post(f"/contracts/{contract_id}/rate", data={
            "overall_rating": rating,
            "quality_rating": rating,
            "communication_rating": rating,
            "safety_rating": rating,
            "comment": f"Load test rating {random.randint(1, 100)}"
        })


class HighVolumeMessageUser(HttpUser):
    """Simulate high-volume messaging for stress testing"""
    
    wait_time = between(0.1, 0.5)  # Very fast messaging
    
    def on_start(self):
        self.client.post("/login", data={
            "email": "message_spam@example.com",
            "password": "spam123"
        })
    
    @task(10)
    def rapid_fire_messages(self):
        """Send messages rapidly"""
        for i in range(5):  # Send 5 messages per task
            self.client.post("/api/messages/", json={
                "receiver_id": random.randint(1, 5),
                "content": f"Rapid message {i} - {random.randint(1, 10000)}",
                "message_type": "text"
            })
    
    @task(5)
    def constant_polling(self):
        """Poll messages constantly"""
        self.client.get("/api/messages/poll")
    
    @task(3)
    def mark_messages_read(self):
        """Mark messages as read rapidly"""
        message_id = random.randint(1, 100)
        self.client.post(f"/api/messages/{message_id}/read")


class GamificationStressUser(HttpUser):
    """Stress test gamification system"""
    
    wait_time = between(0.2, 1)
    
    def on_start(self):
        self.client.post("/login", data={
            "email": "gamer@example.com",
            "password": "gamer123"
        })
    
    @task(5)
    def award_points_rapidly(self):
        """Trigger point awarding rapidly"""
        # These would normally be triggered by completing actions
        # For load testing, we'll call test endpoints if they exist
        self.client.get("/api/test/award-points/1?points=10")
    
    @task(5)
    def check_leaderboards(self):
        """Check different leaderboards"""
        boards = ["weekly", "monthly", "all_time"]
        board = random.choice(boards)
        self.client.get(f"/api/gamification/leaderboard/{board}")
    
    @task(3)
    def check_achievements(self):
        """Check achievement progress"""
        self.client.get("/api/test/achievements/1")
    
    @task(2)
    def full_gamification_test(self):
        """Run full gamification test suite"""
        self.client.get("/api/test/full-test/1")


class NotificationStressUser(HttpUser):
    """Stress test notification system"""
    
    wait_time = between(0.1, 0.5)
    
    def on_start(self):
        self.client.post("/login", data={
            "email": "notify@example.com",
            "password": "notify123"
        })
    
    @task(8)
    def trigger_notifications(self):
        """Trigger various notifications"""
        notification_types = [
            "job_match_found",
            "rating_received", 
            "payment_received",
            "message_received"
        ]
        notif_type = random.choice(notification_types)
        
        # This would normally be triggered by system events
        # For testing, use test endpoints
        self.client.post("/api/test/notifications/trigger", json={
            "type": notif_type,
            "user_id": random.randint(1, 10)
        })
    
    @task(5)
    def check_notifications(self):
        """Check notification inbox"""
        self.client.get("/api/notifications/")
    
    @task(3)
    def mark_notifications_read(self):
        """Mark notifications as read"""
        notif_id = random.randint(1, 100)
        self.client.post(f"/api/notifications/{notif_id}/read")
    
    @task(2)
    def batch_notification_test(self):
        """Test batch notifications"""
        self.client.get("/api/test/notifications/batch")


# Custom load test scenarios

def create_database_stress_test():
    """
    Custom scenario for database stress testing
    Run with: locust -f load_test.py --headless -u 100 -r 10 -t 300s --host http://localhost:5000
    """
    class DatabaseStressUser(HttpUser):
        wait_time = between(0.1, 0.3)
        
        @task(10)
        def heavy_database_queries(self):
            # Multiple complex queries
            self.client.get("/api/search/jobs?q=construction&location=Sydney")
            self.client.get("/api/gamification/leaderboard/all_time?limit=100")
            self.client.get("/api/notifications/?limit=50")
            self.client.get("/api/messages/conversations")


def create_api_stress_test():
    """
    API-only stress test
    Run with: locust -f load_test.py --headless -u 200 -r 20 -t 600s --host http://localhost:5000
    """
    class APIOnlyUser(HttpUser):
        wait_time = between(0.05, 0.1)
        
        @task(20)
        def api_endpoints_only(self):
            endpoints = [
                "/api/health",
                "/api/notifications/",
                "/api/messages/poll", 
                "/api/gamification/leaderboard/weekly",
                "/api/contracts/",
                "/api/jobs/"
            ]
            endpoint = random.choice(endpoints)
            self.client.get(endpoint)


# Usage Instructions:
"""
Basic load test:
locust -f tests/load_test.py --host=http://localhost:5000

Web UI mode (recommended):
locust -f tests/load_test.py --host=http://localhost:5000
# Then open http://localhost:8089

Headless mode:
locust -f tests/load_test.py --headless -u 50 -r 5 -t 300s --host=http://localhost:5000

Specific user types:
locust -f tests/load_test.py ContractorUser WorkerUser --host=http://localhost:5000

High volume messaging test:
locust -f tests/load_test.py HighVolumeMessageUser --headless -u 20 -r 2 -t 180s --host=http://localhost:5000

API stress test:
locust -f tests/load_test.py APIUser --headless -u 100 -r 10 -t 600s --host=http://localhost:5000

Parameters:
-u: Number of users to simulate
-r: Spawn rate (users per second)
-t: Test duration (e.g., 300s, 10m, 1h)
--host: Target host URL
--headless: Run without web UI
"""
