# django_core_micha/auth/views.py
from django.http import JsonResponse
from django.views.decorators.csrf import ensure_csrf_cookie
from django.shortcuts import get_object_or_404
from django.contrib.auth import get_user_model

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

from django_core_micha.invitations.mixins import InviteActionsMixin
from django_core_micha.auth.roles import RolePolicy

from allauth.mfa.models import Authenticator

User = get_user_model()


class BaseUserViewSet(InviteActionsMixin, viewsets.ModelViewSet):
    """
    Core User API:
    - list/retrieve/update/delete: authenticated users
    - current: get/patch self
    - update-role: role management via RolePolicy
    """

    queryset = User.objects.all()
    serializer_class = None  # must be set in project
    permission_classes = [IsAuthenticated]
    role_policy_class = RolePolicy

    def get_role_policy(self):
        return self.role_policy_class()

    @action(
        detail=False,
        methods=["get", "patch"],
        permission_classes=[IsAuthenticated],
        url_path="current",
    )
    def current(self, request):
        if request.method == "GET":
            serializer = self.get_serializer(request.user)
            return Response(serializer.data)

        serializer = self.get_serializer(
            request.user, data=request.data, partial=True
        )
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    @action(
        detail=True,
        methods=["patch"],
        permission_classes=[permissions.IsAuthenticated],
        url_path="update-role",
    )
    def update_role(self, request, pk=None):
        user = self.get_object()
        new_role = request.data.get("role")

        policy = self.get_role_policy()

        if not policy.is_valid_code(new_role):
            return Response(
                {"detail": "Invalid role."},
                status=400,
            )

        if not policy.can_change_role(request.user, user, new_role):
            return Response({"detail": "Permission denied."}, status=403)

        user.profile.role = new_role
        user.profile.save()
        return Response({"detail": "Role updated successfully."})



@ensure_csrf_cookie
def csrf_token_view(request):
    return JsonResponse({"detail": "CSRF cookie set"})


class PasskeyViewSet(viewsets.ViewSet):
    permission_classes = [IsAuthenticated]

    def list(self, request):
        qs = Authenticator.objects.filter(
            user=request.user,
            type=Authenticator.Type.WEBAUTHN,
        )

        data = []
        for a in qs:
            wrapped = a.wrap()  # liefert WebAuthn-spezifische Properties
            data.append(
                {
                    "id": a.pk,
                    # Name wird aus .data rausgezogen
                    "name": getattr(wrapped, "name", None),
                    "created_at": a.created_at,
                    "last_used_at": a.last_used_at,
                    # optional, je nach allauth-Version vorhanden
                    "is_device_passkey": getattr(
                        wrapped, "is_device_passkey", None
                    ),
                }
            )

        return Response(data)

    def destroy(self, request, pk=None):
        obj = get_object_or_404(
            Authenticator,
            pk=pk,
            user=request.user,
            type=Authenticator.Type.WEBAUTHN,
        )
        obj.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
