from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from drf_spectacular.utils import extend_schema

from .models import Notification, NotificationTemplate, NotificationPreference, FCMDevice
from .serializers import (
    NotificationSerializer,
    NotificationCreateSerializer,
    NotificationTemplateSerializer,
    NotificationPreferenceSerializer,
    FCMDeviceSerializer
)
from .handler import NotificationHandler


class NotificationViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing user notifications.

    Supports:
    - Listing notifications (only the authenticated user's)
    - Marking single/multiple as read
    - Deleting notifications
    - Real-time WebSocket delivery
    """
    permission_classes = [IsAuthenticated]

    def get_serializer_class(self):
        if self.action == 'create':
            return NotificationCreateSerializer
        return NotificationSerializer

    def get_queryset(self):
        return Notification.objects.filter(
            user=self.request.user,
            is_deleted=False
        )

    @extend_schema(
        description="Mark a specific notification as read"
    )
    @action(detail=True, methods=['post'])
    def mark_read(self, request, pk=None):
        notification = self.get_object()
        notification.mark_as_read()
        return Response({'status': 'marked as read'})

    @extend_schema(
        description="Mark all notifications as read"
    )
    @action(detail=False, methods=['post'])
    def mark_all_read(self, request):
        count = NotificationHandler.mark_all_as_read(request.user)
        return Response({'status': 'marked all as read', 'count': count})

    @extend_schema(
        description="Get unread count"
    )
    @action(detail=False, methods=['get'])
    def unread_count(self, request):
        count = NotificationHandler.get_unread_count(request.user)
        return Response({'unread_count': count})

    @extend_schema(
        description="Get recent unread notifications"
    )
    @action(detail=False, methods=['get'])
    def unread(self, request):
        limit = int(request.query_params.get('limit', 10))
        notifications = NotificationHandler.get_unread(request.user, limit=limit)
        serializer = NotificationSerializer(notifications, many=True)
        return Response(serializer.data)

    @extend_schema(
        description="Delete (soft) a specific notification"
    )
    @action(detail=True, methods=['post'])
    def delete(self, request, pk=None):
        notification = self.get_object()
        notification.mark_as_deleted()
        return Response({'status': 'deleted'})

    @extend_schema(
        description="Delete all read notifications"
    )
    @action(detail=False, methods=['post'])
    def delete_read(self, request):
        deleted, _ = Notification.objects.filter(
            user=request.user,
            is_read=True,
            is_deleted=False
        ).update(is_deleted=True)
        return Response({'status': 'deleted', 'count': deleted})


class NotificationTemplateViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing notification templates.
    Admin only endpoint.
    """
    queryset = NotificationTemplate.objects.all()
    serializer_class = NotificationTemplateSerializer

    def get_permissions(self):
        from rest_framework.permissions import IsAdminUser
        if self.action in ['create', 'update', 'partial_update', 'destroy']:
            return [IsAdminUser()]
        return [IsAuthenticated()]


class FCMDeviceViewSet(viewsets.ModelViewSet):
    """Register/list/remove the current user's FCM push tokens.

    Browsers POST the token they get from the Firebase JS SDK. Re-registering an
    existing token (e.g. after a token refresh on another account) re-points it
    at the current user and reactivates it.
    """
    permission_classes = [IsAuthenticated]
    serializer_class = FCMDeviceSerializer

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

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        token = serializer.validated_data['token']
        platform = serializer.validated_data.get('platform', 'web')

        device, _ = FCMDevice.objects.update_or_create(
            token=token,
            defaults={
                'user': request.user,
                'platform': platform,
                'is_active': True,
            },
        )
        out = self.get_serializer(device)
        return Response(out.data, status=status.HTTP_201_CREATED)

    @extend_schema(description="Unregister a device token (used on logout)")
    @action(detail=False, methods=['post'])
    def unregister(self, request):
        token = request.data.get('token')
        if not token:
            return Response(
                {'error': 'token is required'},
                status=status.HTTP_400_BAD_REQUEST
            )
        deleted, _ = FCMDevice.objects.filter(
            user=request.user, token=token
        ).delete()
        return Response({'status': 'unregistered', 'deleted': deleted})


class NotificationPreferenceViewSet(viewsets.ModelViewSet):
    """
    ViewSet for managing user notification preferences.
    Each user can only manage their own preferences.
    """
    permission_classes = [IsAuthenticated]
    serializer_class = NotificationPreferenceSerializer

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

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

    @extend_schema(
        description="Get or create notification preferences for current user"
    )
    @action(detail=False, methods=['get', 'post'])
    def me(self, request):
        try:
            prefs = NotificationPreference.objects.get(user=request.user)
        except NotificationPreference.DoesNotExist:
            prefs = NotificationPreference.objects.create(user=request.user)

        serializer = NotificationPreferenceSerializer(prefs)
        return Response(serializer.data)

    @extend_schema(
        description="Update notification type preference"
    )
    @action(detail=False, methods=['post'])
    def update_type(self, request):
        notification_type = request.data.get('type')
        enabled = request.data.get('enabled', True)

        if not notification_type:
            return Response(
                {'error': 'type is required'},
                status=status.HTTP_400_BAD_REQUEST
            )

        try:
            prefs = NotificationPreference.objects.get(user=request.user)
        except NotificationPreference.DoesNotExist:
            prefs = NotificationPreference.objects.create(user=request.user)

        prefs.set_type_enabled(notification_type, enabled)
        serializer = NotificationPreferenceSerializer(prefs)
        return Response(serializer.data)
