from django.contrib import messages
from django.db.models import Count, F, Q
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.views.decorators.http import require_POST
from django.views.generic import DetailView, ListView

from core.models import SiteSetting
from core.seo import article_schema, breadcrumb_schema
from profiles.models import Profile

from .forms import CommentForm
from .models import Category, Post, Tag


class PostListView(ListView):
    model = Post
    template_name = "blog/post_list.html"
    context_object_name = "posts"
    paginate_by = 9

    def get_queryset(self):
        qs = Post.published.select_related("category").prefetch_related("tags")
        category = self.request.GET.get("category")
        tag = self.request.GET.get("tag")
        query = self.request.GET.get("q", "").strip()
        post_type = self.request.GET.get("type")

        if category:
            qs = qs.filter(category__slug=category)
        if tag:
            qs = qs.filter(tags__slug=tag)
        if post_type in {"article", "update"}:
            qs = qs.filter(post_type=post_type)
        if query:
            qs = qs.filter(
                Q(title__icontains=query) | Q(excerpt__icontains=query) | Q(content__icontains=query)
            )
        return qs.distinct()

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["categories"] = Category.objects.annotate(n=Count("posts")).filter(n__gt=0)
        ctx["tags"] = Tag.objects.annotate(n=Count("posts")).filter(n__gt=0).order_by("-n")[:20]
        ctx["popular"] = Post.published.order_by("-views_count")[:5]
        ctx["active_category"] = self.request.GET.get("category", "")
        ctx["active_tag"] = self.request.GET.get("tag", "")
        ctx["active_type"] = self.request.GET.get("type", "")
        ctx["query"] = self.request.GET.get("q", "")
        return ctx


class PostDetailView(DetailView):
    model = Post
    template_name = "blog/post_detail.html"
    context_object_name = "post"

    def get_queryset(self):
        qs = Post.objects.select_related("category").prefetch_related("tags", "comments")
        if self.request.user.is_authenticated:
            return qs  # pemilik bisa melihat draft sebagai preview
        return qs.filter(status="published")

    def get_object(self, queryset=None):
        post = super().get_object(queryset)
        # Hitung view sekali per sesi per post.
        seen = self.request.session.setdefault("seen_posts", [])
        if post.pk not in seen:
            Post.objects.filter(pk=post.pk).update(views_count=F("views_count") + 1)
            post.views_count += 1
            seen.append(post.pk)
            self.request.session.modified = True
        return post

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["comment_form"] = CommentForm()
        ctx["comments"] = self.object.comments.filter(is_approved=True, parent__isnull=True)
        related = Post.published.exclude(pk=self.object.pk)
        if self.object.category_id:
            related = related.filter(category_id=self.object.category_id)
        ctx["related"] = related[:3]

        profile = Profile.get_solo()
        ctx["schema_article"] = article_schema(
            self.request, self.object, profile, SiteSetting.get_solo()
        )
        ctx["schema_breadcrumb"] = breadcrumb_schema(
            self.request,
            [
                ("Beranda", reverse("core:home")),
                ("Blog", reverse("blog:list")),
                (self.object.title, self.object.get_absolute_url()),
            ],
        )
        return ctx


@require_POST
def add_comment(request, slug):
    post = get_object_or_404(Post, slug=slug, status="published")
    if not post.allow_comments:
        messages.error(request, "Komentar ditutup untuk postingan ini.")
        return redirect(post.get_absolute_url())

    form = CommentForm(request.POST)
    if form.is_valid():
        comment = form.save(commit=False)
        comment.post = post
        parent_id = request.POST.get("parent")
        if parent_id:
            comment.parent = post.comments.filter(pk=parent_id).first()
        comment.save()
        messages.success(request, "Komentar terkirim, menunggu moderasi.")
    else:
        messages.error(request, "Komentar gagal dikirim. Cek isian kamu.")
    return redirect(post.get_absolute_url() + "#comments")


@require_POST
def toggle_like(request, slug):
    post = get_object_or_404(Post, slug=slug, status="published")
    liked = request.session.setdefault("liked_posts", [])
    if post.pk in liked:
        liked.remove(post.pk)
        Post.objects.filter(pk=post.pk).update(likes_count=F("likes_count") - 1)
        post.refresh_from_db(fields=["likes_count"])
        state = False
    else:
        liked.append(post.pk)
        Post.objects.filter(pk=post.pk).update(likes_count=F("likes_count") + 1)
        post.refresh_from_db(fields=["likes_count"])
        state = True
    request.session.modified = True
    return JsonResponse({"liked": state, "count": post.likes_count})
