from datetime import timedelta

import requests
from django.utils import timezone
from rest_framework import request, status
from rest_framework.renderers import JSONRenderer

from authenticate import conf
from authenticate.models import VerificationAttempt, WrongVerificationAttempt, WrongPasswordAttempt
from utils.myresponse import MyResponse
from utils.utils import logs_adder
from wikiazma import settings


def check_verification_attempts_and_recaptcha_helper(ip, g_recaptcha_response, email, phone, username):
    try:
        attempt_check_range = timezone.now() - timedelta(hours=48)
        ip_attempts = VerificationAttempt.objects.filter(ip=ip, created_at__gt=attempt_check_range).count()

        if ip_attempts >= conf.maximum_verification_attempts_per_ip:
            google_recaptcha_helper(g_recaptcha_response)

        if email:
            attempts = VerificationAttempt.objects.filter(email=email, created_at__gt=attempt_check_range).count()
            if attempts >= conf.maximum_verification_attempts_codes_count:
                google_recaptcha_helper(g_recaptcha_response)
        elif phone:
            attempts = VerificationAttempt.objects.filter(phone=phone, created_at__gt=attempt_check_range).count()
            if attempts >= conf.maximum_verification_attempts_codes_count:
                google_recaptcha_helper(g_recaptcha_response)
        elif username:
            attempts = VerificationAttempt.objects.filter(username=username, created_at__gt=attempt_check_range).count()
            if attempts >= conf.maximum_verification_attempts_codes_count:
                google_recaptcha_helper(g_recaptcha_response)
        else:
            logs_adder(f'CRITICAL: Invalid State #216321635213')
            return MyResponse(request, {'status': 'error', 'message': 'error_500'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    except GoogleRecaptchaException as e:
        return e.my_response


def check_wrong_verification_attempts_and_recaptcha_helper(ip, g_recaptcha_response, email, phone):
    try:
        attempt_check_range = timezone.now() - timedelta(hours=48)

        ip_attempts = WrongVerificationAttempt.objects.filter(ip=ip, created_at__gt=attempt_check_range).count()

        if ip_attempts >= conf.maximum_verification_attempts_per_ip:
            google_recaptcha_helper(g_recaptcha_response)

        if email:
            attempts = WrongVerificationAttempt.objects.filter(email=email, created_at__gt=attempt_check_range).count()
            if attempts >= conf.maximum_wrong_verification_code_per_email:
                google_recaptcha_helper(g_recaptcha_response)
        elif phone:
            attempts = WrongVerificationAttempt.objects.filter(phone=phone, created_at__gt=attempt_check_range).count()
            if attempts >= conf.maximum_wrong_verification_code_per_phone:
                google_recaptcha_helper(g_recaptcha_response)
        else:
            logs_adder(f'CRITICAL: Invalid State #216321635213')
            return MyResponse(request, {'status': 'error', 'message': 'error_500'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    except GoogleRecaptchaException as e:
        return e.my_response


def check_wrong_password_attempts_and_recaptcha_helper(ip, g_recaptcha_response, email, phone, username):
    try:
        attempt_check_range = timezone.now() - timedelta(hours=48)

        ip_attempts = WrongPasswordAttempt.objects.filter(ip=ip, created_at__gt=attempt_check_range).count()

        if ip_attempts >= conf.maximum_wrong_password_attempt_per_customer_ip:
            google_recaptcha_helper(g_recaptcha_response)

        if email:
            attempts = WrongPasswordAttempt.objects.filter(email=email, created_at__gt=attempt_check_range).count()
            if attempts >= conf.maximum_wrong_password_attempt_per_customer:
                google_recaptcha_helper(g_recaptcha_response)
        elif phone:
            attempts = WrongPasswordAttempt.objects.filter(phone=phone, created_at__gt=attempt_check_range).count()
            if attempts >= conf.maximum_wrong_password_attempt_per_customer:
                google_recaptcha_helper(g_recaptcha_response)
        elif username:
            attempts = WrongPasswordAttempt.objects.filter(username=username, created_at__gt=attempt_check_range).count()
            if attempts >= conf.maximum_wrong_password_attempt_per_customer:
                google_recaptcha_helper(g_recaptcha_response)
        else:
            logs_adder(f'CRITICAL: Invalid State #216321635213')
            return MyResponse(request, {'status': 'error', 'message': 'error_500'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    except GoogleRecaptchaException as e:
        return e.my_response


class GoogleRecaptchaException(Exception):
    def __init__(self, my_response):
        my_response.accepted_renderer = JSONRenderer()
        my_response.accepted_media_type = "application/json"
        my_response.renderer_context = {}
        my_response.render()
        self.my_response = my_response

    def __repr__(self):
        return self.my_response


def google_recaptcha_helper(g_recaptcha_response):
    google_recaptcha_v3_verify_url = "https://www.google.com/recaptcha/api/siteverify"
    if g_recaptcha_response:
        payload = {
            'secret': settings.GOOGLE_RECAPTCHA_V3_SECRET,
            'response': g_recaptcha_response,
        }
        try:
            response = requests.post(google_recaptcha_v3_verify_url, data=payload)
            response = response.json()
        except:
            logs_adder(f'CRITICAL: Invalid Google Response')
            raise GoogleRecaptchaException(
                MyResponse(request, {'status': 'error', 'message': 'error_500'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR))
        if not response['success']:
            data = {'status': 'error', 'message': 'Invalid reCAPTCHA. Please try again.'}
            raise GoogleRecaptchaException(MyResponse(request, data, status=status.HTTP_400_BAD_REQUEST))
    else:
        data = {'status': 'error', 'message': 'The number of attempts you make is too much'}
        raise GoogleRecaptchaException(MyResponse(request, data, status=status.HTTP_429_TOO_MANY_REQUESTS))
