from rest_framework.exceptions import PermissionDenied
from rest_framework.mixins import (
    DestroyModelMixin,
    ListModelMixin,
    UpdateModelMixin,
)
from rest_framework.request import Request
from rest_framework.response import Response

from saas.drf.decorators import resource_permission
from saas.drf.filters import IncludeFilter, TenantIdFilter
from saas.drf.views import TenantEndpoint

from ..models import Member
from ..serializers.member import (
    MemberSerializer,
    MemberUpdateSerializer,
)

__all__ = [
    'MemberListEndpoint',
    'MemberItemEndpoint',
]


class MemberListEndpoint(ListModelMixin, TenantEndpoint):
    serializer_class = MemberSerializer
    filter_backends = [TenantIdFilter, IncludeFilter]
    queryset = Member.objects.all().select_related('user').prefetch_related('groups')

    @resource_permission('iam.member.view')
    def get(self, request: Request, *args, **kwargs):
        """List all members in the tenant."""
        return self.list(request, *args, **kwargs)


class MemberItemEndpoint(UpdateModelMixin, DestroyModelMixin, TenantEndpoint):
    serializer_class = MemberSerializer
    queryset = Member.objects.all()

    def get_serializer_class(self):
        if self.request.method == 'PATCH':
            return MemberUpdateSerializer
        return MemberSerializer

    @resource_permission('iam.member.view')
    def get(self, request: Request, *args, **kwargs):
        instance = self.get_object()
        serializer: MemberSerializer = self.get_serializer(instance)
        return Response(serializer.data)

    @resource_permission('iam.member.update')
    def patch(self, request: Request, *args, **kwargs):
        """Update a member's permissions and groups."""
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        # always return with MemberSerializer
        serializer = MemberSerializer(instance, context=self.get_serializer_context())
        return Response(serializer.data)

    @resource_permission('iam.member.delete')
    def delete(self, request: Request, *args, **kwargs):
        """Remove a member from the tenant."""
        return self.destroy(request, *args, **kwargs)

    def perform_destroy(self, instance: Member):
        if instance.user_id == self.request.tenant.owner_id:
            raise PermissionDenied('Cannot remove the owner from the tenant.')
        instance.delete()
