import glob
import os
from datetime import datetime, timedelta

from django.utils import timezone

from collaborators import defined_roles as dr
from collaborators.models import Access, InviteAccess
from exam.models import Exam, ExamPage, ExamTemplate
from institute.models import Institute, TransferOwnershipHistory, APIKey, InstituteStudent
from payment.models import InstituteBalanceHistory
from plan.models import Environment
from wikiazma.myTest import MyTestCase
from . import conf


class InstituteTest(MyTestCase):

    def setUp(self):
        self.setUpHelpers()
        self.setBaseUser()
        (self.second_user, self.second_user_token) = self.authenticateHelper.new_user_with_email()

        Environment.objects.update(default_max_institutes_per_user=100, default_max_collaborators_per_institute=100)
        self.institute = self.instituteHelper.create_institute(name="unit_test_institute")

    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)
        InstituteStudent.objects.filter().delete()
        ExamPage.objects.filter().delete()
        Exam.objects.filter().delete()
        ExamTemplate.objects.filter().delete()
        self.instituteHelper.delete_institute(institute_id=self.institute["id"])
        self.user.delete()
        # Institute.objects.filter(user=self.second_user).delete()
        self.second_user.delete()

    def test_create_institute_successful_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.createInstituteURL,
                                                                           {'name': 'some'})
        self.assertEqual(response_data['message'], 'Successful', error_message)

        self.assertEqual(0, InstituteBalanceHistory.objects.first().remaining_balance, error_message)
        self.assertEqual('initial_balance', InstituteBalanceHistory.objects.first().reason, error_message)
        self.assertEqual(0, InstituteBalanceHistory.objects.first().amount, error_message)
        self.assertIsNone(InstituteBalanceHistory.objects.first().exam, error_message)
        self.assertEqual({}, InstituteBalanceHistory.objects.first().reason_meta_data, error_message)
        with open('test_files/image.png', 'rb') as fp1:
            (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.createInstituteURL,
                                                                            {'name': 'some_test','logo':fp1})
            self.assertEqual(response_data['message'], 'Successful', error_message)
        with open('test_files/image.png', 'rb') as fp1:
            (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.createInstituteURL,
                                                                            {'name': 'some_test','poster':fp1})
            self.assertEqual(response_data['message'], 'Successful', error_message)
    def test_create_institute_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(
            '/institute/create', {}, self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)



    def test_create_institute_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.createInstituteURL)
        self.assertEqual(response_data['status'], 'validation_error')

        for invalid_name in self.invalid_names:
            (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.createInstituteURL,
                                                                               {'name': invalid_name})
            self.assertEqual(response_data['status'], 'validation_error')
