import datetime
import glob
import os
import tempfile

from PIL import Image
from django.contrib.auth.hashers import make_password, check_password
from django.test import override_settings
from django.utils import timezone

from authenticate import conf
from authenticate.conf import maximum_profile_image_size_MG
from authenticate.models import VerificationAttempt, User, WrongPasswordAttempt, UserJWT, WrongVerificationAttempt
from wikiazma.myTest import MyTestCase
from wikiazma.storage_helper import public_storage
from zappa_schedule import verification_attempt_cleanup_scheduler, wrong_password_attempt_cleanup_scheduler, jwtoken_cleanup_scheduler


@override_settings(MEDIA_ROOT=tempfile.mkdtemp())
class UserAuthenticateTest(MyTestCase):

    def create_image(self):
        with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as f:
            image = Image.new('RGB', (200, 200), 'red')
            image.save(f, 'PNG')
        return open(f.name, mode='rb')

    def setUp(self):
        # every test will run twice
        # once without user info and once with user info
        self.setBaseUser()
        self.image = None
        self.testType = "1"
        # getattr(self, self._testMethodName)()
        # self.tearDown()
        #
        # # running test for the second time
        # self.setBaseUser()
        #
        # self.user.first_name = 'ahmad'
        # self.user.last_name = 'parsa'
        # self.user.info = '{"bio":"some"}'
        # self.user.save()
        # self.image = self.create_image()
        # self.post_with_token(self.authenticateHelper.set_profile_image, {'image': self.image})
        # self.testType = "2"

    def tearDown(self):
        files = glob.glob('test_files/*')
        for file in files:
            if not file.endswith(('/image.png', '\image.png', 'fakepng.png', '.pdf')):
                os.remove(file)
        if self.image != None:
            self.image.close()
        User.objects.all().delete()
        VerificationAttempt.objects.all().delete()
        WrongPasswordAttempt.objects.all().delete()
        UserJWT.objects.all().delete()

    # ######################### Register API Tests ##############################

    def test_send_a_verification_code_maximum_verification_codes_with_email(self):
        for item in range(conf.maximum_verification_attempts_codes_count):
            self.authenticateHelper.new_verification_attempt_with_email(email='ahmad1@yahoo.com')
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.send_a_verification_code_url,
            {'email': 'ahmad1@yahoo.com'}, "")
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)

    def test_send_a_verification_code_maximum_verification_codes_with_phone(self):
        for item in range(conf.maximum_verification_attempts_codes_count):
            self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234567')
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.send_a_verification_code_url,
            {'phone': '09101234567'}, "")
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)

    def test_send_a_verification_code_maximum_verification_codes_with_username_and_recovery_phone(self):
        recovery_phone = "09991234567"
        username = "ahmad"
        (user, _) = self.authenticateHelper.new_user_with_user_name_and_recovery_phone(recovery_phone=recovery_phone, username=username)

        for item in range(conf.maximum_verification_attempts_codes_count):
            self.authenticateHelper.new_verification_attempt_with_username(username='ahmad')

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.send_a_verification_code_url,
            {'username': username})
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)

    def test_send_a_verification_code_successful(self):
        # email
        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.send_a_verification_code_url, {'email': 'ahmad1@yahoo.com'})
        self.assertEqual(response_data['status'], 'ok', error_message)
        self.assertEqual(response_data['message'], 'Successful', error_message)

        # phone
        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.send_a_verification_code_url, {'phone': '09101234567'})
        self.assertEqual(response_data['status'], 'ok', error_message)
        self.assertEqual(response_data['message'], 'Successful', error_message)

        # phone number without 0
        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.send_a_verification_code_url, {'phone': '9101234567'})
        self.assertEqual(response_data['status'], 'ok', error_message)
        self.assertEqual(response_data['message'], 'Successful', error_message)

        # username with recovery_phone
        recovery_phone = "09991234567"
        username = "ahmad"
        (user, _) = self.authenticateHelper.new_user_with_user_name_and_recovery_phone(recovery_phone=recovery_phone, username=username)

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.send_a_verification_code_url,
            {'username': username})
        self.assertEqual(response_data['status'], 'ok', error_message)
        self.assertEqual(response_data['message'], 'Successful', error_message)

    def test_send_a_verification_code_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.send_a_verification_code_url,
            {'email': 'ahmadyahoo.com'}, "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.send_a_verification_code_url,
            {'email': 'ahmad@yahoo.com', 'phone': '09101234567'}, "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.send_a_verification_code_url,
            {}, "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.send_a_verification_code_url,
                                                                           {'phone': "abc"}, "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)
        self.assertEqual(response_data['fields']['phone'], 'phone characters should be digits', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.send_a_verification_code_url,
                                                                           {'phone': "123456789012345678"}, "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)
        self.assertEqual(response_data['fields']['phone'], 'Enter a valid phone', error_message)

    # ################## RegisterVCodeCheck API Tests ########################

    def test_login_or_verification_code_check_error_response(self):
        # with email
        self.authenticateHelper.verification_code_check_incorrect_code_with_email(email='ahmad1@yahoo.com')
        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_or_verification_code_check, {'email': 'ahmad3@yahoo.com', 'code': '123456'})
        self.assertEqual(response_data['message'], 'wrong code', error_message)
        # with phone
        self.authenticateHelper.verification_code_check_incorrect_code_with_phone(phone='09101234567')
        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_or_verification_code_check, {'phone': '09101234568', 'code': '123456'})
        self.assertEqual(response_data['message'], 'wrong code', error_message)

    def test_login_or_verification_code_check_maximum_verification_attempt_attempts(self):
        # with email
        self.authenticateHelper.new_verification_attempt_with_email(email='ahmad1@yahoo.com')
        randnum = self.authenticateHelper.generate_randnum_not_equals_to_verification_code(
            model=VerificationAttempt, email='ahmad1@yahoo.com')
        for item in range(conf.maximum_verification_attempt_attempts):
            self.post_with_token(self.authenticateHelper.login_or_verification_code_check,
                                 {'email': 'ahmad1@yahoo.com', 'code': randnum}, "")
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check, {'email': 'ahmad1@yahoo.com', 'code': '123456'},
            "")
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)
        # with phone
        self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234567')
        randnum = self.authenticateHelper.generate_randnum_not_equals_to_verification_code(
            model=VerificationAttempt, phone='09101234567')
        for item in range(conf.maximum_verification_attempt_attempts):
            self.post_with_token(self.authenticateHelper.login_or_verification_code_check,
                                 {'phone': '09101234567', 'code': randnum}, "")
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check, {'phone': '09101234567', 'code': '123456'}, "")
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)

    def test_login_or_verification_code_check_successful_response_user_not_exists(self):
        # with email
        self.authenticateHelper.new_verification_attempt_with_email(email='ahmad1@yahoo.com')
        verification_code = VerificationAttempt.objects.get(email='ahmad1@yahoo.com').verification_code
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check,
            {'email': 'ahmad1@yahoo.com', 'code': verification_code}, "")
        self.assertEqual(response_data['message'], 'Verification Code is valid. Please register.', error_message)
        self.assertEqual(len(response_data['data']), 0, error_message)
        # with phone
        self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234567')
        verification_code = VerificationAttempt.objects.get(phone='09101234567').verification_code
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check,
            {'phone': '09101234567', 'code': verification_code}, "")
        self.assertEqual(response_data['message'], 'Verification Code is valid. Please register.', error_message)
        self.assertEqual(len(response_data['data']), 0, error_message)

    def test_login_or_verification_code_check_successful_response_user_exists(self):
        # with email
        self.authenticateHelper.new_user_with_email(email='ahmad1@yahoo.com')
        self.authenticateHelper.new_verification_attempt_with_email(email='ahmad1@yahoo.com')
        verification_code = VerificationAttempt.objects.get(email='ahmad1@yahoo.com').verification_code
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check,
            {'email': 'ahmad1@yahoo.com', 'code': verification_code}, "")
        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.assertIn('data', response_data, error_message)
        self.assertIn('token', response_data['data'], error_message)
        self.assertIn('user', response_data['data'], error_message)
        # with phone
        self.authenticateHelper.new_user_with_phone(phone='09101234567')
        self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234567')
        verification_code = VerificationAttempt.objects.get(phone='09101234567').verification_code
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check,
            {'phone': '09101234567', 'code': verification_code}, "")
        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.assertIn('token', response_data['data'], error_message)
        self.assertIn('user', response_data['data'], error_message)

    def test_verification_code_check_phone_variant_successful(self):
        self.authenticateHelper.new_user_with_phone(phone='09101234567')
        self.authenticateHelper.new_verification_attempt_with_phone(phone='9101234567')
        verification_code = VerificationAttempt.objects.get(phone='09101234567').verification_code
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check,
            {'phone': '9101234567', 'code': verification_code}, "")
        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.assertIn('token', response_data['data'], error_message)
        self.assertIn('user', response_data['data'], error_message)

    def test_login_or_verification_code_check_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check, {}, "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check, {'email': 'ahmad1@yahoo.com', 'code': ''}, "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check,
            {'email': 'ahmadyahoo.com', 'code': '123456'}, "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.login_or_verification_code_check,
            {'email': 'ahmad@yahoo.com', 'phone': '09101234567',
             'code': '123456'}, "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)

    # ####################### RegisterV API Tests ############################

    def test_register_serializer_error(self):
        (response_data, status_code, error_message) = self.post_without_token(self.authenticateHelper.register_url)
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_without_token(self.authenticateHelper.register_url,
                                                                              {'email': 'ahmadyahoo.com',
                                                                               'code': '123456'})
        self.assertEqual(response_data['status'], 'validation_error', error_message)
        self.assertEqual(response_data['fields']['email'], 'Enter a valid email address', error_message)
        self.assertEqual(response_data['fields']['first_name'], 'This field is required.', error_message)
        self.assertEqual(response_data['fields']['last_name'], 'This field is required.', error_message)

        # sending both phone and email
        (response_data, status_code, error_message) = self.post_without_token(self.authenticateHelper.register_url,
                                                                              {'email': 'ahmad@yahoo.com',
                                                                               'phone': '09101234567',
                                                                               'code': '123456', 'first_name': 'Ali',
                                                                               'last_name': 'Zamani'})
        self.assertEqual(response_data['status'], 'validation_error', error_message)
        self.assertEqual(response_data['fields']['non_field_errors'], 'You should send phone or email', error_message)

        # invalid username
        self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234567')
        verification_code = VerificationAttempt.objects.filter(phone='09101234567').last().verification_code
        (response_data, status_code, error_message) = self.post_without_token(self.authenticateHelper.register_url,
                                                                              {'phone': '09101234567',
                                                                               'code': verification_code,
                                                                               'first_name': 'Ali',
                                                                               'last_name': 'Zamani',
                                                                               'username': 'a'})
        self.assertEqual(response_data['message'], 'Some fields are not valid', error_message)
        self.assertEqual(response_data['fields']['username'],
                         'Enter a valid name. it can be english and persian characters, numbers and dot, underline or space and also between 3 and 100 characters',
                         error_message)

    def test_register_error_response(self):
        # invalid code with email
        self.authenticateHelper.new_verification_attempt_with_email(email='ahmad1@yahoo.com')
        randnum = self.authenticateHelper.generate_randnum_not_equals_to_verification_code(
            model=VerificationAttempt, email='ahmad1@yahoo.com')
        (response_data, status_code, error_message) = self.post_without_token(self.authenticateHelper.register_url,
                                                                              {'email': 'ahmad1@yahoo.com',
                                                                               'code': randnum,
                                                                               'first_name': 'Ali',
                                                                               'last_name': 'Zamani'})
        self.assertEqual(response_data['message'], 'Your verification code is incorrect', error_message)

        # invalid code with phone
        self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234567')
        randnum = self.authenticateHelper.generate_randnum_not_equals_to_verification_code(
            model=VerificationAttempt, phone='09101234567')
        (response_data, status_code, error_message) = self.post_without_token(self.authenticateHelper.register_url,
                                                                              {'phone': '09101234567',
                                                                               'code': randnum,
                                                                               'first_name': 'Ali',
                                                                               'last_name': 'Zamani'})
        self.assertEqual(response_data['message'], 'Your verification code is incorrect', error_message)

    def test_register_maximum_verification_attempt_attempts(self):
        # with email
        self.authenticateHelper.new_verification_attempt_with_email(email='ahmad1@yahoo.com')
        randnum = self.authenticateHelper.generate_randnum_not_equals_to_verification_code(
            model=VerificationAttempt, email='ahmad1@yahoo.com')
        for item in range(conf.maximum_wrong_verification_code_per_email):
            (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.register_url,
                                                                               {'email': 'ahmad1@yahoo.com', 'code': randnum,
                                                                                'first_name': 'Ali', 'last_name': 'Zamani'}, "")
            self.assertEqual(response_data['message'], 'Your verification code is incorrect', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.register_url,
                                                                           {'email': 'ahmad1@yahoo.com',
                                                                            'code': '123456',
                                                                            'first_name': 'Ali',
                                                                            'last_name': 'Zamani'}, "")
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)

        # cleanup
        WrongVerificationAttempt.objects.all().delete()

        # with phone
        self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234567')
        randnum = self.authenticateHelper.generate_randnum_not_equals_to_verification_code(
            model=VerificationAttempt, phone='09101234567')
        for item in range(conf.maximum_wrong_verification_code_per_phone):
            (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.register_url,
                                                                               {'phone': '09101234567', 'code': randnum,
                                                                                'first_name': 'Ali', 'last_name': 'Zamani'}, "")
            self.assertEqual(response_data['message'], 'Your verification code is incorrect', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.register_url,
                                                                           {'phone': '09101234567',
                                                                            'code': '123456',
                                                                            'first_name': 'Ali',
                                                                            'last_name': 'Zamani'}, "")
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)

    def test_register_successful_response(self):
        # with email
        self.authenticateHelper.new_verification_attempt_with_email(email='ahmad1@yahoo.com')
        verification_code = VerificationAttempt.objects.get(email='ahmad1@yahoo.com').verification_code
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.register_url,
                                                                           {'email': 'ahmad1@yahoo.com',
                                                                            'code': verification_code,
                                                                            'first_name': 'Ali',
                                                                            'last_name': 'Zamani'}, "")
        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.assertIn('token', response_data['data'], error_message)
        self.assertIn('user', response_data['data'], error_message)
        self.assertEqual(response_data['data']['user']['email'], 'ahmad1@yahoo.com', error_message)
        self.assertEqual(response_data['data']['user']['last_name'], 'Zamani', error_message)

        # with phone
        self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234567')
        verification_code = VerificationAttempt.objects.get(phone='09101234567').verification_code
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.register_url,
                                                                           {'phone': '09101234567',
                                                                            'code': verification_code,
                                                                            'first_name': 'Ali',
                                                                            'last_name': 'Zamani'}, "")
        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.assertIn('token', response_data['data'], error_message)
        self.assertIn('user', response_data['data'], error_message)
        self.assertEqual(response_data['data']['user']['phone'], '09101234567', error_message)
        self.assertEqual(response_data['data']['user']['last_name'], 'Zamani', error_message)

        # with phone and username
        self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234568')
        verification_code = VerificationAttempt.objects.get(phone='09101234568').verification_code
        (response_data, status_code, error_message) = self.post_without_token(self.authenticateHelper.register_url,
                                                                              {'phone': '09101234568',
                                                                               'code': verification_code,
                                                                               'first_name': 'Ali',
                                                                               'last_name': 'Zamani',
                                                                               'username': 'ali_zamani'})
        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.assertIn('token', response_data['data'], error_message)
        self.assertIn('user', response_data['data'], error_message)
        self.assertEqual(response_data['data']['user']['phone'], '09101234568', error_message)
        self.assertEqual(response_data['data']['user']['last_name'], 'Zamani', error_message)
        self.assertEqual(response_data['data']['user']['username'], 'ali_zamani', error_message)

    def test_register_phone_variant_successful(self):
        # using 09101234567 in send_a_verification_code and using 9101234567 in register
        self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234567')
        verification_code = VerificationAttempt.objects.get(phone='09101234567').verification_code
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.register_url,
                                                                           # phone number without the leading zero
                                                                           {'phone': '9101234567',
                                                                            'code': verification_code,
                                                                            'first_name': 'Ali',
                                                                            'last_name': 'Zamani'}, "")
        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.assertIn('token', response_data['data'], error_message)
        self.assertIn('user', response_data['data'], error_message)
        self.assertEqual(response_data['data']['user']['phone'], '09101234567', error_message)
        self.assertEqual(response_data['data']['user']['last_name'], 'Zamani', error_message)

        # using 9101234568 in send_a_verification_code and using 09101234568 in register
        self.authenticateHelper.new_verification_attempt_with_phone(phone='9101234568')
        verification_code = VerificationAttempt.objects.get(phone='09101234568').verification_code
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.register_url,
                                                                           # phone number without the leading zero
                                                                           {'phone': '09101234568',
                                                                            'code': verification_code,
                                                                            'first_name': 'Ali',
                                                                            'last_name': 'Zamani'}, "")
        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.assertIn('token', response_data['data'], error_message)
        self.assertIn('user', response_data['data'], error_message)
        self.assertEqual(response_data['data']['user']['phone'], '09101234568', error_message)
        self.assertEqual(response_data['data']['user']['last_name'], 'Zamani', error_message)

    def test_register_email_variant_successful(self):
        self.authenticateHelper.new_verification_attempt_with_email(email='Ahmad1@yahoo.com')
        verification_code = VerificationAttempt.objects.get(email='ahmad1@yahoo.com').verification_code
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.register_url,
                                                                           {'email': 'Ahmad1@yahoo.com',
                                                                            'code': verification_code,
                                                                            'first_name': 'Ali',
                                                                            'last_name': 'Zamani'}, "")
        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.assertIn('token', response_data['data'], error_message)
        self.assertIn('user', response_data['data'], error_message)
        self.assertEqual(response_data['data']['user']['email'], 'ahmad1@yahoo.com', error_message)
        self.assertEqual(response_data['data']['user']['last_name'], 'Zamani', error_message)

    def test_register_twice_should_return_400_error(self):
        self.authenticateHelper.new_user_with_phone(phone='09101234567')

        self.authenticateHelper.new_verification_attempt_with_phone(phone='09101234567')
        verification_code = VerificationAttempt.objects.get(phone='09101234567').verification_code
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.register_url,
                                                                           {'phone': '09101234567',
                                                                            'code': verification_code,
                                                                            'first_name': 'Ali',
                                                                            'last_name': 'Zamani'}, "")
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('Bad request', response_data['message'], error_message)

    # ######################### Login API Tests ##############################

    def test_login_serializer_error(self):
        (response_data, status_code, error_message) = self.post_without_token(self.authenticateHelper.login_url)
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'email': 'ahmad1@yahoo.com'})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'email': 'ahmad1@yahoo.com', 'password': ''})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        # using a weak password in login no longer return error
        # (response_data, status_code, error_message) = self.post_without_token(
        #     self.authenticateHelper.login_url, {'email': 'ahmad1@yahoo.com', 'password': 'asdf1234'})
        # self.assertEqual(response_data['status'], 'validation_error', error_message)

    def test_login_error_response(self):
        self.user.password = make_password(str(self.user.id) + 'Asdf1234')
        self.user.save()
        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'email': 'ahmad3@yahoo.com', 'password': 'Asdf1234'})
        self.assertEqual(response_data['message'], 'Email or password is incorrect')

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'email': self.user.email, 'password': 'Asdf1235'})
        self.assertEqual(response_data['message'], 'Email or password is incorrect')

    def test_login_maximum_wrong_password_attempts(self):
        # login with email and password
        email = 'ahmad1@yahoo.com'
        (email_user, _) = self.authenticateHelper.new_user_with_email(email=email, password='Asdf1234')

        for i in range(min(conf.maximum_wrong_password_attempt_per_customer_ip, conf.maximum_wrong_password_attempt_per_customer)):
            (response_data, status_code, error_message) = self.post_without_token(
                self.authenticateHelper.login_url, {'email': email, 'password': 'wrong_password'})
            self.assertEqual(response_data['message'], 'Email or password is incorrect', error_message)

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'email': email, 'password': 'Asdf1234'})
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)

        # cleanup
        WrongPasswordAttempt.objects.all().delete()

        # In this test, there is no difference between a user with phone+username and a user with username+recovery_phone
        # login with phone and password + login with username and password
        phone = "09991234567"
        username = "ahmad"
        (phone_user, _) = self.authenticateHelper.new_user_with_phone(phone=phone, username=username, password='Asdf1234')

        #   # with phone
        for i in range(min(conf.maximum_wrong_password_attempt_per_customer_ip, conf.maximum_wrong_password_attempt_per_customer)):
            (response_data, status_code, error_message) = self.post_without_token(
                self.authenticateHelper.login_url, {'phone': phone, 'password': 'wrong_password'})
            self.assertEqual(response_data['message'], 'Phone or password is incorrect', error_message)

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'phone': phone, 'password': 'Asdf1234'})
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)

        # cleanup
        WrongPasswordAttempt.objects.all().delete()

        #   # with username
        for i in range(min(conf.maximum_wrong_password_attempt_per_customer_ip, conf.maximum_wrong_password_attempt_per_customer)):
            (response_data, status_code, error_message) = self.post_without_token(
                self.authenticateHelper.login_url, {'username': username, 'password': 'wrong_password'})
            self.assertEqual(response_data['message'], 'Username or password is incorrect', error_message)

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'username': username, 'password': 'Asdf1234'})
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)

        # test ip block
        for i in range(max(conf.maximum_wrong_password_attempt_per_customer_ip, conf.maximum_wrong_password_attempt_per_customer)
                       - min(conf.maximum_wrong_password_attempt_per_customer_ip, conf.maximum_wrong_password_attempt_per_customer)):
            (response_data, status_code, error_message) = self.post_without_token(
                self.authenticateHelper.login_url, {'phone': phone, 'password': 'wrong_password'})
            self.assertEqual(response_data['message'], 'Phone or password is incorrect', error_message)

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'phone': phone, 'password': 'Asdf1234'})
        self.assertEqual(response_data['message'], 'The number of attempts you make is too much', error_message)

    def test_login_check_password(self):
        self.user.password = make_password(str(self.user.id) + 'asdf1234')
        self.user.save()
        self.assertTrue(check_password(str(self.user.id) + 'asdf1234', self.user.password))

    def test_login_successful_response(self):
        phone = "09991234567"
        username = "ahmad"
        self.authenticateHelper.new_user_with_phone(phone=phone, username=username, password='Asdf1234')

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'phone': phone, 'password': 'Asdf1234'})
        self.assertEqual(response_data['message'], 'Successful', error_message)

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'username': username, 'password': 'Asdf1234'})
        self.assertEqual(response_data['message'], 'Successful', error_message)

    def test_login_with_username_and_recovery_phone_successful_and_error_response(self):
        recovery_phone = "09991234567"
        username = "ahmad"
        self.authenticateHelper.new_user_with_user_name_and_recovery_phone(recovery_phone=recovery_phone, username=username, password='Asdf1234')

        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'username': username, 'password': 'Asdf1234'})
        self.assertEqual(response_data['message'], 'Successful', error_message)

        # login with recovery phone is not possible because its not unique
        (response_data, status_code, error_message) = self.post_without_token(
            self.authenticateHelper.login_url, {'phone': recovery_phone, 'password': 'Asdf1234'})
        self.assertEqual(response_data['message'], 'Phone or password is incorrect', error_message)

    # ######################### Logout API Tests ##############################

    def test_logout_successful_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.logout_url)
        self.assertEqual(response_data['message'], 'Successful', error_message)

    def test_logout_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.logout_url, {},
                                                                           self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    # ###################### ChangePassword API Tests ########################

    def test_change_password_password_validator(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password,
                                                                           {'new_password': 'acdswe1',
                                                                            'code': '123456'})
        self.assertEqual(response_data['fields']['new_password'], 'Password length should be between 8 to 20 characters',
                         error_message)
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password,
                                                                           {'new_password': 'acdsw3eswe1',
                                                                            'code': '123456'})
        self.assertEqual(response_data['fields']['new_password'],
                         'Password should contain at least an uppercase letter and a digit', error_message)

    def test_change_password_null_user_password(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password,
                                                                           {
                                                                               'old_password': 'Asdf1235',
                                                                               'new_password': 'Asdf1230'})
        self.assertEqual(response_data['message'], 'Wrong Old Password', error_message)

    def test_change_password_maximum_attempts_with_email(self):
        (user2, user2_token) = self.authenticateHelper.new_user_with_email(email="ahmad3@yahoo.com", password='dEdhbd3Ethdset')

        for item in range(conf.maximum_wrong_password_attempt_per_customer):
            (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password,
                                                                               {
                                                                                   'old_password': 'wrongPassword980',
                                                                                   'new_password': 'dEdhbd3Ethdset',
                                                                               }, test_token=user2_token)

            self.assertEqual(response_data['message'], 'Wrong Old Password', error_message)
        (response, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password,
                                                                      {
                                                                          'old_password': 'dEdhbd3Ethdset',
                                                                          'new_password': 'newPassword123',
                                                                      }, test_token=user2_token)

        self.assertEqual(response['message'], 'The number of attempts you make is too much', error_message)

    def test_change_password_successful(self):
        (user2, user2_token) = self.authenticateHelper.new_user_with_email(email="ahmad3@yahoo.com", password='dEdhbd3Ethdset')
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password,
                                                                           {
                                                                               'old_password': 'dEdhbd3Ethdset',
                                                                               'new_password': 'Asdf1235',
                                                                           }, test_token=user2_token)

        self.assertEqual(response_data['message'], 'Password updated successfully', error_message)

        (user3, user3_token) = self.authenticateHelper.new_user_with_phone(phone="09021729894", password='Asdf1235')
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password,
                                                                           {
                                                                               'old_password': 'Asdf1235',
                                                                               'new_password': 'Asdf1235',
                                                                           }, test_token=user3_token)

        self.assertEqual(response_data['message'], 'Password updated successfully', error_message)

    def test_change_password_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password)
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password,
                                                                           {'password': 'asdf123'})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password,
                                                                           {'password': 'asdf123', 'code': ''})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

    def test_change_password_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.change_password, {},
                                                                           self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    # #################### ForgetPassword API Tests #####################

    def test_forget_password_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password)
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'email': self.user.email})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'email': self.user.email,
                                                                            'new_password': 'asdf'})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'email': self.user.email,
                                                                            'new_password': 'asdf1235',
                                                                            'code': ''})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'email': 'ahmad@123456',
                                                                            'new_password': 'asdf1235',
                                                                            'code': '123456'})
        self.assertEqual(response_data['fields']['email'], 'Enter a valid email address', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'email': 'ahmad@yahoo.com',
                                                                            'new_password': 'xcv457',
                                                                            'code': '123456'})
        self.assertEqual(response_data['fields']['new_password'],
                         'Password length should be between 8 to 20 characters', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'email': 'ahmad@yahoo.com',
                                                                            'new_password': '123xcv4567',
                                                                            'code': '123456'})
        self.assertEqual(response_data['fields']['new_password'],
                         'Password should contain at least an uppercase letter and a digit', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'email': 'ahmad@yahoo.com',
                                                                            'new_password': 'asdf1235',
                                                                            'code': '1a2b3c'})
        self.assertEqual(response_data['fields']['code'], 'Enter a valid verification code', error_message)

    def test_forget_password_record_not_exists(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'email': self.user.email,
                                                                            'new_password': 'Asdf1235',
                                                                            'code': '123456'})
        self.assertEqual(response_data['message'], 'Your verification code is incorrect', error_message)

    def test_forget_password_successful(self):
        # with email
        self.authenticateHelper.new_verification_attempt_with_email(email=self.user.email)
        verification_code = VerificationAttempt.objects.get(email=self.user.email).verification_code

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'email': self.user.email,
                                                                            'new_password': 'Asdf1235',
                                                                            'code': verification_code})

        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.authenticateHelper.login_with_password_helper(email=self.user.email, password='Asdf1235')

        (user2, _) = self.authenticateHelper.new_user_with_phone()
        # with phone
        self.authenticateHelper.new_verification_attempt_with_phone(phone=user2.phone)
        verification_code = VerificationAttempt.objects.get(phone=user2.phone).verification_code

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'phone': user2.phone,
                                                                            'new_password': 'Asdf1235',
                                                                            'code': verification_code})

        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.authenticateHelper.login_with_password_helper(phone=user2.phone, password='Asdf1235')

        (user3, _) = self.authenticateHelper.new_user_with_user_name_and_recovery_phone()
        # with username and recovery_phone
        self.authenticateHelper.new_verification_attempt_with_username(username=user3.username)
        verification_code = VerificationAttempt.objects.get(username=user3.username, recovery_phone=user3.recovery_phone).verification_code

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'username': user3.username,
                                                                            'new_password': 'Asdf1235',
                                                                            'code': verification_code})

        self.assertEqual(response_data['message'], 'Successful', error_message)
        self.authenticateHelper.login_with_password_helper(username=user3.username, password='Asdf1235')

    def test_reset_password_email_before_register(self):
        self.authenticateHelper.new_verification_attempt_with_email(email='test@test.com')
        verification_code = VerificationAttempt.objects.get(email='test@test.com').verification_code

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.forget_password,
                                                                           {'email': 'test@test.com',
                                                                            'new_password': 'Asdf1235',
                                                                            'code': verification_code})

        self.assertEqual(response_data['message'], 'Register First', error_message)

    # ###################### EditProfile API Tests #######################

    def test_edit_profile_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'first_name': ''})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'first_name': 'a'})
        self.assertIn('Enter a valid name.', response_data['fields']['first_name'], error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'last_name': ''})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'last_name': 'b'})
        self.assertIn('Enter a valid name.', response_data['fields']['last_name'], error_message)

    def test_edit_profile_successful_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'first_name': 'reza'})
        self.assertEqual(response_data['message'], 'Successful', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'last_name': 'alavi'})
        self.assertEqual(response_data['message'], 'Successful', error_message)

    def test_edit_profile_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile, {},
                                                                           self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    # ###################### SetProfileImage API Tests #######################

    def test_set_profile_image_invalid_extension(self):
        with tempfile.NamedTemporaryFile(suffix='.bmp', delete=False) as f:
            image = Image.new('RGB', (100, 100), 'red')
            image.save(f, 'BMP')
        self.image = open(f.name, mode='rb')
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'image': self.image})
        self.assertEqual(response_data['fields']['image'], "The image format must be jpg, JPG, jpeg, png, PNG", error_message)
        self.image.close()

    def test_set_profile_image_successful_response_without_compression(self):
        # file_size = 100 * 1024

        # TODO the image is not being deleted after the test
        # C:\\Users\\HAROON\\AppData\\Local\\Temp\\tmpyp9516hd.png
        with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as f:
            # 100x100 image and its thumbnail will not be compressed
            image = Image.new('RGB', (100, 100), 'green')
            image.save(f, 'PNG')
            # Due to changes in the compress_image function, ((seek)) no longer works. The original size of this image is 287.
            # f.seek(file_size)
            f.write(b"\0")
            f.close()

            self.image = open(f.name, mode='rb')
            (response_data, status_code, error_message) = self.post_with_token(
                self.authenticateHelper.edit_profile, {'image': self.image})
            self.assertEqual(response_data['message'], 'Successful', error_message)
            self.image.close()

            (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.account_url)
            self.assertEqual(response_data['message'], 'Successful', error_message)

            self.assertNotEqual(response_data['user']["image"], None, error_message)
            self.assertNotEqual(response_data['user']["image_thumbnail"], None, error_message)

            uploaded_image_size = public_storage.size(response_data['user']["image"].replace("/media/public/", ""))
            self.assertEqual(287, uploaded_image_size)

            uploaded_thumbnail_image_size = public_storage.size(
                response_data['user']["image_thumbnail"].replace("/media/public/", ""))
            self.assertEqual(287, uploaded_thumbnail_image_size)

    def test_set_profile_image_successful_response_with_compression(self):
        file_size = 100 * 1024

        with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as f:
            # 500x500 image and its thumbnail will be compressed
            image = Image.new('RGB', (500, 500), 'green')
            image.save(f, 'PNG')
            f.seek(file_size)
            f.write(b"\0")
            f.close()

            self.image = open(f.name, mode='rb')
            (response_data, status_code, error_message) = self.post_with_token(
                self.authenticateHelper.edit_profile, {'image': self.image})
            self.assertEqual(response_data['message'], 'Successful', error_message)
            self.image.close()

            (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.account_url)
            self.assertEqual(response_data['message'], 'Successful', error_message)

            self.assertNotEqual(response_data['user']["image"], None, error_message)
            self.assertNotEqual(response_data['user']["image_thumbnail"], None, error_message)

            uploaded_image_size = public_storage.size(response_data['user']["image"].replace("/media/public/", ""))
            self.assertGreater(file_size, uploaded_image_size)

            uploaded_thumbnail_image_size = public_storage.size(
                response_data['user']["image_thumbnail"].replace("/media/public/", ""))
            self.assertGreater(file_size, uploaded_thumbnail_image_size)

    def test_set_profile_image_wrong_file_type(self):
        for file in ['test_files/document.pdf', 'test_files/fakepng.png']:
            with open(file, 'rb') as fp:
                self.image = open(fp.name, mode='rb')
                (response_data, status_code, error_message) = self.post_with_token(
                    self.authenticateHelper.edit_profile, {'image': self.image})
                self.image.close()
                self.assertEqual(response_data['message'], 'Some fields are not valid', error_message)
                self.assertEqual(response_data['fields']['image'],
                                 'Upload a valid image. The file you uploaded was either not an image or a corrupted image.',
                                 error_message)

    def test_set_profile_image_serializer_error(self):
        # test 5MB+ profile image error message
        # This code generates an image with more than 4MB size.
        with open('test_files/+4mg_img.png', "wb") as f:
            image = Image.new('RGB', (300, 300), 'green')
            image.save(f, 'PNG')
            f.seek(maximum_profile_image_size_MG * 1024 * 1024 + 10)
            f.write(b"\0")
            f.close()

        with open('test_files/+4mg_img.png', 'rb') as fp:
            (response_data, status_code, error_message) = self.post_with_token(
                self.authenticateHelper.edit_profile, {'image': fp})
            self.assertEqual('validation_error', response_data['status'], error_message)
            self.assertEqual(f"The maximum image size must be {maximum_profile_image_size_MG} MB", response_data['fields']['image'], error_message)

    # ###################### RemoveProfileImage API Tests #######################

    def test_remove_profile_image_successful_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile)
        self.assertEqual(response_data['message'], 'Successful', error_message)

    def test_remove_profile_image_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {},
                                                                           self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    # ######################## Info API Tests #########################

    def test_info_error_info_format_1(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'info': '{"bia":"some"}'})
        self.assertEqual(response_data['fields']['info'], 'Info format is incorrect', error_message)

        # test long bio error
        long_bio = '#' * 3001
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'info': f'{{"bio":"{long_bio}"}}'})
        self.assertEqual(response_data['fields']['info'], 'bio can not has more than 3000 characters', error_message)

    def test_info_error_info_format_2(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'info': '{"bio":"some","bio2":"some2"}'})
        self.assertEqual(response_data['fields']
                         ['info'], 'Info format is incorrect', error_message)

    def test_info_successful_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'info': '{"bio":"fitcrete"}'})
        self.assertEqual(response_data['message'], 'Successful', error_message)

    def test_info_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'info': ''})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile,
                                                                           {'info': 'some'})
        self.assertEqual(response_data['status'], 'validation_error', error_message)

    def test_info_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.edit_profile, {},
                                                                           self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    # ######################## Profile API Tests #########################

    def test_profile_successful_response(self):
        (user2, user2_token) = self.authenticateHelper.new_user_with_email(email="ahmad3@yahoo.com")

        request = {"user_id": user2.id}
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.profile_url,
                                                                           request=request)
        self.assertEqual(response_data['message'], 'Successful', error_message)

        self.assertIsNone(response_data['user']["username"], error_message)
        self.assertIsNone(response_data['user']["recovery_phone"], error_message)
        self.assertEqual(response_data['user']["first_name"], 'testfirstname', error_message)
        self.assertEqual(response_data['user']["last_name"], 'testlastname', error_message)
        self.assertEqual(response_data['user']["email"], "ahmad3@yahoo.com", error_message)
        self.assertEqual(response_data['user']["image"], None, error_message)
        self.assertEqual(response_data['user']["image_thumbnail"], None, error_message)
        self.assertEqual(response_data['user']["info"], None, error_message)

    def test_profile_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.profile_url, {},
                                                                           self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    # ######################## Account API Tests #########################

    def test_account_successful_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.account_url)
        self.assertEqual(response_data['message'], 'Successful', error_message)
        if self.testType == "1":
            # self.assertEqual(response_data['user']["first_name"], None, error_message)
            # self.assertEqual(response_data['user']["last_name"], None, error_message)
            self.assertEqual(response_data['user']["email"], self.user.email, error_message)
            self.assertEqual(response_data['user']["image"], None, error_message)
            self.assertEqual(response_data['user']["image_thumbnail"], None, error_message)
            self.assertEqual(response_data['user']["info"], None, error_message)
        else:
            self.assertEqual(response_data['user']["first_name"], "ahmad", error_message)
            self.assertEqual(response_data['user']["last_name"], "parsa", error_message)
            self.assertEqual(response_data['user']["email"], self.user.email, error_message)
            self.assertNotEqual(response_data['user']["image"], None, error_message)
            self.assertNotEqual(response_data['user']["image_thumbnail"], None, error_message)
            self.assertNotEqual(response_data['user']["info"], None, error_message)
            self.assertEqual(response_data['user']["info"], '{"bio":"some"}', error_message)

    def test_account_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.account_url, {},
                                                                           self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    def test_google_login_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.google_login_url, {},
                                                                           "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)

    def test_google_login_error(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.google_login_url,
                                                                           {'g_id_token': '1234'}, "")
        self.assertEqual(response_data['status'], 'error', error_message)

    def test_facebook_login_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.facebook_login_url,
                                                                           {}, "")
        self.assertEqual(response_data['status'], 'validation_error', error_message)

    def test_facebook_login_error(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.facebook_login_url,
                                                                           {'fb_code': '1234'}, "")
        self.assertEqual(response_data['status'], 'error', error_message)

    def test_cleanup_expired_verification_attempt_function(self):
        for i in range(5, 10):
            # These users should be deleted because we will change the created_at of them to an expired date
            (response_data, status_code, error_message) = self.post_with_token(
                self.authenticateHelper.send_a_verification_code_url,
                {'email': f'ahmad{i}@yahoo.com'}, "")
            self.assertEqual(response_data['message'], 'Successful', error_message)

        VerificationAttempt.objects.update(
            created_at=timezone.now() - datetime.timedelta(hours=conf.temp_user_cleanup_offset_hours + 1))

        # This temp user should not be deleted
        (response_data, status_code, error_message) = self.post_with_token(
            self.authenticateHelper.send_a_verification_code_url,
            {'email': 'ahmad1@yahoo.com'}, "")
        self.assertEqual(response_data['message'], 'Successful', error_message)

        verification_attempt_cleanup_scheduler()
        self.assertEqual(VerificationAttempt.objects.count(), 1)

    def test_cleanup_expired_wrong_password_attempt_function(self):
        for i in range(3):
            WrongPasswordAttempt.objects.create(ip='127.0.0.1', email=f'ahmad{i}@yahoo.com')

        WrongPasswordAttempt.objects.update(
            created_at=timezone.now() - datetime.timedelta(hours=conf.wrong_password_attempt_cleanup_offset_hours + 1))
        WrongPasswordAttempt.objects.create(ip='127.0.0.1', email='ahmad3@yahoo.com')

        wrong_password_attempt_cleanup_scheduler()
        self.assertEqual(WrongPasswordAttempt.objects.count(), 1)

    def test_cleanup_expired_userjwts_function(self):
        for i in range(3):
            UserJWT.objects.create(user=self.user, token=f'token{i}',
                                   expire_at=timezone.now() + datetime.timedelta(
                                       days=conf.user_jwt_expire_time_in_days))

        UserJWT.objects.update(expire_at=timezone.now() -
                                         datetime.timedelta(days=conf.user_jwt_expire_time_in_days + 1))
        UserJWT.objects.create(user=self.user, token='token3',
                               expire_at=timezone.now() + datetime.timedelta(days=conf.user_jwt_expire_time_in_days))

        jwtoken_cleanup_scheduler()
        self.assertEqual(UserJWT.objects.count(), 1)

    def test_user_balance(self):
        (response_data, status_code, error_message) = self.post_with_token(self.authenticateHelper.user_balance)

        self.assertEqual(response_data['message'], 'Successful', error_message)
