from rest_framework import mixins, status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from accounts.permissions import HasPermission

from .models import Notification, NotificationSetting
from .serializers import (
    NotificationSerializer,
    NotificationSettingSerializer,
    NotificationSettingUpdateSerializer,
)


class NotificationViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """A user's own notifications — read-only besides marking read."""

    serializer_class = NotificationSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        return Notification.objects.filter(recipient=self.request.user)

    @action(detail=False, methods=['get'], url_path='unread-count')
    def unread_count(self, request):
        count = self.get_queryset().filter(is_read=False).count()
        return Response({'unread_count': count})

    @action(detail=True, methods=['post'])
    def read(self, request, pk=None):
        notification = self.get_object()
        if not notification.is_read:
            notification.is_read = True
            notification.save(update_fields=['is_read'])
        return Response(NotificationSerializer(notification).data)

    @action(detail=False, methods=['post'], url_path='read-all')
    def read_all(self, request):
        self.get_queryset().filter(is_read=False).update(is_read=True)
        return Response(status=status.HTTP_204_NO_CONTENT)


class NotificationSettingViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """The manager-editable role/notification-type matrix."""

    queryset = NotificationSetting.objects.all()
    serializer_class = NotificationSettingSerializer
    permission_classes = [HasPermission('settings.manage_notifications')]

    @action(detail=False, methods=['post'])
    def set(self, request):
        serializer = NotificationSettingUpdateSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data
        setting, _ = NotificationSetting.objects.update_or_create(
            role=data['role'], notification_type=data['notification_type'],
            defaults={'enabled': data['enabled']},
        )
        return Response(NotificationSettingSerializer(setting).data)
