import json

from question_bank.models import QuestionBank


class QuestionBankTestHelper:
    create_question_bank_url = "/question_bank/create"
    edit_question_bank_url = "/question_bank/edit"
    edit_question_bank_filters_url = "/question_bank/edit_filters"
    archive_question_bank_url = "/question_bank/archive"
    get = "/question_bank/get"
    question_bank_list_url = "/question_bank/list"
    bookmark_url = '/question_bank/public/bookmark'
    list_bookmark_url = '/question_bank/bookmark/list'
    question_bank_market_place_url = '/question_bank/market_place'
    question_bank_pick_url = '/question_bank/pick'
    unsubscribe_url = '/question_bank/unsubscribe'
    tag_list = '/question_bank/tag_list'
    tag_key_suggestion_url = '/question_bank/tag_key_list'
    tag_value_suggestion_url = '/question_bank/tag_value_list'

    def __init__(self, tester):
        self.tester = tester

    name_index = 0

    def new_name(self):
        self.name_index += 1
        return 'new_name' + str(self.name_index)

    def create_question_bank(self, institute_id, name=None, public=None, description=None, token=None):
        if name is None:
            name = self.new_name()

        request = {'context_institute_id': institute_id, 'name': name}

        if public is not None:
            request['public'] = public

        if description is not None:
            request['description'] = description

        (response_data, status_code, error_message) = self.tester.post_with_token(self.create_question_bank_url,
                                                                                  request, test_token=token)
        self.tester.assertEqual('ok', response_data['status'], error_message)

        return response_data['data']['question_bank']['id']

    def archive_question_bank_helper(self, context_institute_id, question_bank_id):
        (response_data, status_code, error_message) = self.tester.post_with_token(
            self.archive_question_bank_url, {
                'context_institute_id': context_institute_id,
                'question_bank_id': question_bank_id,
            })
        self.tester.assertEqual('ok', response_data['status'], error_message)
        question_bank = QuestionBank.objects.get(id=question_bank_id)
        self.tester.assertEqual(True, question_bank.archived, error_message)

    def create_a_question_bank_with_questions_and_tags(self, institute_id, name=None):
        if name is None:
            name = 'full_question_bank'
        question_bank_id = self.create_question_bank(institute_id, name=name)

        # adding several tags for test
        tags = json.dumps(
            {'subject': 'circles', 'subject2': 'square', 'field': 'math'})
        self.tester.questionHelper.new_question(question_bank_id, tags=tags)

        # we have two 'subject2' and they should be retrieved in alphabetical order
        tags = json.dumps({'subject2': 'zoology'})
        self.tester.questionHelper.new_question(question_bank_id, tags=tags)

        # create 'subject': 'circular matter' 3 times and 'subject2': 'zoology' 2 times
        tags = json.dumps({'subject': 'circular matter'})
        self.tester.questionHelper.new_question(question_bank_id, tags=tags)
        self.tester.questionHelper.new_question(question_bank_id, tags=tags)

        tags = json.dumps(
            {'subject': 'circular matter', 'subject2': 'zoology'})
        self.tester.questionHelper.new_question(question_bank_id, tags=tags)

        # creating a deleted question
        tags = json.dumps(
            {'subject': 'circular matter', 'subject2': 'zoology'})
        response_data, status_code, error_message = self.tester.questionHelper.new_question(
            question_bank_id, tags=tags)
        self.tester.questionHelper.archive_question_helper(
            question_bank_id, response_data['data']['question']['id'])

    def check_key_suggestions(self, request, expected_suggestions,):
        (response_data, status_code, error_message) = self.tester.post_with_token(
            self.tag_key_suggestion_url, request)
        self.tester.assertEqual(status_code, 200, error_message)
        self.tester.assertEqual(
            response_data['message'], 'Successful', error_message)
        self.tester.assertEqual(len(response_data['data']['keys']), len(
            expected_suggestions), error_message)
        for i in range(len(expected_suggestions)):
            self.tester.assertEqual(
                response_data['data']['keys'][i], expected_suggestions[i], error_message)

    def check_value_suggestions(self, request, expected_suggestions):
        (response_data, status_code, error_message) = self.tester.post_with_token(self.tag_value_suggestion_url,
                                                                                  request)
        self.tester.assertEqual(status_code, 200, error_message)
        self.tester.assertEqual(
            response_data['message'], 'Successful', error_message)
        self.tester.assertEqual(len(response_data['data']['values']), len(
            expected_suggestions), error_message)
        for i in range(len(expected_suggestions)):
            self.tester.assertEqual(
                response_data['data']['values'][i], expected_suggestions[i], error_message)

    def bookmark_questions_bank_public_helper(self, question_bank_id, star):
        request = {'question_bank_id': question_bank_id, 'star': star}
        (response_data, status_code, error_message) = self.tester.post_with_token(self.bookmark_url,
                                                                                  request)

        return response_data, status_code, error_message

    def list_bookmark_questions_bank_public_helper(self, skip, take):
        request = {'skip': skip, 'take': take}
        (response_data, status_code, error_message) = self.tester.post_with_token(self.list_bookmark_url,
                                                                                  request)

        return response_data, status_code, error_message

    def market_place_helper(self, skip, take, free_filter, context_institute_id, q=None):
        request = {'skip': skip, 'take': take, 'free_filter': free_filter,
                   'context_institute_id': context_institute_id}
        if q is not None:
            request['q'] = q
        (response_data, status_code, error_message) = self.tester.post_with_token(self.question_bank_market_place_url,
                                                                                  request)

        return response_data, status_code, error_message

    def question_bank_list_helper(self, context_institute_id, skip, take, q=None, archived_filter=None):
        request = {'context_institute_id': context_institute_id, 'archived_filter': 'include',
                   'skip': skip, 'take': take}

        if q is not None:
            request['q'] = q

        if archived_filter is not None:
            request['archived_filter'] = archived_filter

        (response_data, status_code, error_message) = self.tester.post_with_token(self.question_bank_list_url,
                                                                                  request)

        return response_data, status_code, error_message

    def question_bank_pick(self, question_bank_id, context_institute_id):
        request = {"question_bank_id": question_bank_id,
                   "context_institute_id": context_institute_id}

        (response_data, status_code, error_message) = self.tester.post_with_token(self.question_bank_pick_url,
                                                                                  request)

        return response_data, status_code, error_message
