"""
SMS configuration (eskiz.uz)
"""

import typing

from django.utils.translation import gettext_lazy as _
from rest_framework import permissions
from rest_framework import request as rest_request
from rest_framework import throttling, views

from core import enums, exceptions, services, utils
from core.http import serializers
from core.http import views as http_views
from core.http.models import User


class RegisterView(
    views.APIView, services.UserService, http_views.ApiResponse
):
    """
    Register new user
    """

    serializer_class = serializers.RegisterSerializer
    throttle_classes = [throttling.UserRateThrottle]

    def post(self, request: rest_request.Request):
        ser = self.serializer_class(data=request.data)
        ser.is_valid(raise_exception=True)
        data = ser.data
        phone = data.get("phone")

        # Create pending user
        self.create_user(
            phone,
            data.get("first_name"),
            data.get("last_name"),
            data.get("password"),
        )

        # Send confirmation code for sms eskiz.uz
        self.send_confirmation(phone)
        return self.success(_(enums.Messages.SEND_MESSAGE) % {"phone": phone})


class ConfirmView(views.APIView, services.UserService, http_views.ApiResponse):
    """Confirm otp code"""

    serializer_class = serializers.ConfirmSerializer

    def post(self, request: rest_request.Request):
        ser = self.serializer_class(data=request.data)
        ser.is_valid(raise_exception=True)

        data = ser.data
        phone, code = data.get("phone"), data.get("code")

        try:
            # Check Sms confirmation otp code
            if services.SmsService.check_confirm(phone, code=code):
                # Create user
                token = self.validate_user(
                    User.objects.filter(phone=phone).first()
                )
                return self.success(
                    _(enums.Messages.OTP_CONFIRMED), token=token
                )
        except exceptions.SmsException as e:
            return utils.ResponseException(e)
        except Exception as e:
            return self.error(e)


class ResetConfirmationCodeView(
    views.APIView, http_views.ApiResponse, services.UserService
):  # noqa
    """
    Reset confirm otp code
    """

    serializer_class = serializers.ResetConfirmationSerializer

    def post(self, request: rest_request.Request):
        ser = self.serializer_class(data=request.data)
        ser.is_valid(raise_exception=True)

        data = ser.data
        code, phone, password = (
            data.get("code"),
            data.get("phone"),
            data.get("password"),
        )  # noqa

        try:
            res = services.SmsService.check_confirm(phone, code)
            if res:
                self.change_password(phone, password)
                return self.success(_(enums.Messages.CHANGED_PASSWORD))
            return self.error(_(enums.Messages.INVALID_OTP))
        except exceptions.SmsException as e:
            return self.error(e, error_code=enums.Codes.INVALID_OTP_ERROR)
        except Exception as e:
            return self.error(e)


class ResendView(http_views.AbstractSendSms):
    """
    Resend Otp Code
    """

    serializer_class = serializers.ResendSerializer


class ResetPasswordView(http_views.AbstractSendSms):
    """
    Reset user password
    """

    serializer_class: typing.Type[serializers.ResetPasswordSerializer] = (
        serializers.ResetPasswordSerializer
    )  # noqa


# class MeView(views.APIView, http_views.ApiResponse):
#     """
#     Get user information
#     """
#     permission_classes = [permissions.IsAuthenticated]
#
#     def get(self, request: rest_request.Request):
#         user = request.user
#         serializer = serializers.UserSerializer(user, context={'request': request})
#         return self.success(data=serializer.data)


class MeView(views.APIView, http_views.ApiResponse):
    """
    Get user information
    """

    permission_classes = [permissions.IsAuthenticated]

    def get(self, request: rest_request.Request):
        user = request.user
        return self.success(data=serializers.UserSerializer(user).data)
