from django.contrib.auth import get_user_model
from django.utils.decorators import method_decorator
from django_ratelimit.decorators import ratelimit
from rest_framework import generics, permissions, status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

from portfolio.models import StudentProfile, TeacherManagedGroup

from .serializers import (
    CustomTokenObtainPairSerializer,
    PasswordResetConfirmSerializer,
    PasswordResetRequestSerializer,
    RegisterSerializer,
)


@method_decorator(ratelimit(key="ip", rate="10/m", method="POST"), name="dispatch")
class RegisterView(generics.CreateAPIView):
    queryset = get_user_model().objects.all()
    permission_classes = (permissions.AllowAny,)
    serializer_class = RegisterSerializer

    def perform_create(self, serializer):
        user = serializer.save()
        extra = getattr(serializer, "_pending_profile", {}) or {}
        User = get_user_model()
        if user.role == User.Role.TEACHER:
            for g in getattr(serializer, "_managed_groups", []) or []:
                TeacherManagedGroup.objects.get_or_create(teacher=user, group_name=g)
            return
        StudentProfile.objects.create(
            user=user,
            first_name=user.first_name,
            last_name=user.last_name,
            patronymic=extra.get("patronymic", ""),
            student_group=extra.get("student_group", ""),
        )

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        return Response(
            {
                "detail": "Регистрация успешна. Дождитесь подтверждения администратором."
            },
            status=status.HTTP_201_CREATED,
        )


@method_decorator(ratelimit(key="ip", rate="30/m", method="POST"), name="dispatch")
class LoginView(TokenObtainPairView):
    permission_classes = (permissions.AllowAny,)
    serializer_class = CustomTokenObtainPairSerializer


class RefreshView(TokenRefreshView):
    permission_classes = (permissions.AllowAny,)


class LogoutView(APIView):
    permission_classes = (permissions.IsAuthenticated,)

    def post(self, request):
        refresh = request.data.get("refresh")
        if not refresh:
            return Response(
                {"detail": "Передайте refresh-токен."},
                status=status.HTTP_400_BAD_REQUEST,
            )
        try:
            token = RefreshToken(refresh)
            token.blacklist()
        except Exception:
            return Response(
                {"detail": "Некорректный токен."}, status=status.HTTP_400_BAD_REQUEST
            )
        return Response({"detail": "Выход выполнен."})


@method_decorator(ratelimit(key="ip", rate="10/m", method="POST"), name="dispatch")
class PasswordResetRequestView(generics.GenericAPIView):
    permission_classes = (permissions.AllowAny,)
    serializer_class = PasswordResetRequestSerializer

    def post(self, request, *args, **kwargs):
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        return Response(
            {
                "detail": "Если email зарегистрирован, на него отправлена инструкция."
            }
        )


class PasswordResetConfirmView(generics.GenericAPIView):
    permission_classes = (permissions.AllowAny,)
    serializer_class = PasswordResetConfirmSerializer

    def post(self, request, *args, **kwargs):
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save()
        return Response({"detail": "Пароль обновлён."})
