from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework.exceptions import PermissionDenied, APIException
from rest_framework.viewsets import ModelViewSet

from api_fhir_r4.models import Subscription
from api_fhir_r4.openapi_schema_extensions import get_inline_error_serializer
from api_fhir_r4.permissions import FHIRApiSubscriptionPermissions
from api_fhir_r4.subscriptions import SubscriptionSerializer
from api_fhir_r4.services import SubscriptionService
from api_fhir_r4.subscriptions.subscriptionSerializer import SubscriptionSerializerSchema
from api_fhir_r4.views.fhir.base import BaseFHIRView
from api_fhir_r4.views.filters import DateUpdatedRequestParameterFilter


@extend_schema_view(
    list=extend_schema(responses={(200, 'application/json'): SubscriptionSerializerSchema()}),
    retrieve=extend_schema(responses={
        (200, 'application/json'): SubscriptionSerializerSchema(),
        (404, 'application/json'): get_inline_error_serializer()
    }),
    create=extend_schema(
        request=SubscriptionSerializerSchema(),
        responses={(201, 'application/json'): SubscriptionSerializerSchema()}
    ),
    update=extend_schema(
        request=SubscriptionSerializerSchema(),
        responses={(200, 'application/json'): SubscriptionSerializerSchema()}
    ),
    destroy=extend_schema(responses={204: None})
)
class SubscriptionViewSet(BaseFHIRView, ModelViewSet):
    _error_while_deleting = 'Error while deleting a subscription: %(msg)s'
    serializer_class = SubscriptionSerializer
    http_method_names = ('get', 'post', 'put', 'delete')
    permission_classes = (FHIRApiSubscriptionPermissions,)

    def get_queryset(self):
        queryset = Subscription.objects.filter(is_deleted=False).order_by('date_created')
        return DateUpdatedRequestParameterFilter(self.request).filter_queryset(queryset)

    def perform_destroy(self, instance):
        if not self.check_if_owner(self.request.user, instance):
            raise PermissionDenied(
                detail=self._error_while_deleting % {'msg': 'You are not the owner of this subscription'})
        service = SubscriptionService(self.request.user)
        result = service.delete({'id': instance.uuid})
        self.check_error_message(result)

    @staticmethod
    def check_error_message(result):
        if not result.get('success', False):
            msg = result.get('message', 'Unknown')
            raise APIException(f'Error while deleting a subscription: {msg}')

    @staticmethod
    def check_if_owner(user, instance):
        return str(user.id).lower() == str(instance.user_created.id).lower()
