from django.http.response import JsonResponse
from django.utils.timezone import now
from rest_framework import status
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

from greg.models import Identity, Person, InvitationLink
from greg.permissions import IsSponsor
from gregui.api.serializers.guest import create_identity_or_update
from gregui.validation import validate_email


class PersonView(APIView):
    """
    Fetch person info for any guest as long as you are a sponsor

    This is required for the functionality where a sponsor wants to add a guest role to
    an already existing person that is not already their guest.

    Returns enough information to fill a profile page in the frontend
    """

    authentication_classes = [SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated, IsSponsor]

    def get(self, request, id):
        person = Person.objects.get(id=id)
        response = {
            "pid": person.id,
            "first": person.first_name,
            "last": person.last_name,
            "email": person.private_email and person.private_email.value,
            "mobile": person.private_mobile and person.private_mobile.value,
            "fnr": person.fnr and "".join((person.fnr.value[:-5], "*****")),
            "active": person.is_registered and person.is_verified,
            "registered": person.is_registered,
            "verified": person.is_verified,
            "roles": [
                {
                    "id": role.id,
                    "name_nb": role.type.name_nb,
                    "name_en": role.type.name_en,
                    "ou_nb": role.orgunit.name_nb,
                    "ou_en": role.orgunit.name_en,
                    "start_date": role.start_date,
                    "end_date": role.end_date,
                    "max_days": role.type.max_days,
                }
                for role in person.roles.all()
            ],
        }
        return JsonResponse(response)

    def patch(self, request, id):
        person = Person.objects.get(id=id)
        # For now only the e-mail is allowed to be updated
        email = request.data.get("email")
        if not email:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        validate_email(email)
        # The following line will raise an exception if the e-mail is not valid
        create_identity_or_update(Identity.IdentityType.PRIVATE_EMAIL, email, person)

        return Response(status=status.HTTP_200_OK)


class PersonSearchView(APIView):
    """Search for persons using email or phone number"""

    authentication_classes = [SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated, IsSponsor]

    def get(self, requests, searchstring):
        search = Identity.objects.filter(
            value__icontains=searchstring,  # icontains to include wrong case emails
            type__in=[
                Identity.IdentityType.PRIVATE_EMAIL,
                Identity.IdentityType.PRIVATE_MOBILE_NUMBER,
            ],
        )[:10]
        response = {
            "persons": [
                {
                    "pid": i.person.id,
                    "first": i.person.first_name,
                    "last": i.person.last_name,
                    "value": i.value,
                    "type": i.type,
                }
                for i in search
            ]
        }
        return JsonResponse(response)