from collections import Counter

from django.db.models import Q, Count
from django.utils import timezone
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from drf_spectacular.utils import extend_schema, OpenApiParameter

from .models import Contact, Reminder
from .serializers import ContactSerializer, ReminderSerializer


def visible_contacts_qs(user):
    """Public contacts + private contacts owned by user. Anonymous → public only."""
    qs = Contact.objects.all()
    if user is None or not user.is_authenticated:
        return qs.filter(visibility="public")
    return qs.filter(Q(visibility="public") | Q(visibility="private", created_by=user))


class ContactViewSet(viewsets.ModelViewSet):
    """ViewSet for Contact management. Honors per-contact visibility."""
    rbac_domain = "phonebook"
    serializer_class = ContactSerializer

    def get_queryset(self):
        return visible_contacts_qs(self.request.user).select_related("company", "created_by")

    def perform_create(self, serializer):
        user = self.request.user if self.request.user.is_authenticated else None
        serializer.save(created_by=user)

    @extend_schema(
        parameters=[
            OpenApiParameter(name="type", type=str, description="Filter by type (individual/organization)"),
            OpenApiParameter(name="company", type=str, description="Filter by company ID"),
        ]
    )
    def list(self, request, *args, **kwargs):
        qs = self.get_queryset()
        type_ = request.query_params.get("type")
        company = request.query_params.get("company")
        if type_:
            qs = qs.filter(type=type_)
        if company:
            qs = qs.filter(company_id=company)
        page = self.paginate_queryset(qs)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)
        serializer = self.get_serializer(qs, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=["get"], url_path="stats")
    def stats(self, request):
        qs = visible_contacts_qs(request.user)
        total = qs.count()
        favorites = qs.filter(is_favorite=True).count()

        tag_counter = Counter()
        for tag_list in qs.values_list("tags", flat=True):
            for t in (tag_list or []):
                tag_counter[t] += 1
        top_tags = [{"name": name, "count": count} for name, count in tag_counter.most_common(10)]

        recent = list(
            qs.order_by("-created_at")[:5].values(
                "id", "name", "position", "phone", "company__name", "visibility"
            )
        )
        recent = [
            {
                "id": str(r["id"]),
                "name": r["name"],
                "position": r["position"],
                "phone": r["phone"],
                "company_name": r["company__name"],
                "visibility": r["visibility"],
            }
            for r in recent
        ]

        by_company = list(
            qs.exclude(company__isnull=True)
              .values("company__name")
              .annotate(count=Count("id"))
              .order_by("-count")[:10]
        )
        by_company = [{"name": c["company__name"], "count": c["count"]} for c in by_company]

        return Response({
            "total": total,
            "favorites": favorites,
            "top_tags": top_tags,
            "recent": recent,
            "by_company": by_company,
        })

    @action(detail=True, methods=["post"], url_path="toggle_favorite")
    def toggle_favorite(self, request, pk=None):
        contact = self.get_object()
        contact.is_favorite = not contact.is_favorite
        contact.save(update_fields=["is_favorite", "updated_at"])
        return Response(self.get_serializer(contact).data)

    @action(detail=False, methods=["get"], url_path="reminders")
    def reminders(self, request):
        pending = request.query_params.get("pending")
        visible_ids = visible_contacts_qs(request.user).values_list("id", flat=True)
        qs = Reminder.objects.filter(contact_id__in=visible_ids).select_related("contact")
        if pending:
            qs = qs.filter(status="pending", remind_at__gte=timezone.now())
        serializer = ReminderSerializer(qs.order_by("remind_at"), many=True)
        return Response(serializer.data)


class ReminderViewSet(viewsets.ModelViewSet):
    """Reminder CRUD. Limited to reminders on contacts the user can see."""
    rbac_domain = "phonebook"
    serializer_class = ReminderSerializer

    def get_queryset(self):
        visible_ids = visible_contacts_qs(self.request.user).values_list("id", flat=True)
        return Reminder.objects.filter(contact_id__in=visible_ids).select_related("contact__company", "contact__created_by")

    def perform_create(self, serializer):
        from rest_framework.exceptions import PermissionDenied
        user = self.request.user
        contact = serializer.validated_data.get("contact")
        if contact and not visible_contacts_qs(user).filter(pk=contact.pk).exists():
            raise PermissionDenied("Contact not accessible")
        serializer.save(created_by=user)