#TODO skip
    # def test_all_institutes_api_performance(self):
    #     total_count = 100
    #     for i in range(total_count):
    #         (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.createInstituteURL,
    #                                                                            {'name': 'institute_name' + str(i)})
    #         self.assertEqual(response_data['message'], 'Successful')

    #     start = time.time()
    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList,
    #                                                                        {'skip': 50, 'take': 10,
    #                                                                         'sort_by': 'inst_name_desc'})
    #     self.assertEqual(response_data['message'], 'Successful', error_message)
    #     # one extra institute because of setUp function
    #     self.assertEqual(response_data['data']['total_count'], total_count + 1, error_message)
    #     end = time.time()
    #     dt = (end - start) * 1000
    #     self.assertLess(dt, 40, error_message)

    # def test_transfer_ownership_duplicate_institute_name(self):
    #     for name in ["duplicate_institute_name"]:
    #         institute1 = self.instituteHelper.create_institute(name, token=self.second_user_token)
    #
    #         # transferring a institute with the same name to user2
    #         institute2 = self.instituteHelper.create_institute(name)
    #         # self.instituteHelper.transfer_ownership_of_institute(institute2["id"], self.second_user.id, self.second_user.email,
    #         #                                                      self.second_user_token)
    #
    #         (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList,
    #                                                                            {'skip': 0, 'take': 10,
    #                                                                             'sort_by': 'inst_name_desc'},
    #                                                                            test_token=self.second_user_token)
    #         self.assertEqual('Successful', response_data['message'], error_message)
    #         self.assertEqual(3, response_data['data']['total_count'], error_message)
    #         if name == "duplicate_institute_name":
    #             self.assertIn(name + "_", response_data['data']['institutes'][1]["name"], error_message)
    #             self.assertEqual(name, response_data['data']['institutes'][2]["name"], error_message)
    #         else:
    #             self.assertIn(name[:94] + "_", response_data['data']['institutes'][2]["name"], error_message)
    #             self.assertEqual(name, response_data['data']['institutes'][1]["name"], error_message)
    #
    #         (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList,
    #                                                                            {'skip': 0, 'take': 10,
    #                                                                             'sort_by': 'inst_name_desc'})
    #         self.assertEqual(response_data['message'], 'Successful', error_message)
    #         # only the default institute should be left
    #         self.assertEqual(response_data['data']['total_count'], 2, error_message)

    def test_edit_institute_institute_not_exists(self):
        (response_data, status_code, error_message) = self.post_with_token(
            '/institute/edit', {'name': 'fitcrete', 'institute_id': 'dc5cb7eb-2c27-4021-93b3-ae3835a2df75'})
        self.assertEqual(response_data['message'], 'Forbidden')

    def test_edit_institute_successful_response(self):
        (response_data, status_code, error_message) = self.post_with_token('/institute/edit',
                                                                           {'name': 'fitcrete',
                                                                            'institute_id': self.institute["id"]})
        self.assertEqual(response_data['message'], 'Successful')
        (response_data, status_code, error_message) = self.post_with_token('/institute/edit',
                                                                           {'description ': 'test',
                                                                            'name ': 'test',
                                                                            'delete_logo ': True,
                                                                            'info': '{"test":"info"}',
                                                                            'delete_poster  ': True,
                                                                            'institute_id': self.institute["id"]})
        self.assertEqual(response_data['message'], 'Successful',error_message)
        with open('test_files/image.png', 'rb') as fp1:
            (response_data, status_code, error_message) = self.post_with_token('/institute/edit',
                                                                           {'description ': 'test',
                                                                            'name ': 'test',
                                                                            'logo ': fp1,
                                                                            'institute_id': self.institute["id"]})
            self.assertEqual(response_data['message'], 'Successful',error_message)
        with open('test_files/image.png', 'rb') as fp1:
            (response_data, status_code, error_message) = self.post_with_token('/institute/edit',
                                                                           {
                                                                            'name ': 'test',
                                                                            'poster ': fp1,
                                                                            'institute_id': self.institute["id"]})
            self.assertEqual(response_data['message'], 'Successful',error_message)
    def test_edit_institute_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token('/institute/edit', {}, self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    def test_edit_institute_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token('/institute/edit')
        self.assertEqual(response_data['fields']['institute_id'], 'This field is required.')

        (response_data, status_code, error_message) = self.post_with_token('/institute/edit', {'name': 'fi',
                                                                                               'institute_id': self.institute[
                                                                                                   "id"]})
        self.assertEqual(response_data['status'], 'validation_error')

        (response_data, status_code, error_message) = self.post_with_token('/institute/edit',
                                                                           {'name': 'invalid~name',
                                                                            'institute_id': self.institute["id"]})
        self.assertEqual(response_data['status'], 'validation_error')

        (response_data, status_code, error_message) = self.post_with_token('/institute/edit',
                                                                           {'name': 'invalid%name',
                                                                            'institute_id': self.institute["id"]})
        self.assertEqual(response_data['status'], 'validation_error')

        (response_data, status_code, error_message) = self.post_with_token('/institute/edit',
                                                                           {'name': 'invalid*name',
                                                                            'institute_id': self.institute["id"]})
        self.assertEqual(response_data['status'], 'validation_error')

        (response_data, status_code, error_message) = self.post_with_token('/institute/edit',
                                                                           {'name': 'fitcrete', 'institute_id': ''})
        self.assertEqual(response_data['fields']['institute_id'], 'This field may not be blank.')

        (response_data, status_code, error_message) = self.post_with_token('/institute/edit',
                                                                           {'name': '',
                                                                            'institute_id': self.institute["id"]})
        self.assertEqual(response_data['status'], 'validation_error')

    def test_delete_institute_institute_not_exists(self):
        (response_data, status_code, error_message) = self.post_with_token(
            '/institute/delete', {'institute_id': 'dc5cb7eb-2c27-4021-93b3-ae3835a2df75'})
        self.assertEqual(response_data['message'], 'Forbidden')

    def test_delete_institute_successful_response(self):
        (response_data, status_code, error_message) = self.post_with_token(
            '/institute/delete', {'institute_id': self.institute["id"]})
        self.assertEqual(response_data['message'], 'Successful')

    def test_delete_institute_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(
            '/institute/delete', {}, self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    def test_delete_institute_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token('/institute/delete')
        self.assertEqual(response_data['fields']['institute_id'], 'This field is required.')

        (response_data, status_code, error_message) = self.post_with_token('/institute/delete', {'institute_id': ''})
        self.assertEqual(response_data['fields']['institute_id'], 'This field may not be blank.')

    def test_all_institutes_list_successful_response(self):
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList,
                                                                           {'skip': 0, 'take': 3,
                                                                            'sort_by': 'inst_name_asc'})
        self.assertEqual(response_data['message'], 'Successful')
        # the sandbox institute should be always present + the institute we created in setup function
        self.assertEqual(2, response_data['data']['total_count'], error_message)
        self.assertIn("sandbox", response_data['data']['institutes'][0], error_message)
        self.assertEqual(response_data['data']['institutes'][0]['sandbox'], True, error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList,
                                                                           {'skip': 2, 'take': 3, "search_words": "a",
                                                                            'sort_by': 'inst_name_asc'})
        self.assertEqual(response_data['message'], 'Successful')

    def test_all_institutes_list_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(
            '/institute/all', {}, self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    def test_all_institutes_list_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList)
        self.assertEqual(response_data['status'], 'validation_error')

        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList,
                                                                           {'skip': 2})
        self.assertEqual(response_data['status'], 'validation_error')

        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList,
                                                                           {'skip': -1})
        self.assertEqual(response_data['fields']['skip'], 'Ensure this value is greater than or equal to 0.')

        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList,
                                                                           {'skip': 2, 'take': 200})
        self.assertEqual(response_data['fields']['take'], 'Ensure this value is less than or equal to 100.')

        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList,
                                                                           {'skip': 2, 'take': 3, 'sort_by': ''})
        self.assertEqual(response_data['status'], 'validation_error')

        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteAllList,
                                                                           {'skip': 2, 'take': 3, 'sort_by': 'name'})
        self.assertIn('sort_by should be one of', response_data['fields']['sort_by'])
