from datetime import timedelta

from django.db.models import Avg, Count
from django.db.models.functions import TruncDate
from django.utils import timezone
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny, IsAdminUser
from rest_framework.response import Response

from apps.analytics.filters import UserEventFilter, UserSessionFilter
from apps.analytics.models import UserEvent, UserSession
from apps.analytics.serializers import (
    UserEventBatchSerializer,
    UserEventCreateSerializer,
    UserEventListSerializer,
    UserSessionCreateSerializer,
    UserSessionListSerializer,
)


class EventTrackingViewSet(viewsets.GenericViewSet):
    """Endpoints for the mobile app to send behavior events.

    - track : send a single event (authenticated or guest)
    - batch : send multiple events at once
    - session : report a session start/end
    """

    def get_permissions(self):
        # Allow both authenticated and guest users to track events
        return [AllowAny()]

    def _get_client_ip(self, request):
        x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
        if x_forwarded_for:
            return x_forwarded_for.split(",")[0].strip()
        return request.META.get("REMOTE_ADDR")

    @action(detail=False, methods=["post"], url_path="track")
    def track(self, request):
        """POST /analytics/track/ — send a single event."""
        serializer = UserEventCreateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        event = serializer.save(
            user=request.user if request.user.is_authenticated else None,
            ip_address=self._get_client_ip(request),
        )
        return Response({"id": event.id}, status=status.HTTP_201_CREATED)

    @action(detail=False, methods=["post"], url_path="batch")
    def batch(self, request):
        """POST /analytics/batch/ — send multiple events at once."""
        serializer = UserEventBatchSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        events_data = serializer.validated_data["events"]
        user = request.user if request.user.is_authenticated else None
        ip = self._get_client_ip(request)

        events = [
            UserEvent(user=user, ip_address=ip, **event_data)
            for event_data in events_data
        ]
        created = UserEvent.objects.bulk_create(events)

        return Response(
            {"count": len(created), "message": f"{len(created)} events recorded."},
            status=status.HTTP_201_CREATED,
        )

    @action(detail=False, methods=["post"], url_path="session")
    def session(self, request):
        """POST /analytics/session/ — report session start or end."""
        serializer = UserSessionCreateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)

        session_id = serializer.validated_data["session_id"]
        user = request.user if request.user.is_authenticated else None

        session, created = UserSession.objects.update_or_create(
            session_id=session_id,
            defaults={
                "user": user,
                **serializer.validated_data,
            },
        )

        return Response(
            UserSessionListSerializer(session).data,
            status=status.HTTP_201_CREATED if created else status.HTTP_200_OK,
        )


class EventAdminViewSet(viewsets.ReadOnlyModelViewSet):
    """Admin read-only access to all tracked events.

    Supports filtering by user, event_type, screen, platform, date range, etc.
    """

    permission_classes = [IsAdminUser]
    serializer_class = UserEventListSerializer
    filterset_class = UserEventFilter
    ordering_fields = ["created_at", "event_type", "screen_name"]
    ordering = ["-created_at"]

    def get_queryset(self):
        return UserEvent.objects.select_related("user").all()


class SessionAdminViewSet(viewsets.ReadOnlyModelViewSet):
    """Admin read-only access to all sessions."""

    permission_classes = [IsAdminUser]
    serializer_class = UserSessionListSerializer
    filterset_class = UserSessionFilter
    ordering_fields = ["started_at", "duration_seconds", "events_count"]
    ordering = ["-started_at"]

    def get_queryset(self):
        return UserSession.objects.select_related("user").all()


class AnalyticsDashboardViewSet(viewsets.ViewSet):
    """Admin dashboard — aggregated analytics.

    GET /analytics/dashboard/summary/ — overall stats
    GET /analytics/dashboard/top-screens/ — most visited screens
    GET /analytics/dashboard/top-events/ — most triggered events
    GET /analytics/dashboard/user-activity/?user_id=X — specific user timeline
    GET /analytics/dashboard/funnel/ — conversion funnel
    """

    permission_classes = [IsAdminUser]

    @action(detail=False, methods=["get"], url_path="summary")
    def summary(self, request):
        """GET /analytics/dashboard/summary/ — key metrics."""
        now = timezone.now()
        today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
        week_ago = now - timedelta(days=7)
        month_ago = now - timedelta(days=30)

        total_events = UserEvent.objects.count()
        total_sessions = UserSession.objects.count()
        total_users = UserEvent.objects.values("user").distinct().count()

        active_today = (
            UserEvent.objects.filter(created_at__gte=today_start)
            .values("user").distinct().count()
        )
        active_week = (
            UserEvent.objects.filter(created_at__gte=week_ago)
            .values("user").distinct().count()
        )
        active_month = (
            UserEvent.objects.filter(created_at__gte=month_ago)
            .values("user").distinct().count()
        )

        avg_duration = (
            UserSession.objects.filter(duration_seconds__isnull=False)
            .aggregate(avg=Avg("duration_seconds"))["avg"] or 0
        )

        # Top screens (last 30 days)
        top_screens = list(
            UserEvent.objects.filter(
                created_at__gte=month_ago,
                screen_name__gt="",
            )
            .values("screen_name")
            .annotate(count=Count("id"))
            .order_by("-count")[:10]
        )

        # Top event types (last 30 days)
        top_events = list(
            UserEvent.objects.filter(created_at__gte=month_ago)
            .values("event_type")
            .annotate(count=Count("id"))
            .order_by("-count")[:10]
        )

        # Events per day (last 14 days)
        events_by_day = list(
            UserEvent.objects.filter(created_at__gte=now - timedelta(days=14))
            .annotate(date=TruncDate("created_at"))
            .values("date")
            .annotate(count=Count("id"))
            .order_by("date")
        )
        # Convert dates to strings
        for entry in events_by_day:
            entry["date"] = entry["date"].isoformat()

        data = {
            "total_events": total_events,
            "total_sessions": total_sessions,
            "total_users": total_users,
            "active_users_today": active_today,
            "active_users_week": active_week,
            "active_users_month": active_month,
            "avg_session_duration": round(avg_duration, 1),
            "top_screens": top_screens,
            "top_events": top_events,
            "events_by_day": events_by_day,
        }
        return Response(data)

    @action(detail=False, methods=["get"], url_path="user-activity")
    def user_activity(self, request):
        """GET /analytics/dashboard/user-activity/?user_id=X — user's full timeline."""
        user_id = request.query_params.get("user_id")
        if not user_id:
            return Response(
                {"detail": "user_id query param required."},
                status=status.HTTP_400_BAD_REQUEST,
            )

        events = (
            UserEvent.objects.filter(user_id=user_id)
            .order_by("-created_at")[:200]
        )
        serializer = UserEventListSerializer(events, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=["get"], url_path="funnel")
    def funnel(self, request):
        """GET /analytics/dashboard/funnel/ — conversion funnel stats."""
        days = int(request.query_params.get("days", 30))
        since = timezone.now() - timedelta(days=days)

        base_qs = UserEvent.objects.filter(created_at__gte=since)

        funnel = {
            "app_opens": base_qs.filter(event_type="app_open").values("user").distinct().count(),
            "store_views": base_qs.filter(event_type="store_view").values("user").distinct().count(),
            "product_views": base_qs.filter(event_type="product_view").values("user").distinct().count(),
            "favorites_added": base_qs.filter(event_type="favorite_add").values("user").distinct().count(),
            "whatsapp_clicks": base_qs.filter(event_type="whatsapp_click").values("user").distinct().count(),
            "shares": base_qs.filter(event_type="share").values("user").distinct().count(),
        }

        return Response({"days": days, "funnel": funnel})
