"""
Management command for analyzing state transition patterns.

This command provides insights into transition usage, patterns, and statistics
across all models using django-fsm-log.
"""

from datetime import timedelta

from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand
from django.db.models import Count
from django.db.models.functions import ExtractHour, TruncDate
from django.utils import timezone
from django_fsm_log.models import StateLog


class Command(BaseCommand):
    help = "Analyze state transition patterns and generate statistics"

    def add_arguments(self, parser):
        parser.add_argument("--days", type=int, default=30, help="Number of days to analyze (default: 30)")
        parser.add_argument("--model", type=str, help="Specific model to analyze (e.g., editsubmission)")
        parser.add_argument(
            "--output",
            type=str,
            choices=["console", "json", "csv"],
            default="console",
            help="Output format (default: console)",
        )

    def handle(self, *args, **options):
        days = options["days"]
        model_filter = options["model"]
        output_format = options["output"]

        self.stdout.write(self.style.SUCCESS(f"\n=== State Transition Analysis (Last {days} days) ===\n"))

        # Filter by date range
        start_date = timezone.now() - timedelta(days=days)
        queryset = StateLog.objects.filter(timestamp__gte=start_date)

        # Filter by specific model if provided
        if model_filter:
            try:
                content_type = ContentType.objects.get(model=model_filter.lower())
                queryset = queryset.filter(content_type=content_type)
                self.stdout.write(f"Filtering for model: {model_filter}\n")
            except ContentType.DoesNotExist:
                self.stdout.write(self.style.ERROR(f'Model "{model_filter}" not found'))
                return

        # Total transitions
        total_transitions = queryset.count()
        self.stdout.write(self.style.SUCCESS(f"Total Transitions: {total_transitions}\n"))

        if total_transitions == 0:
            self.stdout.write(self.style.WARNING("No transitions found in the specified period."))
            return

        # Most common transitions
        self.stdout.write(self.style.SUCCESS("\n--- Most Common Transitions ---"))
        common_transitions = (
            queryset.values("transition", "content_type__model").annotate(count=Count("id")).order_by("-count")[:10]
        )

        for t in common_transitions:
            model_name = t["content_type__model"]
            transition_name = t["transition"] or "N/A"
            count = t["count"]
            percentage = (count / total_transitions) * 100
            self.stdout.write(f"  {model_name}.{transition_name}: {count} ({percentage:.1f}%)")

        # Transitions by model
        self.stdout.write(self.style.SUCCESS("\n--- Transitions by Model ---"))
        by_model = queryset.values("content_type__model").annotate(count=Count("id")).order_by("-count")

        for m in by_model:
            model_name = m["content_type__model"]
            count = m["count"]
            percentage = (count / total_transitions) * 100
            self.stdout.write(f"  {model_name}: {count} ({percentage:.1f}%)")

        # Transitions by state
        self.stdout.write(self.style.SUCCESS("\n--- Final States Distribution ---"))
        by_state = queryset.values("state").annotate(count=Count("id")).order_by("-count")

        for s in by_state:
            state_name = s["state"]
            count = s["count"]
            percentage = (count / total_transitions) * 100
            self.stdout.write(f"  {state_name}: {count} ({percentage:.1f}%)")

        # Most active users
        self.stdout.write(self.style.SUCCESS("\n--- Most Active Users ---"))
        active_users = (
            queryset.exclude(by__isnull=True)
            .values("by__username", "by__id")
            .annotate(count=Count("id"))
            .order_by("-count")[:10]
        )

        for u in active_users:
            username = u["by__username"]
            user_id = u["by__id"]
            count = u["count"]
            self.stdout.write(f"  {username} (ID: {user_id}): {count} transitions")

        # System vs User transitions
        system_count = queryset.filter(by__isnull=True).count()
        user_count = queryset.exclude(by__isnull=True).count()

        self.stdout.write(self.style.SUCCESS("\n--- Transition Attribution ---"))
        self.stdout.write(f"  User-initiated: {user_count} ({(user_count/total_transitions)*100:.1f}%)")
        self.stdout.write(f"  System-initiated: {system_count} ({(system_count/total_transitions)*100:.1f}%)")

        # Daily transition volume
        # Security: Using Django ORM functions instead of raw SQL .extra() to prevent SQL injection
        self.stdout.write(self.style.SUCCESS("\n--- Daily Transition Volume ---"))
        daily_stats = (
            queryset.annotate(day=TruncDate("timestamp")).values("day").annotate(count=Count("id")).order_by("-day")[:7]
        )

        for day in daily_stats:
            date = day["day"]
            count = day["count"]
            self.stdout.write(f"  {date}: {count} transitions")

        # Busiest hours
        # Security: Using Django ORM functions instead of raw SQL .extra() to prevent SQL injection
        self.stdout.write(self.style.SUCCESS("\n--- Busiest Hours (UTC) ---"))
        hourly_stats = (
            queryset.annotate(hour=ExtractHour("timestamp"))
            .values("hour")
            .annotate(count=Count("id"))
            .order_by("-count")[:5]
        )

        for hour in hourly_stats:
            hour_val = int(hour["hour"])
            count = hour["count"]
            self.stdout.write(f"  Hour {hour_val:02d}:00: {count} transitions")

        # Transition patterns (common sequences)
        self.stdout.write(self.style.SUCCESS("\n--- Common Transition Patterns ---"))
        self.stdout.write("  Analyzing transition sequences...")

        # Get recent objects and their transition sequences
        recent_objects = queryset.values("content_type", "object_id").distinct()[:100]

        pattern_counts = {}
        for obj in recent_objects:
            transitions = list(
                StateLog.objects.filter(content_type=obj["content_type"], object_id=obj["object_id"])
                .order_by("timestamp")
                .values_list("transition", flat=True)
            )

            # Create pattern from consecutive transitions
            if len(transitions) >= 2:
                pattern = " → ".join([t or "N/A" for t in transitions[:3]])
                pattern_counts[pattern] = pattern_counts.get(pattern, 0) + 1

        # Display top patterns
        sorted_patterns = sorted(pattern_counts.items(), key=lambda x: x[1], reverse=True)[:5]

        for pattern, count in sorted_patterns:
            self.stdout.write(f"  {pattern}: {count} occurrences")

        self.stdout.write(self.style.SUCCESS("\n=== Analysis Complete ===\n"))

        # Export options
        if output_format == "json":
            self._export_json(queryset, days)
        elif output_format == "csv":
            self._export_csv(queryset, days)

    def _export_json(self, queryset, days):
        """Export analysis results as JSON."""
        import json
        from datetime import datetime

        data = {
            "analysis_date": datetime.now().isoformat(),
            "period_days": days,
            "total_transitions": queryset.count(),
            "transitions": list(
                queryset.values(
                    "id", "timestamp", "state", "transition", "content_type__model", "object_id", "by__username"
                )
            ),
        }

        filename = f'transition_analysis_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json'
        with open(filename, "w") as f:
            json.dump(data, f, indent=2, default=str)

        self.stdout.write(self.style.SUCCESS(f"Exported to {filename}"))

    def _export_csv(self, queryset, days):
        """Export analysis results as CSV."""
        import csv
        from datetime import datetime

        filename = f'transition_analysis_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv'

        with open(filename, "w", newline="") as f:
            writer = csv.writer(f)
            writer.writerow(["ID", "Timestamp", "Model", "Object ID", "State", "Transition", "User"])

            for log in queryset.select_related("content_type", "by"):
                writer.writerow(
                    [
                        log.id,
                        log.timestamp,
                        log.content_type.model,
                        log.object_id,
                        log.state,
                        log.transition or "N/A",
                        log.by.username if log.by else "System",
                    ]
                )

        self.stdout.write(self.style.SUCCESS(f"Exported to {filename}"))