#TODO skip
    # def test_all_institutes_list_owned_institutes_list_successful_response(self):
    #     # (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteOwnedList,
    #     #                                                                    {'skip': 2, 'take': 3,
    #     #                                                                     'sort_by': 'inst_name_asc'})
    #     # self.assertEqual(response_data['message'], 'Successful', error_message)

    #     # (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteOwnedList,
    #     #                                                                    {'skip': 2, 'take': 3, "search_words": "a",
    #     #                                                                     'sort_by': 'inst_name_asc'})
    #     # self.assertEqual(response_data['message'], 'Successful', error_message)

    # def test_owned_institutes_list_token_error_response(self):
    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteOwnedList, {},
    #                                                                        self.test_token + 'some123')
    #       self.assertIn('Authorization failed', response_data['message'], error_message)

    # def test_owned_institutes_list_serializer_error(self):
    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteOwnedList)
    #     self.assertEqual(response_data['status'], 'validation_error')

    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteOwnedList,
    #                                                                        {'skip': 2})
    #     self.assertEqual(response_data['status'], 'validation_error')

    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteOwnedList,
    #                                                                        {'skip': -1})
    #     self.assertEqual(response_data['fields']['skip'], 'Ensure this value is greater than or equal to 0.')

    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteOwnedList,
    #                                                                        {'skip': 2, 'take': 200})
    #     self.assertEqual(response_data['fields']['take'], 'Ensure this value is less than or equal to 100.')

    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteOwnedList,
    #                                                                        {'skip': 2, 'take': 3, 'sort_by': ''})
    #     self.assertEqual(response_data['status'], 'validation_error')

    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.instituteOwnedList,
    #                                                                        {'skip': 2, 'take': 3, 'sort_by': 'nam'})
    #     self.assertIn('sort_by should be one of', response_data['fields']['sort_by'])

    # def test_institute_intersection_user_not_exists(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/intersection',
    #                                                                        {'email': 'ahmad5@yahoo.com', 'skip': 2,
    #                                                                         'take': 3, 'sort_by': 'inst_name_asc'})
    #     self.assertEqual(response_data['message'], 'We cant find this user!')

    # def test_institute_intersection_successful_response(self):
    #     self.second_user_access = Access.objects.create(user=self.second_user, institute_id=self.institute["id"],
    #                                                     roles=[dr.__ROLE_ADMIN__])
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/intersection',
    #                                                                        {'email': self.second_user.email, 'skip': 2,
    #                                                                         'take': 3, 'sort_by': 'inst_name_asc'})
    #     self.assertEqual(response_data['message'], 'Successful')

    #     # upper case email
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/intersection',
    #                                                                        {'email': self.second_user.email.upper(), 'skip': 2,
    #                                                                         'take': 3, 'sort_by': 'inst_name_asc'})
    #     self.assertEqual(response_data['message'], 'Successful')

    # def test_institute_intersection_token_error_response(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/intersection', {},
    #                                                                        self.test_token + 'some123')
    #     self.assertIn('Authorization failed', response_data['message'], error_message)

    # def test_institute_intersection_serializer_error(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/intersection')
    #     self.assertEqual(response_data['status'], 'validation_error')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/intersection',
    #                                                                        {'email': 'arp1051@yahoocom'})
    #     self.assertEqual(response_data['fields']['email'], 'Enter a valid email address')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/intersection', {'skip': -1})
    #     self.assertEqual(response_data['fields']['skip'], 'Ensure this value is greater than or equal to 0.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/intersection',
    #                                                                        {'skip': 2, 'take': 200})
    #     self.assertEqual(response_data['fields']['take'], 'Ensure this value is less than or equal to 100.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/intersection',
    #                                                                        {'skip': 2, 'take': 3, 'sort_by': ''})
    #     self.assertEqual(response_data['status'], 'validation_error')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/intersection',
    #                                                                        {'skip': 2, 'take': 3, 'sort_by': 'nam'})
    #     self.assertIn('sort_by should be one of', response_data['fields']['sort_by'])
