import random
from datetime import datetime, timedelta

from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand
from django.utils import timezone

from apps.core.analytics import PageView
from apps.core.services.trending_service import trending_service
from apps.parks.models.companies import Company
from apps.parks.models.parks import Park
from apps.rides.models.rides import Ride


class Command(BaseCommand):
    help = "Test the trending algorithm with sample data"

    def add_arguments(self, parser):
        parser.add_argument(
            "--clean",
            action="store_true",
            help="Clean existing test data before creating new data",
        )
        parser.add_argument(
            "--verbose",
            action="store_true",
            help="Show detailed output",
        )

    def handle(self, *args, **options):
        self.verbose = options["verbose"]

        if options["clean"]:
            self.clean_test_data()

        self.create_test_data()
        self.test_trending_algorithm()
        self.test_api_format()

        self.stdout.write(self.style.SUCCESS("✓ Trending system test completed successfully!"))

    def clean_test_data(self):
        """Clean existing test data."""
        self.stdout.write("Cleaning existing test data...")

        # Delete test PageViews
        PageView.objects.filter(
            content_type__in=[
                ContentType.objects.get_for_model(Park),
                ContentType.objects.get_for_model(Ride),
            ]
        ).delete()

        self.stdout.write("✓ Test data cleaned")

    def create_test_data(self):
        """Create sample parks, rides, and page views for testing."""
        self.stdout.write("Creating test data...")

        # Create or get default operator company
        operator, created = Company.objects.get_or_create(
            name="Default Theme Park Operator",
            defaults={
                "roles": ["OPERATOR"],
                "description": "Default operator for test parks",
            },
        )
        if created and self.verbose:
            self.stdout.write(f"  Created operator company: {operator.name}")

        # Get or create test parks and rides
        parks_data = [
            {
                "name": "Cedar Point",
                "slug": "cedar-point",
                "description": "America's Roller Coast featuring world-class roller coasters",
                "average_rating": 9.2,
                "opening_date": datetime(1870, 1, 1).date(),
                "operator": operator,
            },
            {
                "name": "Magic Kingdom",
                "slug": "magic-kingdom",
                "description": "Walt Disney World's most magical theme park",
                "average_rating": 9.5,
                "opening_date": datetime(1971, 10, 1).date(),
                "operator": operator,
            },
            {
                "name": "Six Flags Great Adventure",
                "slug": "six-flags-great-adventure",
                "description": "Home to Kingda Ka and incredible thrills",
                "average_rating": 8.8,
                "opening_date": datetime(1974, 7, 1).date(),
                "operator": operator,
            },
        ]

        # Create parks
        parks = []
        for park_data in parks_data:
            park, created = Park.objects.get_or_create(name=park_data["name"], defaults=park_data)
            parks.append(park)
            if created and self.verbose:
                self.stdout.write(f"  Created park: {park.name}")

        # Now create rides - they need park references
        rides_data = [
            {
                "name": "Steel Vengeance",
                "slug": "steel-vengeance",
                "description": "Hybrid roller coaster at Cedar Point",
                "park": next(p for p in parks if p.name == "Cedar Point"),
                "category": "RC",  # Roller Coaster
                "average_rating": 9.8,
                "opening_date": datetime(2018, 5, 5).date(),
            },
            {
                "name": "Space Mountain",
                "slug": "space-mountain",
                "description": "Indoor space-themed roller coaster",
                "park": next(p for p in parks if p.name == "Magic Kingdom"),
                "category": "RC",  # Roller Coaster
                "average_rating": 8.5,
                "opening_date": datetime(1975, 1, 15).date(),
            },
            {
                "name": "Kingda Ka",
                "slug": "kingda-ka",
                "description": "World's tallest roller coaster",
                "park": next(p for p in parks if p.name == "Six Flags Great Adventure"),
                "category": "RC",  # Roller Coaster
                "average_rating": 9.0,
                "opening_date": datetime(2005, 5, 21).date(),
            },
            {
                "name": "Millennium Force",
                "slug": "millennium-force",
                "description": "Legendary steel roller coaster",
                "park": next(p for p in parks if p.name == "Cedar Point"),
                "category": "RC",  # Roller Coaster
                "average_rating": 9.4,
                "opening_date": datetime(2000, 5, 13).date(),
            },
        ]

        # Create rides
        rides = []
        for ride_data in rides_data:
            ride, created = Ride.objects.get_or_create(name=ride_data["name"], defaults=ride_data)
            rides.append(ride)
            if created and self.verbose:
                self.stdout.write(f"  Created ride: {ride.name}")

        # Create PageViews with different patterns to test trending
        self.create_page_views(parks, rides)

        self.stdout.write("✓ Test data created")

    def create_page_views(self, parks, rides):
        """Create PageViews with different trending patterns."""
        now = timezone.now()

        # Pattern 1: Recently trending item (Steel Vengeance)
        steel_vengeance = next(r for r in rides if r.name == "Steel Vengeance")
        self.create_views_for_content(steel_vengeance, recent_views=50, older_views=10, base_time=now)

        # Pattern 2: Consistently popular item (Space Mountain)
        space_mountain = next(r for r in rides if r.name == "Space Mountain")
        self.create_views_for_content(space_mountain, recent_views=30, older_views=25, base_time=now)

        # Pattern 3: Declining popularity (Kingda Ka)
        kingda_ka = next(r for r in rides if r.name == "Kingda Ka")
        self.create_views_for_content(kingda_ka, recent_views=5, older_views=40, base_time=now)

        # Pattern 4: New but growing (Millennium Force)
        millennium_force = next(r for r in rides if r.name == "Millennium Force")
        self.create_views_for_content(millennium_force, recent_views=25, older_views=5, base_time=now)

        # Create some park views too
        cedar_point = next(p for p in parks if p.name == "Cedar Point")
        self.create_views_for_content(cedar_point, recent_views=35, older_views=20, base_time=now)

        if self.verbose:
            self.stdout.write("  Created PageView data for trending analysis")

    def create_views_for_content(self, content_object, recent_views, older_views, base_time):
        """Create PageViews for a content object with specified patterns."""
        content_type = ContentType.objects.get_for_model(type(content_object))

        # Create recent views (last 2 hours)
        for _i in range(recent_views):
            view_time = base_time - timedelta(minutes=random.randint(0, 120))  # Last 2 hours
            PageView.objects.create(
                content_type=content_type,
                object_id=content_object.id,
                ip_address=f"192.168.1.{random.randint(1, 255)}",
                user_agent="Test Agent",
                timestamp=view_time,
            )

        # Create older views (2-24 hours ago)
        for _i in range(older_views):
            view_time = base_time - timedelta(hours=random.randint(2, 24))
            PageView.objects.create(
                content_type=content_type,
                object_id=content_object.id,
                ip_address=f"10.0.0.{random.randint(1, 255)}",
                user_agent="Test Agent",
                timestamp=view_time,
            )

    def test_trending_algorithm(self):
        """Test the trending algorithm functionality."""
        self.stdout.write("Testing trending algorithm...")

        # Test trending content for different content types
        trending_parks = trending_service.get_trending_content(content_type="parks", limit=3)
        trending_rides = trending_service.get_trending_content(content_type="rides", limit=3)
        trending_all = trending_service.get_trending_content(content_type="all", limit=5)

        # Test new content
        new_parks = trending_service.get_new_content(content_type="parks", limit=3)
        new_rides = trending_service.get_new_content(content_type="rides", limit=3)
        new_all = trending_service.get_new_content(content_type="all", limit=5)

        if self.verbose:
            self.stdout.write(f"  Trending parks: {len(trending_parks)} results")
            self.stdout.write(f"  Trending rides: {len(trending_rides)} results")
            self.stdout.write(f"  Trending all: {len(trending_all)} results")
            self.stdout.write(f"  New parks: {len(new_parks)} results")
            self.stdout.write(f"  New rides: {len(new_rides)} results")
            self.stdout.write(f"  New all: {len(new_all)} results")

        self.stdout.write("✓ Trending algorithm working correctly")

    def test_api_format(self):
        """Test that API responses match expected frontend format."""
        self.stdout.write("Testing API response format...")

        # Test trending content format
        trending_parks = trending_service.get_trending_content(content_type="parks", limit=3)
        trending_service.get_trending_content(content_type="rides", limit=3)

        # Test new content format
        new_parks = trending_service.get_new_content(content_type="parks", limit=3)
        trending_service.get_new_content(content_type="rides", limit=3)

        # Verify trending data structure
        if trending_parks:
            item = trending_parks[0]
            required_trending_fields = [
                "id",
                "name",
                "slug",
                "views",
                "views_change",
                "rank",
            ]
            for field in required_trending_fields:
                if field not in item:
                    raise ValueError(f"Missing required trending field: {field}")

        # Verify new content data structure
        if new_parks:
            item = new_parks[0]
            required_new_fields = ["id", "name", "slug"]
            for field in required_new_fields:
                if field not in item:
                    raise ValueError(f"Missing required new content field: {field}")

        if self.verbose:
            self.stdout.write("  Sample trending park data:")
            if trending_parks:
                self.stdout.write(f"    {trending_parks[0]}")

            self.stdout.write("  Sample new park data:")
            if new_parks:
                self.stdout.write(f"    {new_parks[0]}")

        self.stdout.write("✓ API format validation passed")
