# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later

from api.viewsets import ReadProtectedModelViewSet
from django_filters.rest_framework import DjangoFilterBackend
from api.filters import RegexSafeSearchFilter
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status

from .serializers import FamilySerializer, FamilyMembershipSerializer, ChallengeSerializer, AchievementSerializer
from ..models import Family, FamilyMembership, Challenge, Achievement


class FamilyViewSet(ReadProtectedModelViewSet):
    """
    REST API View set.
    The djangorestframework plugin will get all `Family` objects, serialize it to JSON with the given serializer,
    then render it on /api/family/family/
    """
    queryset = Family.objects.order_by('id')
    serializer_class = FamilySerializer
    filter_backends = [DjangoFilterBackend, RegexSafeSearchFilter]
    filterset_fields = ['name', 'description', 'score', 'rank', ]
    search_fields = ['$name', '$description', ]


class FamilyMembershipViewSet(ReadProtectedModelViewSet):
    """
    REST API View set.
    The djangorestframework plugin will get all `FamilyMembership` objects, serialize it to JSON with the given serializer,
    then render it on /api/family/familymembership/
    """
    queryset = FamilyMembership.objects.order_by('id')
    serializer_class = FamilyMembershipSerializer
    filter_backends = [DjangoFilterBackend, RegexSafeSearchFilter]
    filterset_fields = ['user__username', 'user__first_name', 'user__last_name', 'user__email', 'user__note__alias__name',
                        'user__note__alias__normalized_name', 'family__name', 'family__description', 'year', ]
    search_fields = ['$user__username', '$user__first_name', '$user__last_name', '$user__email', '$user__note__alias__name',
                     '$user__note__alias__normalized_name', '$family__name', '$family__description', '$year', ]


class ChallengeViewSet(ReadProtectedModelViewSet):
    """
    REST API View set.
    The djangorestframework plugin will get all `Challenge` objects, serialize it to JSON with the given serializer,
    then render it on /api/family/challenge/
    """
    queryset = Challenge.objects.order_by('id')
    serializer_class = ChallengeSerializer
    filter_backends = [DjangoFilterBackend, RegexSafeSearchFilter]
    filterset_fields = ['name', 'description', 'points', ]
    search_fields = ['$name', '$description', '$points', ]


class AchievementViewSet(ReadProtectedModelViewSet):
    """
    REST API View set.
    The djangorestframework plugin will get all `Achievement` objects, serialize it to JSON with the given serializer,
    then render it on /api/family/achievement/
    """
    queryset = Achievement.objects.order_by('id')
    serializer_class = AchievementSerializer
    filter_backends = [DjangoFilterBackend, RegexSafeSearchFilter]
    filterset_fields = ['family__name', 'family__description', 'challenge__name', 'challenge__description', 'obtained_at', 'valid', ]
    search_fields = ['$family__name', '$family__description', '$challenge__name', '$challenge__description', ]


class BatchAchievementsAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, format=None):
        family_ids = request.data.get('families')
        challenge_ids = request.data.get('challenges')
        families = Family.objects.filter(id__in=family_ids)
        challenges = Challenge.objects.filter(id__in=challenge_ids)
        results = []
        for family in families:
            for challenge in challenges:
                a, created = Achievement.objects.get_or_create(family=family, challenge=challenge)
                if created:
                    results.append({
                        'family': family.name,
                        'challenge': challenge.name,
                        'status': 'created'
                    })
                else:
                    results.append({
                        'family': family.name,
                        'challenge': challenge.name,
                        'status': 'existed',
                    })
        for family in families:
            family.update_score()
        Family.update_ranking()

        return Response({'results': results}, status=status.HTTP_201_CREATED)
