from django.db.models import Count, Q, Sum
from django.shortcuts import render
from django.utils import timezone
from django.views import View

from apps.accounts import permissions as perms
from apps.contact.models import Message, Subscriber
from apps.core.mixins import BackofficeMixin
from apps.editorial.models import Annonce, Article, Status
from apps.engagement.models import Comment
from apps.taxonomy.models import Category


class DashboardView(BackofficeMixin, View):
    def get(self, request):
        user = request.user
        now = timezone.now()
        mine = Article.objects.alive().filter(auteur=user)
        ctx = {
            "my_drafts": mine.filter(statut__in=[Status.BROUILLON, Status.RELECTURE]).order_by("-updated_at")[:6],
            "my_stats": mine.aggregate(
                total=Count("pk"),
                published=Count("pk", filter=Q(statut=Status.PUBLIE, publie_le__lte=now)),
                review=Count("pk", filter=Q(statut=Status.RELECTURE)),
                views=Sum("vues"),
            ),
        }
        if perms.is_editeur(user):
            published = Article.objects.published()
            week_ago = now - timezone.timedelta(days=7)
            ctx.update(
                stats={
                    "published": published.count(),
                    "published_week": published.filter(publie_le__gte=week_ago).count(),
                    "views": published.aggregate(v=Sum("vues"))["v"] or 0,
                    "annonces": Annonce.objects.published().count(),
                    "pending_comments": Comment.objects.pending().count(),
                    "unread": Message.objects.filter(lu=False).count(),
                    "subscribers": Subscriber.objects.filter(is_active=True).count(),
                },
                review_queue=list(Article.objects.alive().filter(statut=Status.RELECTURE).select_related("auteur", "categorie").order_by("soumis_le")[:6])
                + list(Annonce.objects.alive().filter(statut=Status.RELECTURE).select_related("auteur").order_by("soumis_le")[:4]),
                scheduled=Article.objects.scheduled().select_related("categorie").order_by("publie_le")[:5],
                top_articles=published.select_related("categorie").order_by("-vues")[:5],
                pending_comments=Comment.objects.pending().select_related("article", "user")[:5],
                latest_messages=Message.objects.all()[:5],
                categories=self.category_bars(),
            )
        return render(request, "backoffice/dashboard.html", ctx)

    @staticmethod
    def category_bars():
        rows = list(
            Category.objects.annotate(n=Count("articles", filter=Q(articles__statut=Status.PUBLIE, articles__deleted_at__isnull=True)))
            .filter(n__gt=0).order_by("-n")[:8]
        )
        top = max((r.n for r in rows), default=1)
        return [(r, round(r.n * 100 / top)) for r in rows]