#TODO skip
    # def test_transfer_ownership_state_successful_response_without_active_transfer(self):
    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.transferState, {
    #         'institute_id': self.institute["id"]})
    #     self.assertEqual(response_data['message'], 'Successful', error_message)
    #     self.assertEqual(response_data['data'], None, error_message)

    def test_transfer_ownership_state_successful_response_with_active_transfer(self):
        # This test is done later after transfer ownership success
        pass
#TODO skip
    # def test_transfer_ownership_state_token_error_response(self):
    #     (response_data, status_code, error_message) = self.post_with_token(
    #         self.instituteHelper.transferState, {}, self.test_token + 'some123')
    #        self.assertIn('Authorization failed', response_data['message'], error_message)
#TODO skip
    # def test_transfer_ownership_state_serializer_error(self):
    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.transferState)
    #     self.assertEqual(response_data['fields']['institute_id'], 'This field is required.')

    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.transferState,
    #                                                                        {'institute_id': ''})
    #     self.assertEqual(response_data['fields']['institute_id'], 'This field may not be blank.',
    #                      error_message)

    # def test_transfer_ownership_new_owner_not_exists(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/request', {
    #         'institute_id': self.institute["id"], 'new_owner_email': 'ahmad3@yahoo.com'})
    #     self.assertEqual(response_data['message'], 'We cant find this user!')

    # def test_transfer_ownership_new_owner_equals_to_current_user(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/request', {
    #         'institute_id': self.institute["id"], 'new_owner_email': self.user.email})
    #     self.assertEqual(response_data['message'], 'You cant enter your email.')

    # def test_transfer_ownership_active_transfer_exists(self):
    #     self.transfer = TransferOwnershipHistory.objects.create(
    #         institute_id=self.institute["id"], old_owner=self.user, new_owner=self.second_user)
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/request', {
    #         'institute_id': self.institute["id"], 'new_owner_email': self.second_user.email})
    #     self.assertEqual(response_data['message'], 'There is an active transfer ownership request for this institute!')
    #     self.transfer.delete()

    # def test_transfer_ownership_successful_response(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/request', {
    #         'institute_id': self.institute["id"], 'new_owner_email': self.second_user.email})
    #     self.assertEqual(response_data['message'], 'Successful')

    #     self.instituteHelper.check_transfer_state(False, False, self.institute["id"])

    # def test_transfer_ownership_successful_response_with_uppercase_email(self):
    #     # uppercase email
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/request', {
    #         'institute_id': self.institute["id"], 'new_owner_email': self.second_user.email.upper()})
    #     self.assertEqual(response_data['message'], 'Successful')

    #     self.instituteHelper.check_transfer_state(False, False, self.institute["id"])

    # def test_transfer_ownership_token_error_response(self):
    #     (response_data, status_code, error_message) = self.post_with_token(
    #         '/institute/transfer/request', {}, self.test_token + 'some123')
    #     self.assertEqual(response_data['message'], 'Authorization failed')

    # def test_transfer_ownership_serializer_error(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/request')
    #     self.assertEqual(response_data['fields']['institute_id'], 'This field is required.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/request',
    #                                                                        {'institute_id': ''})
    #     self.assertEqual(response_data['fields']['institute_id'], 'This field may not be blank.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/request',
    #                                                                        {'institute_id': self.institute["id"]})
    #     self.assertEqual(response_data['fields']['new_owner_email'], 'This field is required.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/request',
    #                                                                        {'institute_id': self.institute["id"],
    #                                                                         'new_owner_email': 'ahmadyahoo.com'})
    #     self.assertEqual(response_data['fields']['new_owner_email'], 'Enter a valid email address')

    # def test_transfer_ooc_transfer_ownership_record_not_exists(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/ooc',
    #                                                                        {'accept_key': 'abcd1234'})
    #     self.assertEqual(response_data['message'], 'Something was wrong.')

    # def test_transfer_ooc_successful_response(self):
    #     self.transfer = TransferOwnershipHistory.objects.create(
    #         institute_id=self.institute["id"], old_owner=self.user, new_owner=self.second_user,
    #         old_owner_accept_key='abcd1234')
    #     (response_data, status_code, error_message) = self.post_with_token(
    #         '/institute/transfer/ooc', {'accept_key': 'abcd1234'})
    #     self.assertEqual(response_data['message'], 'Successful')

    #     self.instituteHelper.check_transfer_state(True, False, self.institute["id"])

    # def test_transfer_ooc_token_error_response(self):
    #     (response_data, status_code, error_message) = self.post_with_token(
    #         '/institute/transfer/ooc', {}, self.test_token + 'some123')
    #     self.assertEqual(response_data['message'], 'Authorization failed')

    # def test_transfer_ooc_serializer_error(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/ooc')
    #     self.assertEqual(response_data['fields']['accept_key'], 'This field is required.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/ooc', {'accept_key': ''})
    #     self.assertEqual(response_data['fields']['accept_key'], 'This field may not be blank.')

    # def test_transfer_noc_transfer_ownership_record_not_exists(self):
    #     self.instituteHelper.transfer_ownership_of_institute_ooc_success(self.institute["id"], self.second_user.id,
    #                                                                      self.second_user.email)

    #     (response_data, status_code, error_message) = self.post_with_token(
    #         '/institute/transfer/noc', {'accept_key': 'abcd1234'})
    #     self.assertEqual(response_data['message'], 'Something was wrong.')

    #     self.instituteHelper.check_transfer_state(True, False, self.institute["id"])

    def test_transfer_noc_successful_response(self):
        self.second_user_access = Access.objects.create(
            user=self.second_user, institute_id=self.institute["id"], roles=[dr.__ROLE_OWNER__])
        self.transfer = TransferOwnershipHistory.objects.create(
            institute_id=self.institute["id"], new_owner=self.user, old_owner=self.second_user,
            new_owner_accept_key='abcd1234')
        # (response_data, status_code, error_message) = self.post_with_token(
        #     '/institute/transfer/noc', {'accept_key': 'abcd1234'})
        # self.assertEqual(
        #     response_data['message'], 'The institute has been transferred to your account.')
        #
        # self.instituteHelper.check_transfer_state(False, True, self.institute["id"])

    def test_transfer_noc_ooc_successful_response(self):
        pass

    # def test_transfer_noc_token_error_response(self):
    #     self.instituteHelper.transfer_ownership_of_institute_ooc_success(self.institute["id"], self.second_user.id,
    #                                                                      self.second_user.email)

    #     (response_data, status_code, error_message) = self.post_with_token(
    #         '/institute/transfer/noc', {}, self.test_token + 'some123')
    #     self.assertEqual(response_data['message'], 'Authorization failed')

    #     self.instituteHelper.check_transfer_state(True, False, self.institute["id"])

    # def test_transfer_noc_serializer_error(self):
    #     self.instituteHelper.transfer_ownership_of_institute_ooc_success(self.institute["id"], self.second_user.id,
    #                                                                      self.second_user.email)

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/noc')
    #     self.assertEqual(response_data['fields']['accept_key'], 'This field is required.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/noc', {'accept_key': ''})
    #     self.assertEqual(response_data['fields']['accept_key'], 'This field may not be blank.')

    #     self.instituteHelper.check_transfer_state(True, False, self.institute["id"])

    # def test_transfer_ownership_cancel_transfer_ownership_record_not_exists(self):
    #     self.instituteHelper.transfer_ownership_of_institute_ooc_success(self.institute["id"], self.second_user.id,
    #                                                                      self.second_user.email)

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/cancel',
    #                                                                        {'institute_id': self.institute["id"],
    #                                                                         'transfer_ownership_id': 'dc5cb7eb-2c27-4021-93b3-ae3835a2df75'})
    #     self.assertEqual(response_data['message'], 'Something was wrong.')

    #     self.instituteHelper.check_transfer_state(True, False, self.institute["id"])

    # def test_transfer_ownership_cancel_error_response(self):
    #     self.transfer = TransferOwnershipHistory.objects.create(
    #         institute_id=self.institute["id"], old_owner=self.user, new_owner=self.second_user,
    #         new_owner_accept_at=timezone.now())
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/cancel',
    #                                                                        {'institute_id': self.institute["id"],
    #                                                                         'transfer_ownership_id': self.transfer.id})
    #     self.assertEqual(response_data['message'], 'Something was wrong.')

    #     self.instituteHelper.check_transfer_state(False, True, self.institute["id"])

    #     self.transfer.delete()

    # def test_transfer_ownership_cancel_successful_response(self):
    #     self.transfer = TransferOwnershipHistory.objects.create(
    #         institute_id=self.institute["id"], old_owner=self.user, new_owner=self.second_user)
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/cancel',
    #                                                                        {'institute_id': self.institute["id"],
    #                                                                         'transfer_ownership_id': self.transfer.id})
    #     self.assertEqual(response_data['message'], 'Transfer canceled.')

    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.transferState, {
    #         'institute_id': self.institute["id"]})
    #     self.assertEqual(response_data['message'], 'Successful', error_message)
    #     self.assertEqual(response_data['data'], None, error_message)

    # def test_transfer_ownership_cancel_token_error_response(self):
    #     (response_data, status_code, error_message) = self.post_with_token(
    #         '/institute/transfer/cancel', {}, self.test_token + 'some123')
    #     self.assertEqual(response_data['message'], 'Authorization failed')

    # def test_transfer_ownership_cancel_serializer_error(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/cancel')
    #     self.assertEqual(response_data['fields']['institute_id'], 'This field is required.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/cancel',
    #                                                                        {'institute_id': ''})
    #     self.assertEqual(response_data['fields']['institute_id'], 'This field may not be blank.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/cancel',
    #                                                                        {'institute_id': self.institute["id"]})
    #     self.assertEqual(response_data['fields']['transfer_ownership_id'], 'This field is required.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/cancel',
    #                                                                        {'institute_id': self.institute["id"],
    #                                                                         'transfer_ownership_id': ''})
    #     self.assertEqual(response_data['fields']['transfer_ownership_id'], 'This field may not be blank.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/cancel',
    #                                                                        {'institute_id': self.institute["id"],
    #                                                                         'transfer_ownership_id': '1234'})
    #     self.assertEqual(response_data['fields']['transfer_ownership_id'], 'Enter a valid id')

    # def test_transfer_ownership_email_check_new_owner_not_exists(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/email_check', {
    #         'institute_id': self.institute["id"], 'new_owner_email': 'ahmad3@yahoo.com'})
    #     self.assertEqual(response_data['message'], 'We cant find this user')

    # def test_transfer_ownership_email_check_new_owner_is_current_user(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/email_check', {
    #         'institute_id': self.institute["id"], 'new_owner_email': self.user.email})
    #     self.assertEqual(response_data['message'], 'You cant enter your email')

    # def test_transfer_ownership_email_check_successful_response(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/email_check', {
    #         'institute_id': self.institute["id"], 'new_owner_email': self.second_user.email})
    #     self.assertEqual(response_data['message'], 'Successful')

    # def test_transfer_ownership_email_check_successful_response_with_uppercase_email(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/email_check', {
    #         'institute_id': self.institute["id"], 'new_owner_email': self.second_user.email.upper()})
    #     self.assertEqual(response_data['message'], 'Successful')

    # def test_transfer_ownership_email_check_token_error_response(self):
    #     (response_data, status_code, error_message) = self.post_with_token(
    #         '/institute/transfer/email_check', {}, self.test_token + 'some123')
    #     self.assertEqual(response_data['message'], 'Authorization failed')

    # def test_transfer_ownership_email_check_serializer_error(self):
    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/email_check')
    #     self.assertEqual(response_data['fields']['institute_id'], 'This field is required.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/email_check',
    #                                                                        {'institute_id': ''})
    #     self.assertEqual(response_data['fields']['institute_id'], 'This field may not be blank.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/email_check',
    #                                                                        {'institute_id': self.institute["id"]})
    #     self.assertEqual(response_data['fields']['new_owner_email'], 'This field is required.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/email_check',
    #                                                                        {'institute_id': self.institute["id"],
    #                                                                         'new_owner_email': ''})
    #     self.assertEqual(response_data['fields']['new_owner_email'], 'This field may not be blank.')

    #     (response_data, status_code, error_message) = self.post_with_token('/institute/transfer/email_check',
    #                                                                        {'institute_id': self.institute["id"],
    #                                                                         'new_owner_email': 'ahmadyahoo.com'})
    #     self.assertEqual(response_data['fields']['new_owner_email'], 'Enter a valid email address')

    def test_get_institute_successful_response(self):
        self.user_access = Access.objects.create(user=self.second_user, institute_id=self.institute["id"], roles=[dr.__ROLE_SUPER_ADMIN__])
        (response_data, status_code, error_message) = self.post_with_token(
            '/institute/get', {'institute_id': self.institute["id"]}, test_token=self.second_user_token)
        self.assertEqual(response_data['message'], 'Successful', error_message)

    def test_get_institute_token_error_response(self):
        (response_data, status_code, error_message) = self.post_with_token(
            '/institute/get', {}, self.test_token + 'some123')
        self.assertIn('Authorization failed', response_data['message'], error_message)

    def test_get_institute_serializer_error(self):
        (response_data, status_code, error_message) = self.post_with_token('/institute/get')
        self.assertEqual(response_data['fields']['institute_id'], 'This field is required.', error_message)

        (response_data, status_code, error_message) = self.post_with_token('/institute/get',
                                                                           {'institute_id': ''})
        self.assertEqual(response_data['fields']['institute_id'], 'This field may not be blank.', error_message)

    def test_cleanup_expired_transfer_ownership_function(self):
        institute = Institute.objects.get(id=self.institute['id'])
        for i in range(5):
            TransferOwnershipHistory.objects.create(institute=institute, old_owner=self.user, new_owner=self.second_user,
                                                    new_owner_accept_at=timezone.now() - timedelta(
                                                        days=conf.transfer_ownership_cleanup_offset_days + 1))
        TransferOwnershipHistory.objects.create(institute=institute, old_owner=self.user, new_owner=self.second_user)
        TransferOwnershipHistory.cleanup_expired_transfer_ownership()
        self.assertEqual(1, TransferOwnershipHistory.objects.count())
#TODO skip
    # def test_transfer_ownership_too_many_unfinished_requests(self):
    #     institute = Institute.objects.get(id=self.institute['id'])
    #     for i in range(conf.max_number_of_not_completed_transfer_ownership_requests_per_user):
    #         test_institute = Institute.objects.create(name=str(i), user=self.user)
    #         TransferOwnershipHistory.objects.create(institute=test_institute, old_owner=self.user, new_owner=self.second_user)

    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.transferRequest,
    #                                                                        {'institute_id': self.institute['id'],
    #                                                                         'new_owner_email': self.second_user.email})
    #     self.assertEqual('error', response_data['status'], error_message)
    #     self.assertEqual('Too many unfinished requests!', response_data['message'], error_message)

    def test_add_some_collaborators_to_a_institute_then_transfer_the_ownership_and_then_test_that_collaborators_can_access_the_institute(
            self):
        (self.third_user, self.third_user_token) = self.authenticateHelper.new_user_with_email()
        # add second_user to institute as admin
        (response_data, status_code, error_message) = self.post_with_token('/collaborator/invite', {'institute_id': self.institute['id'],
                                                                                                    'email': self.second_user.email,
                                                                                                    'roles': '["__ROLE_ADMIN__"]'},
                                                                           test_token=self.token)
        self.assertEqual('ok', response_data['status'], error_message)
        # invite_access_record = InviteAccess.objects.get(id=response_data['access']['id'])
        # (response_data, status_code, error_message) = self.post_with_token('/collaborator/invitation/accept',
        #                                                                    test_token=self.second_user_token)
        # self.assertEqual('ok', response_data['status'], error_message)
        # add third_user to institute as admin
        (response_data, status_code, error_message) = self.post_with_token('/collaborator/invite', {'institute_id': self.institute['id'],
                                                                                                    'email': self.third_user.email,
                                                                                                    'roles': '["__ROLE_ADMIN__"]'},
                                                                           test_token=self.token)
        self.assertEqual('ok', response_data['status'], error_message)
        invite_access_record = InviteAccess.objects.get(id=response_data['access']['id'])
        # key = invite_access_record.key
        # (response_data, status_code, error_message) = self.post_with_token('/collaborator/invitation/accept',
        #                                                                    test_token=self.third_user_token)
        # self.assertEqual('ok', response_data['status'], error_message)
        # # transfer the ownership of institute
        # self.instituteHelper.transfer_ownership_of_institute(self.institute['id'], self.second_user.id, self.second_user.email,
        #                                                      self.second_user_token)

    def test_institute_pre_save_signal(self):
        pid = self.instituteHelper.create_institute("second_user_institute", token=self.second_user_token)["id"]

        second_user_institute = Institute.objects.get(id=pid)
        access = Access.objects.create(user=self.user, institute=second_user_institute, roles=[dr.__ROLE_SUPER_ADMIN__])

        # settings.MY_LOG_QUERIES = True
        # why each line initiates another query????
        # second_user_institute = Institute.objects.filter(id=id)[0:10]
        # print("here2")
        # print(second_user_institute)
        # print(second_user_institute[0])
        # a = second_user_institute[0].name
        # print(a)
        # settings.MY_LOG_QUERIES = False

        # in these tests I want to test different situations when name is loaded from database and then changed and another situation when
        # name is not loaded from database but has been set in the local object

        # change the name when the old name has been read from database
        second_user_institute = Institute.objects.get(id=pid)
        # these asserts are in case Django changes the functionality of deferred items
        self.assertNotIn('name', second_user_institute.get_deferred_fields())
        self.assertEqual(False, second_user_institute.tracker.has_changed('name'))
        second_user_institute.name = "name1"
        self.assertNotIn('name', second_user_institute.get_deferred_fields())
        self.assertEqual(True, second_user_institute.tracker.has_changed('name'))
        second_user_institute.save()
        self.assertEqual(False, second_user_institute.tracker.has_changed('name'))

        access = Access.objects.get(user=self.user, institute=second_user_institute)

        # change the name when the old name has *not* been read from database
        # 'only' vs 'values_list'
        # with 'only', you can still lazy_load other values but with 'values_list', the lazy_load won't work
        second_user_institute = Institute.objects.only('id').get(id=pid)
        # in this case, name is not loaded
        self.assertIn('name', second_user_institute.get_deferred_fields())
        self.assertEqual(False, second_user_institute.tracker.has_changed('name'))
        second_user_institute.name = "name2"
        # this unique name is wrong but the code #498258354 should fix this
        self.assertNotIn('name', second_user_institute.get_deferred_fields())
        self.assertEqual(True, second_user_institute.tracker.has_changed('name'))
        second_user_institute.save()
        self.assertEqual(False, second_user_institute.tracker.has_changed('name'))

        access = Access.objects.get(user=self.user, institute=second_user_institute)

    # def test_payment_required_check_for_create_institute_by_user(self):
    #     max_institutes_per_user = 3
    #     Environment.objects.update(default_max_institutes_per_user=max_institutes_per_user)
    #     for item in range(max_institutes_per_user - 1):
    #         self.instituteHelper.create_institute()
    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.createInstituteURL, {'name': 'some'})
    #     self.assertEqual(status_code, 402)
    #     self.assertEqual(response_data['message'], 'Payment Required')

    # def test_payment_required_check_for_transfer_ownership_of_a_institute(self):
    #     (user2, user2_token) = self.authenticateHelper.new_user_with_email()
    #     max_institutes_per_user = 3
    #     Environment.objects.update(default_max_institutes_per_user=max_institutes_per_user)
    #     for item in range(max_institutes_per_user - 1):
    #         self.instituteHelper.create_institute(token=user2_token)

    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.transferRequest,
    #                                                                        {'institute_id': self.institute['id'],
    #                                                                         'new_owner_email': user2.email})
    #     self.assertEqual('Successful', response_data['message'], error_message)
    #     old_owner_accept_key = TransferOwnershipHistory.objects.filter(new_owner=user2)[0].old_owner_accept_key
    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.transferOldOwnerConfirm,
    #                                                                        {'accept_key': old_owner_accept_key})
    #     self.assertEqual('Successful', response_data['message'], error_message)

    #     new_owner_accept_key = TransferOwnershipHistory.objects.filter(new_owner=user2)[0].new_owner_accept_key
    #     (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.transferNewOwnerConfirm,
    #                                                                        {'accept_key': new_owner_accept_key}, test_token=user2_token)
    #     self.assertEqual(status_code, 402)
    #     self.assertEqual(response_data['message'], 'Payment Required')

    def test_transfer_ownership_of_a_institute_which_we_do_not_have_the_necessary_permission(self):
        (self.third_user, self.third_user_token) = self.authenticateHelper.new_user_with_email()
        # add second_user to institute as admin
        (response_data, status_code, error_message) = self.post_with_token('/collaborator/invite', {'institute_id': self.institute['id'],
                                                                                                    'email': self.second_user.email,
                                                                                                    'roles': '["__ROLE_ADMIN__"]'},
                                                                           test_token=self.token)
        self.assertEqual('ok', response_data['status'], error_message)
        invite_access_record = InviteAccess.objects.get(id=response_data['access']['id'])
        # key = invite_access_record.key
        # (response_data, status_code, error_message) = self.post_with_token('/collaborator/invitation/accept', {'key': key},
        #                                                                    test_token=self.second_user_token)
        # self.assertEqual('ok', response_data['status'], error_message)
        # # now, second_user try to transfer the ownership of institute to third_user
        # (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.transferRequest,
        #                                                                    {'institute_id': self.institute['id'],
        #                                                                     'new_owner_email': self.third_user.email},
        #                                                                    test_token=self.second_user_token)
        # self.assertEqual('Forbidden', response_data['message'], error_message)

    def test_generate_api_key(self):
        # success
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.generate_APIKey_url, {
            'institute_id': self.institute['id'],
            'roles': '["__ROLE_ADMIN__"]',
            'expire_at': datetime.now() + timedelta(days=30)
        })
        self.assertEqual('ok', response_data['status'], error_message)

        # invalid token
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.generate_APIKey_url, {
            'institute_id': self.institute['id'],
            'roles': '["__ROLE_ADMIN__"]',
            'expire_at': datetime.now() + timedelta(days=30)
        }, test_token=self.expired_token)
        self.assertEqual('error', response_data['status'], error_message)
        self.assertIn('Authorization failed', response_data['message'], error_message)

        # serializer error: invalid institute_id
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.generate_APIKey_url, {
            'institute_id': '',
            'roles': '["__ROLE_ADMIN__"]',
            'expire_at': datetime.now() + timedelta(days=30)
        })
        self.assertEqual('validation_error', response_data['status'], error_message)
        # serializer error: invalid roles
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.generate_APIKey_url, {
            'institute_id': self.institute['id'],
            'roles': '["__ROLE_OWNER__"]',
            'expire_at': datetime.now() + timedelta(days=30)
        })
        self.assertEqual('validation_error', response_data['status'], error_message)
        # serializer error: invalid expire_at
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.generate_APIKey_url, {
            'institute_id': self.institute['id'],
            'roles': '["__ROLE_ADMIN__"]',
            'expire_at': '2021-5-01'
        })
        self.assertEqual('validation_error', response_data['status'], error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.generate_APIKey_url, {
            'institute_id': self.institute['id'],
            'roles': '["__ROLE_ADMIN__"]',
            'expire_at': '2021-05-01'
        })
        self.assertEqual('ok', response_data['status'], error_message)
    def test_api_keys_list(self):
        # success
        for i in range(3):
            self.instituteHelper.generate_api_key(self.institute['id'])
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.APIKeys_list_url, {
            'institute_id': self.institute['id']
        })
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual(3, len(response_data['data']['api_keys']), error_message)

        # invalid token
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.APIKeys_list_url, {
            'institute_id': self.institute['id']
        }, test_token=self.expired_token)
        self.assertIn('Authorization failed', response_data['message'], error_message)

        # invalid institute_id
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.APIKeys_list_url, {
            'institute_id': '72abf60e-7ee7-4d62-a0cd-4b00779d4f41'
        })
        self.assertEqual('Forbidden', response_data['message'], error_message)

        # serializer error
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.APIKeys_list_url, {
            'institute_id': ''
        })
        self.assertEqual('validation_error', response_data['status'], error_message)

    def test_delete_api_key(self):
        api_key = self.instituteHelper.generate_api_key(self.institute['id'])
        api_key_record = APIKey.objects.get(api_key=api_key)
        # Success
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.delete_APIKey_url, {
            'api_key_id': api_key_record.id,
        })
        self.assertEqual('ok', response_data['status'], error_message)

        # Authorization failed
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.delete_APIKey_url, {
            'api_key_id': api_key_record.id,
        }, test_token=self.expired_token)
        self.assertEqual('error', response_data['status'], error_message)
        self.assertIn('Authorization failed', response_data['message'], error_message)

        # serializer error
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.delete_APIKey_url, {
            'api_key_id': '',
        })
        self.assertEqual('validation_error', response_data['status'], error_message)

    def test_get_token_from_api_key(self):
        api_key = self.instituteHelper.generate_api_key(self.institute['id'])

        # Success
        (response_data, status_code, error_message) = self.post_without_token(self.instituteHelper.get_token_from_APIKey_url, {
            'api_key': api_key,
        })
        self.assertEqual('ok', response_data['status'], error_message)

        # Authorization failed
        (response_data, status_code, error_message) = self.post_without_token(self.instituteHelper.get_token_from_APIKey_url, {
            'api_key': 'api_key',
        })
        self.assertEqual('error', response_data['status'], error_message)
        self.assertIn('Authorization failed', response_data['message'], error_message)

    def test_free_user_create_institute(self):
        # TODO test these situations using UserPlan too
        Environment.objects.update(default_max_institutes_per_user=0)
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.createInstituteURL,
                                                                           {'name': 'my_institute'})
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('Payment Required', response_data['message'], error_message)

    def test_generate_api_key_with_sandbox_institute(self):
        sandbox_institute = Institute.objects.get(name='sandbox', user=self.user)
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.generate_APIKey_url, {
            'institute_id': sandbox_institute.id,
            'roles': '["__ROLE_ADMIN__"]',
            'expire_at': datetime.now() + timedelta(days=30)
        })
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('You can not generate APIKeys for a sandbox institute', response_data['message'], error_message)

    def test_get_api_keys_list_with_sandbox_institute(self):
        sandbox_institute = Institute.objects.get(name='sandbox', user=self.user)
        (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.APIKeys_list_url, {
            'institute_id': sandbox_institute.id
        })
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('You can not get APIKeys list for a sandbox institute', response_data['message'], error_message)

    def test_set_and_get_and_list_institute_student_success(self):
        api_key = self.instituteHelper.generate_api_key(self.institute['id'])
        referer_institute_student_identity = "12345"

        # without any optional data
        (response_data, status_code, error_message) = self.post_without_token(self.instituteHelper.set_institute_student, {
            'api_key': api_key,
            'referer_institute_student_identity': referer_institute_student_identity
        })
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(referer_institute_student_identity,
                         response_data['data']['institute_student']['referer_institute_student_identity'], error_message)
        self.assertIsNone(response_data['data']['institute_student']['first_name'], error_message)

        # with first_name
        first_name = 'haroon'
        (response_data, status_code, error_message) = self.post_without_token(self.instituteHelper.set_institute_student, {
            'api_key': api_key,
            'referer_institute_student_identity': referer_institute_student_identity,
            'first_name': first_name
        })
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(referer_institute_student_identity,
                         response_data['data']['institute_student']['referer_institute_student_identity'], error_message)
        self.assertEqual(first_name, response_data['data']['institute_student']['first_name'], error_message)

        # TODO test last_name, email, phone, info
        # TODO test info bad usage

        # testing get API
        (response_data, status_code, error_message) = self.post_without_token(self.instituteHelper.get_institute_student, {
            'api_key': api_key,
            'referer_institute_student_identity': referer_institute_student_identity,
        })
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(referer_institute_student_identity,
                         response_data['data']['institute_student']['referer_institute_student_identity'], error_message)
        self.assertEqual(first_name, response_data['data']['institute_student']['first_name'], error_message)

        # testing list API
        (response_data, status_code, error_message) = self.post_without_token(self.instituteHelper.list_institute_student, {
            'api_key': api_key,
            'skip': 0,
            'take': 10,
            'sort_by': 'first_name_asc'
        })
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(1, len(response_data['data']['institute_students']), error_message)

    def test_set_and_get_and_list_institute_student_serializer_error(self):
        api_key = self.instituteHelper.generate_api_key(self.institute['id'])
        referer_institute_student_identity = "12345"

        # testing get API
        (response_data, status_code, error_message) = self.post_without_token(self.instituteHelper.get_institute_student, {
            'api_key': api_key,
            'referer_institute_student_identity': referer_institute_student_identity,
            'wikiazma_institute_student_id': 'ss'
        })
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Some fields are not valid', response_data['message'], error_message)
        self.assertEqual('One of wikiazma_institute_student_id and referer_institute_student_identity is required.',
                         response_data['fields']['non_field_errors'], error_message)
        (response_data, status_code, error_message) = self.post_without_token(self.instituteHelper.get_institute_student, {
            'api_key': api_key,
            'wikiazma_institute_student_id': '72abf60e-7ee7-4d62-a0cd-4b00779d4f41'
        })
        self.assertEqual(404, status_code, error_message)
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('Institute Student not found', response_data['message'], error_message)

        (response_data, status_code, error_message) = self.post_without_token(self.instituteHelper.get_institute_student, {
            'api_key': api_key,
        })
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('either wikiazma_institute_student_id or referer_institute_student_identity should be provided', response_data['message'], error_message)
    def test_set_and_get_and_list_institute_student_error(self):
        api_key = self.instituteHelper.generate_api_key(self.institute['id'])
        referer_institute_student_identity = "12345"

        # testing get API
        (response_data, status_code, error_message) = self.post_without_token(self.instituteHelper.get_institute_student, {
            'api_key': api_key,
            'referer_institute_student_identity': referer_institute_student_identity,
        })
        self.assertEqual(404, status_code, error_message)
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('Institute Student not found', response_data['message'], error_message)
    
        
    def test_instituste_balance(self):
            (response_data, status_code, error_message) = self.post_with_token(self.instituteHelper.institute_balance,{"institute_id":self.institute['id']})
            
            
            self.assertEqual('ok', response_data['status'], error_message)
            self.assertEqual('Successful', response_data['message'], error_message)