import logging
from django.core.management.base import BaseCommand
from scrobbles.models import Scrobble
from locations.utils import detect_movement

logger = logging.getLogger(__name__)


class Command(BaseCommand):
    help = "Run movement detection on all location scrobbles retroactively"

    def add_arguments(self, parser):
        parser.add_argument(
            "--dry-run",
            action="store_true",
            help="Show what would be updated without making changes",
        )
        parser.add_argument(
            "--batch-size",
            type=int,
            default=100,
            help="Number of scrobbles to process at once (default: 100)",
        )
        parser.add_argument(
            "--user-id",
            type=int,
            help="Only process scrobbles for a specific user ID",
        )

    def handle(self, *args, **options):
        dry_run = options["dry_run"]
        batch_size = options["batch_size"]
        user_id = options.get("user_id")

        # Get all location scrobbles ordered by timestamp
        queryset = Scrobble.objects.filter(
            media_type=Scrobble.MediaType.GEO_LOCATION,
        ).order_by("timestamp")

        if user_id:
            queryset = queryset.filter(user_id=user_id)

        total_count = queryset.count()
        self.stdout.write(f"Processing {total_count} location scrobbles...")

        processed = 0
        updated = 0
        errors = 0

        # Track previous scrobble per user for calculated speed
        previous_scrobbles = {}

        for scrobble in queryset.iterator(chunk_size=batch_size):
            try:
                if not scrobble.geo_location:
                    processed += 1
                    continue

                # Get previous scrobble for this user
                prev = previous_scrobbles.get(scrobble.user_id)

                # Run movement detection
                movement_data = detect_movement(scrobble, prev)

                # Update previous scrobble tracker
                previous_scrobbles[scrobble.user_id] = scrobble

                # Check if we need to update
                log = scrobble.log or {}
                existing_detection = log.get("movement_detection", {})

                if existing_detection != movement_data:
                    if not dry_run:
                        # Store movement data in log
                        scrobble.log["movement_detection"] = movement_data
                        scrobble.save(update_fields=["log"])

                    updated += 1
                    self.stdout.write(
                        f"[{processed}/{total_count}] "
                        f"User {scrobble.user_id}: "
                        f"{movement_data['movement_type']} "
                        f"({movement_data['confidence']} confidence, "
                        f"{movement_data['detection_method']})"
                    )
                else:
                    self.stdout.write(f"[{processed}/{total_count}] No change needed")

                processed += 1

                if processed % 100 == 0:
                    self.stdout.write(
                        f"Progress: {processed}/{total_count} "
                        f"({processed * 100 // total_count}%)"
                    )

            except Exception as e:
                errors += 1
                logger.error(
                    f"Error processing scrobble {scrobble.id}: {e}",
                    exc_info=True,
                )
                self.stderr.write(f"Error processing scrobble {scrobble.id}: {e}")

        self.stdout.write(
            self.style.SUCCESS(
                f"Done! Processed: {processed}, "
                f"Updated: {updated}, Errors: {errors}"
            )
        )

        if dry_run:
            self.stdout.write(self.style.WARNING("Dry run - no changes were made"))
