

from datetime import timedelta
from django.utils import timezone

from django.db.models import Count, Q

from django.db.models.functions import TruncDate

from rest_framework.views import APIView

from rest_framework.permissions import IsAuthenticated

from rest_framework.response import Response

from adverts.models import AdBanner, BannerEvent

from blog.permissions import IsBlogAdmin

from .serializers import (
    BannerDashboardSerializer,
    BannerPerformanceSerializer,
    BannerTimelineSerializer,
)


class BannerDashboardView(APIView):

    permission_classes = [
        IsAuthenticated,
        IsBlogAdmin,
    ]

    def get(self, request):

        total_banners = AdBanner.objects.count()

        active_banners = (
            AdBanner.objects
            .filter(is_active=True)
            .count()
        )

        inactive_banners = (
            total_banners - active_banners
        )

        total_impressions = (
            BannerEvent.objects
            .filter(event_type="impression")
            .count()
        )

        total_clicks = (
            BannerEvent.objects
            .filter(event_type="click")
            .count()
        )

        overall_ctr = 0

        if total_impressions > 0:
            overall_ctr = round(
                (total_clicks / total_impressions) * 100,
                2,
            )

        serializer = BannerDashboardSerializer({
            "total_banners": total_banners,
            "active_banners": active_banners,
            "inactive_banners": inactive_banners,
            "total_impressions": total_impressions,
            "total_clicks": total_clicks,
            "overall_ctr": overall_ctr,
        })

        return Response(serializer.data)
    
class BannerPerformanceView(APIView):

    permission_classes = [
        IsAuthenticated,
        IsBlogAdmin,
    ]

    def get(self, request):

        banners = AdBanner.objects.all()

        results = []

        for banner in banners:

            impressions = BannerEvent.objects.filter(
                banner=banner,
                event_type="impression",
            ).count()

            clicks = BannerEvent.objects.filter(
                banner=banner,
                event_type="click",
            ).count()

            ctr = 0

            if impressions > 0:
                ctr = round(
                    (clicks / impressions) * 100,
                    2,
                )

            results.append({

                "id": banner.id,

                "title": banner.title,

                "placement": banner.placement,

                "is_active": banner.is_active,

                "impressions": impressions,

                "clicks": clicks,

                "ctr": ctr,

            })

        serializer = BannerPerformanceSerializer(
            results,
            many=True,
        )

        return Response(serializer.data)
    

class BannerTimelineView(APIView):

    permission_classes = [
        IsAuthenticated,
        IsBlogAdmin,
    ]

    def get(self, request):

        start = (
            timezone.now()
            - timedelta(days=30)
        )

        impressions = (
            BannerEvent.objects
            .filter(
                event_type="impression",
                created_at__gte=start,
            )
            .annotate(
                date=TruncDate("created_at")
            )
            .values("date")
            .annotate(
                impressions=Count("id")
            )
        )

        clicks = (
            BannerEvent.objects
            .filter(
                event_type="click",
                created_at__gte=start,
            )
            .annotate(
                date=TruncDate("created_at")
            )
            .values("date")
            .annotate(
                clicks=Count("id")
            )
        )

        timeline = {}

        for row in impressions:

            timeline[row["date"]] = {
                "date": row["date"],
                "impressions": row["impressions"],
                "clicks": 0,
            }

        for row in clicks:

            if row["date"] not in timeline:

                timeline[row["date"]] = {
                    "date": row["date"],
                    "impressions": 0,
                    "clicks": row["clicks"],
                }

            else:

                timeline[row["date"]]["clicks"] = row["clicks"]

        data = sorted(
            timeline.values(),
            key=lambda x: x["date"],
        )

        serializer = BannerTimelineSerializer(
            data,
            many=True,
        )

        return Response(serializer.data)