"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: ksp-servicestelle@sgdnord.rlp.de
Created on: 10.05.24

"""
import base64
import hashlib
import json

from cryptography.fernet import Fernet
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpRequest, JsonResponse
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt

from konova.sub_settings.sso_settings import OAUTH_CLIENT_ID
from user.models import User


class PropagateUserView(View):
    """ Receives user data to be stored in db

    Used if new user gets access to application and needs to be created in application before first login (e.g.
    proper rights management)

    """

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)

    def post(self, request: HttpRequest, *args, **kwargs):
        # Decrypt
        encrypted_body = request.body
        hash = hashlib.md5()
        hash.update(OAUTH_CLIENT_ID.encode("utf-8"))
        key = base64.urlsafe_b64encode(hash.hexdigest().encode("utf-8"))
        fernet = Fernet(key)
        body = fernet.decrypt(encrypted_body).decode("utf-8")
        body = json.loads(body)

        try:
            status = "updated"
            user = User.objects.get(username=body.get('username'))
            # Update user data, excluding some changes
            skipable_attrs = {
                "username",
                "is_staff",
                "is_superuser",
            }
            for _attr, _val in body.items():
                if _attr in skipable_attrs:
                    continue
                setattr(user, _attr, _val)
        except ObjectDoesNotExist:
            user = User(**body)
            status = "created"
        user.set_unusable_password()
        user.save()

        data = {
            "success": True,
            "status": status
        }

        return JsonResponse(data)
