"""Custom model mixins"""

# Utils
from logging import getLogger

# Django
from django.contrib.auth import update_session_auth_hash
from django.core.cache import cache
from django.utils.translation import gettext_lazy as _
from drf_spectacular.utils import extend_schema

# DRF
from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.response import Response

# Model
from {{project_slug}}.users.models import User

# Utils
from {{project_slug}}.utils.serializers import confirmation_inline_serializer

logger = getLogger("console")


class CacheListModelMixin(mixins.ListModelMixin):
    def list(self, request, *args, **kwargs):
        data = cache.get(request.path)
        if not data or request.query_params:
            response = super().list(request, *args, **kwargs)
            data = response.data
            cache.set(request.path, data, self.get_cache_timeout())

        return Response(data)


class CacheListPrivateModelMixin(mixins.ListModelMixin):
    def list(self, request, *args, **kwargs):
        data = cache.get(request.path + str(request.user.pk))
        if not data or request.query_params:
            response = super().list(request, *args, **kwargs)
            data = response.data
            cache.set(
                request.path + str(request.user.pk), data, self.get_cache_timeout()
            )

        return Response(data)


class CacheRetrieveModelMixin(mixins.RetrieveModelMixin):
    def retrieve(self, request, *args, **kwargs):
        data = cache.get(request.path)
        if not data:
            response = super().retrieve(request, *args, **kwargs)
            data = response.data
            cache.set(request.path, data, self.get_cache_timeout())

        return Response(data)


class CustomDeleteMixin(mixins.DestroyModelMixin):

    def perform_destroy(self, instance):
        instance.is_deleted = True
        instance.is_active = False
        instance.save()


class PasswordResetModelMixin:
    @extend_schema(
        responses={200: confirmation_inline_serializer},
    )
    @action(detail=True, methods=["post"], url_path="update-password")
    def update_password(self, request, *args, **kwargs):
        """User reset password"""
        serializer = self.get_serializer_class()(data=request.data)
        if serializer.is_valid(raise_exception=True):
            user: User = self.get_object()
            current_password = serializer.validated_data["current_password"]
            new_password = serializer.validated_data["new_password"]

            if not user.check_password(current_password):
                return Response(
                    {"message": _("Current password is incorrect.")}, status=400
                )

            user.set_password(new_password)
            user.save()
            logger.info("User {} changed password".format(user.username))
            # Important: Update the session authentication hash
            update_session_auth_hash(request, user)

            return Response(
                {"message": _("Password updated successfully.")}, status=200
            )

    @extend_schema(
        responses={200: confirmation_inline_serializer},
    )
    @action(detail=False, methods=["post"], url_path="recover-password")
    def recover_password(self, request, *args, **kwargs):
        serializer = self.get_serializer_class()(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response({"message": _("Recovery email sent successfully.")}, status=200)

    @extend_schema(
        responses={200: confirmation_inline_serializer},
    )
    @action(detail=False, methods=["post"], url_path="reset-password")
    def reset_password(self, request):
        serializer = self.get_serializer_class()(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
