# coding=utf-8
# from _mysql_exceptions import IntegrityError
import datetime
import json

from django.conf import settings
from django.contrib.auth.models import User
from django.db import transaction, IntegrityError
from django.db.models import Q
from gm_types.gaia import PROBLEM_TYPE

from api.tool.user_tool import get_user_from_context
from launch.cache.start_process import StartupProcess
from launch.models import (
    QuestionnaireTheme,
    QuestionnaireQuestion,
    QuestionnaireAnswer,
    QuestionnaireAnswerRelationTag,
    QuestionnaireAnswerRelationTagV3,
    QuestionnaireAnswerInterestQuestion,
    QuestionnaireThemeAndQuestionRelations,
    QuestionnaireQaSubRelations,
    QuestionnaireQuestions,
    QuestionnaireAnswerRelationAttrTag,
)
from rpc.decorators import bind_context
from rpc.exceptions import RPCIntegrityError, RPCNotFoundException
from rpc.tool.dict_mixin import to_dict

uri_pre = 'hera/questionnaire'


@bind_context(uri_pre + '/get_deploy')
def get_button_layout(ctx):
    return StartupProcess.get_start_up_process_deploy()


@bind_context(uri_pre + '/set_deploy')
def set_button_layout(ctx, deploy_info):
    deploy_info = json.dumps(deploy_info)
    StartupProcess.update_app_config(deploy_info)

@bind_context(uri_pre + '/theme_online')
def theme_online(ctx, theme_items):
    """
    处理主题的上下线
    """
    _online = theme_items and (theme_items[0] or {}).get("is_online", False) or False
    theme_ids = map(lambda x: x.get("key", 0), theme_items)

    _now = datetime.datetime.now()
    base_update_info = {
        "update_time": _now,
        "last_modified": _now,
    }
    base_filter_query = Q(pk__in=theme_ids)

    if _online:  # 若是上线的话
        QuestionnaireTheme.objects.filter(is_online=True).update(
            is_online=False, update_time=_now, last_modified=_now
        )  # 先将之前的下线

        update_info = {
            "is_online": True,
        }
        update_info.update(base_update_info)

    else:  # 下线
        update_info = {
            "is_online": False,
        }
        update_info.update(base_update_info)

    QuestionnaireTheme.objects.filter(base_filter_query).update(**update_info)

    return theme_ids


@bind_context(uri_pre + '/edit')
@transaction.atomic
def theme_edit(ctx, theme_id=None, theme_info=None):
    """
    问券主题的编辑
    :param ctx:
    :param theme_id:
    :param theme_info:
    :return:
    """
    user = get_user_from_context(ctx)
    if theme_info is None:
        return None

    if theme_id is None:
        try:
            questionnaire_theme = QuestionnaireTheme.objects.create(
                theme=theme_info.get('theme', ''),
                operator_id=user.id,
                is_online=False,
            )
        except IntegrityError:
            raise RPCIntegrityError
    else:
        try:
            questionnaire_theme = QuestionnaireTheme.objects.get(id=theme_id)
            questionnaire_theme.theme = theme_info.get('theme', '')
            questionnaire_theme.operator_id = user.id
            questionnaire_theme.last_modified = datetime.datetime.now()
            questionnaire_theme.save()
        except:
            raise RPCNotFoundException
    return {'id': questionnaire_theme.id}


@bind_context(uri_pre + '/get')
def theme_detail(ctx, theme_id):
    try:
        questionnaire_theme = QuestionnaireTheme.objects.get(id=theme_id)
    except:
        raise RPCNotFoundException
    theme_data = to_dict(questionnaire_theme)
    theme_questionnaire_questions = QuestionnaireThemeAndQuestionRelations.objects.filter(
        questionnaire_theme_id=theme_id
    ).values('questionnaire_question_id', "can_skip", "rank", "sub_questions_show_nums", "send_message")

    theme_question_rel_infos = {}
    for item in theme_questionnaire_questions:
        theme_question_rel_infos[item["questionnaire_question_id"]] = dict(item)

    topicproblem_list = QuestionnaireQuestions.objects.filter(
        id__in=list(theme_question_rel_infos.keys()),
        is_delete=False
    )
    theme_data['quesiton'] = []
    for t in topicproblem_list:
        _ques_id = t.id
        topicanswer_list = []
        topicanswers = QuestionnaireAnswer.objects.filter(
            questionnaire_question_id=t.id, is_delete=False
        ).order_by('rank')
        for ts in topicanswers:
            questionnaireqasubrelations = QuestionnaireQaSubRelations.objects.filter(
                questionnaire_theme_id=theme_id,
                questionnaire_question_id=_ques_id,
                questionnaire_answer_id=ts.id
            )
            topicanswer_list.append({
                'anwer_id': ts.id,
                'questionnaire_content': ts.questionnaire_content,
                'questionnaire_display_content': ts.questionnaire_display_content,
                'is_ugc': ts.is_ugc,
                'is_force_display': ts.is_force_display,
                'can_skip': questionnaireqasubrelations.first().can_skip if questionnaireqasubrelations.first() else False,
                'is_series_answer': questionnaireqasubrelations.first().is_series_answer if questionnaireqasubrelations.first() else False,
                'weight': questionnaireqasubrelations.first().weight if questionnaireqasubrelations.first() else False,
                'questionnaire_sub_question_ids': list(
                    questionnaireqasubrelations.values_list('questionnaire_sub_question_id', flat=True)),
            })

        theme_question_config_info = theme_question_rel_infos.get(_ques_id, {})
        theme_data['quesiton'].append({
            'id': _ques_id,
            'is_influence_user_portrait': t.is_influence_user_portrait,
            'is_effect': t.is_effect,
            'is_filter_selected_answer': t.is_filter_selected_answer,
            'problem_type': PROBLEM_TYPE.getDesc(t.problem_type),
            'can_skip': theme_question_config_info.get("can_skip", False),
            'send_message': theme_question_config_info.get("send_message", False),
            'rank': theme_question_config_info.get("rank", 999),
            "sub_questions_show_nums": theme_question_config_info.get("sub_questions_show_nums", 0),
            'topicanswer_list': topicanswer_list,
        })
    return theme_data


@bind_context(uri_pre + '/problem/edit')
@transaction.atomic
def problem_edit(ctx,theme_id=None, layout_id=None, layout_info=None):
    user = get_user_from_context(ctx)
    if layout_info is None:
        return None
    floors = json.loads(layout_info.get('related', {}))['floor']
    for floor in floors:  #问题信息
        questionnaire_question_id = int(floor['questionnaire_question_id']) if floor['questionnaire_question_id'] else 0
        relation_question_id = int(floor['relation_question_id']) if floor['relation_question_id'] else 0
        questionnairequestion = QuestionnaireQuestion.objects.filter(id=questionnaire_question_id).first()
        if questionnairequestion:
            questionnairequestion.title = floor['floor_title']
            questionnairequestion.problem_type = int(floor['single_url_type'])
            questionnairequestion.relation_question_id = relation_question_id
            questionnairequestion.rank = floor['floor_order']
            questionnairequestion.is_effect = floor['is_effect']
            questionnairequestion.is_influence_user_portrait = floor['is_influence_user_portrait']
            questionnairequestion.save()
        else:
            questionnairequestion = QuestionnaireQuestion.objects.create(
            questionnaire_theme_id=theme_id,
            title=floor['floor_title'],
            problem_type=int(floor['single_url_type']),
            relation_question_id=relation_question_id,
            rank=floor['floor_order'],
            is_effect=floor['is_effect'],
            is_influence_user_portrait=floor['is_influence_user_portrait'],
        )

        contents = floor['content']
        for content in contents:  #答案信息
            questionnaire_answer_id = int(content['questionnaire_answer_id']) if content['questionnaire_answer_id'] else 0
            questionnaire_answer = QuestionnaireAnswer.objects.filter(id=questionnaire_answer_id).first()
            answer_relation_question_id = int(content['answer_relation_question_id']) if content['answer_relation_question_id'] else 0
            if questionnaire_answer:
                questionnaire_answer.questionnaire_content = content['questionnaire_content']
                questionnaire_answer.questionnaire_image_url = content['questionnaire_image_url']
                questionnaire_answer.answer_create_content = content['answer_create_content']
                questionnaire_answer.answer_create_image_url = content['answer_create_image_url']
                questionnaire_answer.relation_question_id = answer_relation_question_id
                questionnaire_answer.is_ugc = content['is_ugc']
                questionnaire_answer.rank = content['content_order']
                questionnaire_answer.save()
                QuestionnaireAnswerRelationTag.objects.filter(questionnaire_answer=questionnaire_answer).delete()
            else:
                questionnaire_answer = QuestionnaireAnswer.objects.create(
                    questionnaire_question=questionnairequestion,
                    questionnaire_content=content['questionnaire_content'],
                    questionnaire_image_url=content['questionnaire_image_url'],
                    answer_create_content=content['answer_create_content'],
                    answer_create_image_url=content['answer_create_image_url'],
                    relation_question_id=answer_relation_question_id,
                    is_ugc=content['is_ugc'],
                    rank=content['content_order'],
                )
            tag_ids = content['tag_ids']
            if tag_ids:
                for tag in tag_ids:
                    QuestionnaireAnswerRelationTag.objects.get_or_create(
                        questionnaire_answer=questionnaire_answer,
                        tag_id=tag,
                    )
    q = QuestionnaireTheme.objects.get(id=theme_id)
    q.operator_id = user.id
    q.last_modified = datetime.datetime.now()
    q.save()
    return {
        'code': 1,
        'message': u'修改成功！'
    }


@bind_context(uri_pre + '/problem/delete')
@transaction.atomic
def problem_delete(ctx, theme_id=None, relation_question_id=None):
    """
    删除问题信息
    :param ctx:
    :param questionnaire_theme_id:
    :param theme_id:
    :return:
    """
    questionnaireqasubrelations = QuestionnaireQaSubRelations.objects.filter(questionnaire_theme_id=theme_id, questionnaire_question_id=relation_question_id)
    if questionnaireqasubrelations:
        questionnaireqasubrelations.delete()
    QuestionnaireThemeAndQuestionRelations.objects.filter(questionnaire_theme_id=theme_id, questionnaire_question_id=relation_question_id).delete()

    return []


@bind_context(uri_pre + '/problem_answer/delete')
@transaction.atomic
def delete_answer_by_id(ctx, answer_id):
    """
    答案删除
    :param ctx:
    :param answer_id:
    :return:
    """
    result = {
        'error': 0,
        'message': '',
        'data': '',
    }
    if not answer_id or not answer_id.isdigit():
        return result
    QuestionnaireAnswerRelationTag.objects.filter(questionnaire_answer_id=int(answer_id)).delete()
    QuestionnaireQaSubRelations.objects.filter(questionnaire_answer_id=int(answer_id)).delete()

    QuestionnaireAnswer.objects.filter(id=int(answer_id)).update(is_delete=True)

    return result


@bind_context(uri_pre + '/problem_answer/edit')
# @transaction.atomic
def question_answer_edit(ctx, question_id, edit_data, new_data):
    """
    回答编辑
    :param ctx:
    :param question_id:
    :param edit_data:
    :param new_data:
    :return:
    """
    result = {
        'error': 0,
        'message': '',
        'data': '',
    }
    if not any([edit_data, new_data]):
        return result

    def update_questionnaire_answer_relation_datas(relation_model, item_id, relation_ids, param_id):
        if not isinstance(relation_ids, list):
            return

        old_relation_ids = set(relation_model.objects.filter(**{
            "questionnaire_answer_id": item_id
        }).values_list(param_id, flat=True))

        if old_relation_ids - set(relation_ids):
            relation_model.objects.filter(**{
                "questionnaire_answer_id": item_id,
                "{}__in".format(param_id): old_relation_ids - set(relation_ids)
            }).delete()

        for relation_id in set(relation_ids) - old_relation_ids:
            relation_model.objects.get_or_create(**{
                "questionnaire_answer_id": item_id,
                param_id: relation_id
            })

    related_tags, related_tags_v3, related_attrtags, interest_questions = [], [], [], []
    for item in new_data:
        answer = QuestionnaireAnswer.objects.create(
            questionnaire_question_id=question_id,
            questionnaire_content=item.get('questionnaire_content'),
            questionnaire_display_content=item.get('questionnaire_display_content'),
            questionnaire_image_url=item.get('questionnaire_image_url'),
            answer_create_content=item.get('answer_create_content'),
            answer_create_image_url=item.get('answer_create_image_url'),
            relation_question_id=item.get('relation_question_id') or 0,
            is_ugc=item.get('is_ugc'),
            is_force_display=item.get('is_force_display'),
            rank=item.get('rank'),
        )
        _answer_id = answer.id
        for _id in list(map(int, item.get('answer_related_tags') or [])):
            related_tags.append(
                QuestionnaireAnswerRelationTag(
                    questionnaire_answer_id=_answer_id,
                    tag_id=_id,
                ))

        for tag_v3_id in list(map(int, item.get("answer_related_tags_v3") or [])):
            related_tags_v3.append(QuestionnaireAnswerRelationTagV3(
                questionnaire_answer_id=_answer_id,
                tag_v3_id=tag_v3_id
            ))

        # for attr_tag_id in list(map(int, item.get("answer_related_attrtags") or [])):
        #     related_attrtags.append(QuestionnaireAnswerRelationAttrTag(
        #         questionnaire_answer_id=_answer_id,
        #         attr_tag_id=attr_tag_id
        #     ))

        for interest_question_id in list(map(int, item.get("interest_question_ids") or [])):
            interest_questions.append(QuestionnaireAnswerInterestQuestion(
                questionnaire_answer_id=_answer_id,
                question_id=interest_question_id
            ))

    QuestionnaireAnswerRelationTag.objects.bulk_create(related_tags)
    QuestionnaireAnswerRelationTagV3.objects.bulk_create(related_tags_v3)
    # QuestionnaireAnswerInterestQuestion.objects.bulk_create(related_attrtags)
    QuestionnaireAnswerInterestQuestion.objects.bulk_create(interest_questions)

    for item in edit_data:
        answer_id = int(item.pop('answer_id', 0))
        new_related_tags = item.pop('answer_related_tags', []) or []
        new_related_tags_v3 = item.pop('answer_related_tags_v3', []) or []
        # answer_related_attrtags = item.pop('answer_related_attrtags', []) or []
        new_interest_question_ids = item.pop('interest_question_ids', []) or []
        item['questionnaire_question_id'] = question_id
        try:
            answer = QuestionnaireAnswer.objects.get(id=answer_id)
        except QuestionnaireAnswer.DoesNotExist:
            continue
        for k, v in item.items():
            setattr(answer, k, v)
        answer.save()

        update_questionnaire_answer_relation_datas(
            relation_model=QuestionnaireAnswerRelationTag,
            item_id=answer_id,
            relation_ids=new_related_tags,
            param_id="tag_id"
        )
        update_questionnaire_answer_relation_datas(
            relation_model=QuestionnaireAnswerRelationTagV3,
            item_id=answer_id,
            relation_ids=new_related_tags_v3,
            param_id="tag_v3_id"
        )
        # 3.0标签 属性类
        # update_questionnaire_answer_relation_datas(
        #     relation_model=QuestionnaireAnswerRelationAttrTag,
        #     item_id=answer_id,
        #     relation_ids=answer_related_attrtags,
        #     param_id="attr_tag_id"
        # )
        update_questionnaire_answer_relation_datas(
            relation_model=QuestionnaireAnswerInterestQuestion,
            item_id=answer_id,
            relation_ids=new_interest_question_ids,
            param_id="question_id"
        )

    return result


@bind_context(uri_pre + '/problem/get')
def questionnaire_problem_get(ctx, questionnaire_id):
    """
    获取问题
    :param questionnaire_id:
    :return:
    """
    result = {}
    if not questionnaire_id or not questionnaire_id.isdigit():
        return result

    def convert_data(map_items):
        convert_dic = {}

        for item_id, questionnaire_answer_id in map_items:
            if questionnaire_answer_id not in convert_dic:
                convert_dic[questionnaire_answer_id] = []

            convert_dic[questionnaire_answer_id].append(item_id)

        return convert_dic

    try:
        questionnaire = QuestionnaireQuestions.objects.get(id=int(questionnaire_id))
    except QuestionnaireQuestions.DoesNotExist:
        return result
    answers = QuestionnaireAnswer.objects.filter(
        questionnaire_question_id=questionnaire_id, is_delete=False
    )
    _answer_ids = [ans.id for ans in answers]
    ans_tags_v1 = QuestionnaireAnswerRelationTag.objects.filter(
        questionnaire_answer_id__in=_answer_ids
    ).values_list('tag_id', "questionnaire_answer_id")
    v1_ans_tags_dic = convert_data(ans_tags_v1)

    ans_tags_v3 = QuestionnaireAnswerRelationTagV3.objects.filter(
        questionnaire_answer_id__in=_answer_ids
    ).values_list("tag_v3_id", "questionnaire_answer_id")
    v3_ans_tags_dic = convert_data(ans_tags_v3)

    # 标签 3.0 属性标签 去除
    # ans_attrtags = QuestionnaireAnswerRelationAttrTag.objects.filter(
    #     questionnaire_answer_id__in=_answer_ids
    # ).values_list("attr_tag_id", "questionnaire_answer_id")
    # attrtags_dict = convert_data(ans_attrtags)

    interest_questions = QuestionnaireAnswerInterestQuestion.objects.filter(
        questionnaire_answer_id__in=_answer_ids
    ).values_list("question_id", "questionnaire_answer_id")
    interest_questions_dic = convert_data(interest_questions)

    related_answers = []
    for answer in answers:
        _id = answer.id
        related_answers.append({
            'answer_id': _id,
            'rank': answer.rank,
            'is_force_display': answer.is_force_display,
            'questionnaire_content': answer.questionnaire_content,
            'questionnaire_display_content': answer.questionnaire_display_content,
            'questionnaire_image_url': answer.questionnaire_image_url,
            'answer_related_tags': v1_ans_tags_dic.get(_id, []),
            'answer_related_tags_v3': v3_ans_tags_dic.get(_id, []),
            # 'answer_related_attrtags': attrtags_dict.get(_id, []),
            "interest_question_ids": interest_questions_dic.get(_id, []),
            'relation_question_id': answer.relation_question_id,
            'answer_create_image_url': answer.answer_create_image_url,
            'answer_create_content': answer.answer_create_content,
            'is_ugc': answer.is_ugc,
        })
    return {
        'problem_type': questionnaire.problem_type,
        'title': questionnaire.title,
        'portrait_type': questionnaire.portrait_type,
        'relation_question_id': questionnaire.relation_question_id,
        'is_effect': questionnaire.is_effect,
        'is_influence_user_portrait': questionnaire.is_influence_user_portrait,
        'is_filter_selected_answer': questionnaire.is_filter_selected_answer,
        'related_answers': related_answers,
    }


@bind_context(uri_pre + '/problem/edit_v1')
def questionnaire_problem_deit_v1(ctx, questionnaire_id, data):
    result = {
        'error': 0,
        'message': '',
        'data': '',
    }
    if not any([questionnaire_id, data]):
        return result

    qs_info = {
        'problem_type': data.get('problem_type'),
        'title': data.get('title'),
        'portrait_type': data.get('portrait_type'),
        'relation_question_id': data.get('relation_question_id') or 0,
        'is_effect': data.get('is_effect'),
        'is_influence_user_portrait': data.get('is_influence_user_portrait'),
        'is_filter_selected_answer': data.get('is_filter_selected_answer'),
    }
    if not questionnaire_id:
        questionnaire_answer = QuestionnaireQuestions.objects.create(**qs_info)
    else:
        try:
            questionnaire_answer = QuestionnaireQuestions.objects.get(id=questionnaire_id)
        except QuestionnaireQuestions.DoesNotExist:
            return result
        for k, v in qs_info.items():
            setattr(questionnaire_answer, k, v)
        questionnaire_answer.save()
    result['data'] = questionnaire_answer.id

    return result


@bind_context(uri_pre + "/problem/delete_theme_relation")
def questionnaire_problem_delete_theme_relation(ctx, theme_id, question_id, answer_id):
    """
    删除主题关联的问题及该问题下回答关联的子问题
    :param theme_id:
    :param question_id:
    :param answer_id:
    :return:
    """
    QuestionnaireThemeAndQuestionRelations.objects.filter(
        questionnaire_theme_id=theme_id,
        questionnaire_question_id=question_id
    ).delete()

    QuestionnaireQaSubRelations.objects.filter(
        questionnaire_theme_id=theme_id,
        questionnaire_question_id=question_id,
        questionnaire_answer_id=answer_id
    ).delete()

    return {"error": 0, "message": "删除成功!"}


@bind_context(uri_pre + "/problem/edit_theme_question_relation")
def questionnaire_problem_edit_theme_question_relation(ctx, theme_id, question_id, old_question_id, data):
    """
    主题 问题 关联关系
    :param theme_id:
    :param question_id:
    :param data:
    :return:
    """
    if old_question_id and old_question_id != question_id:
        QuestionnaireQaSubRelations.objects.filter(questionnaire_theme_id=theme_id,
                                                   questionnaire_question_id=old_question_id).delete()
        QuestionnaireThemeAndQuestionRelations.objects.filter(questionnaire_theme_id=theme_id,
                                                              questionnaire_question_id=old_question_id).delete()
    rank = data.get("rank", 999)
    send_message = data.get("send_message", False)
    relation_obj, status = QuestionnaireThemeAndQuestionRelations.objects.update_or_create(
        questionnaire_theme_id=theme_id,
        questionnaire_question_id=question_id,
        defaults={
            "can_skip": False if data.get("can_skip", False) == 'false' else True,
            "rank": rank if rank else 999,
            "sub_questions_show_nums": data.get("sub_questions_show_nums", 0),
            "send_message": send_message,
        }
    )
    result = {
        "error": 0,
        "message": "",
        "data": {"relation_id": relation_obj.id},
    }
    if status:
        result["message"] = u"创建成功!"
    else:
        result["message"] = u"修改成功!"


@bind_context(uri_pre + '/problem/get_answer')
def questionnaire_problem_deit_v1(ctx, theme_id, questionnairequestions_id):
    result = {
        'error': 0,
        'message': '',
        'data': '',
    }
    data = {}
    questionnairequestions = QuestionnaireQuestions.objects.filter(id=questionnairequestions_id).first()
    qtqr = QuestionnaireThemeAndQuestionRelations.objects.filter(questionnaire_theme_id=theme_id,questionnaire_question_id=questionnairequestions_id).first()
    if questionnairequestions:
        data['question'] = {
            'is_influence_user_portrait': questionnairequestions.is_influence_user_portrait,
            'is_effect': questionnairequestions.is_effect,
            'is_filter_selected_answer': questionnairequestions.is_filter_selected_answer,
            'problem_type': PROBLEM_TYPE.getDesc(questionnairequestions.problem_type),
            'can_skip': qtqr.can_skip if qtqr else False,
            'rank': qtqr.rank if qtqr else False,
            'sub_questions_show_nums': qtqr.sub_questions_show_nums if qtqr else 0,
        }
        data['anwer'] = []
        questionnaireanswer = QuestionnaireAnswer.objects.filter(questionnaire_question_id=questionnairequestions_id, is_delete=False)
        for q in questionnaireanswer:
            questionnaireqasubrelations = QuestionnaireQaSubRelations.objects.filter(questionnaire_theme_id=theme_id,questionnaire_question_id=questionnairequestions_id,
                                                   questionnaire_answer_id=q.id)
            questionnaire_sub_question_info = list(QuestionnaireQuestions.objects.filter(
                id__in=list(questionnaireqasubrelations.values_list('questionnaire_sub_question_id', flat=True))
            ).values_list('id','title'))
            data['anwer'].append({
                'anwer_id': q.id,
                'questionnaire_content': q.questionnaire_content,
                'questionnaire_display_content': q.questionnaire_display_content,
                'is_ugc': q.is_ugc,
                'is_force_display': q.is_force_display,
                'can_skip': questionnaireqasubrelations.first().can_skip if questionnaireqasubrelations.first() else False,
                'is_series_answer': questionnaireqasubrelations.first().is_series_answer if questionnaireqasubrelations.first() else False,
                'weight': questionnaireqasubrelations.first().weight if questionnaireqasubrelations.first() else 999,
                'questionnaire_sub_question_info': questionnaire_sub_question_info,
            })
    result['data'] = data

    return result


@bind_context(uri_pre + "/problem_answer/edit_sub_relation")
def questionnaire_problem_edit_sub_relation(ctx, theme_id, question_id, answer_id, data):
    """
    问卷回答下 保存 or 修改 子问题
    :param theme_id:
    :param question_id:
    :param answer_id:
    :param data:
    :return:
    """
    # 子问题没变。则更新权重和是否跳过。 子问题发生改变。则创建 + 更新字段

    new_sub_question_ids = data.get("sub_question_ids") or []
    new_weight = data.get("weight", 999)
    new_can_skip = data.get("can_skip", False)
    new_is_series_answer = data.get("is_series_answer", False)

    sub_qa_relations = QuestionnaireQaSubRelations.objects.filter(
        questionnaire_theme_id=theme_id,
        questionnaire_question_id=question_id,
        questionnaire_answer_id=answer_id
    )

    need_bulk_create = False
    need_del_old_info = False

    if sub_qa_relations.exists():
        sub_question_obj = sub_qa_relations.first()
        raw_weight = sub_question_obj.weight
        raw_can_skip = sub_question_obj.can_skip
        raw_is_series_answer = sub_question_obj.is_series_answer
        raw_questionnaire_sub_question_ids = sub_qa_relations.values_list("questionnaire_sub_question_id", flat=True)

        if set(raw_questionnaire_sub_question_ids) - set(new_sub_question_ids):  # 如果子问题有变更
            need_bulk_create = True
            need_del_old_info = True

        else:
            update_dic = {}
            if raw_weight != new_weight:
                update_dic.update({
                    "weight": new_weight,
                })

            if raw_can_skip != new_can_skip:
                update_dic.update({
                    "can_skip": new_can_skip,
                })

            if raw_is_series_answer != new_is_series_answer:
                update_dic.update({
                    "is_series_answer": new_is_series_answer,
                })

            if update_dic:
                sub_qa_relations.update(**update_dic)

    else:
        need_bulk_create = True

    if need_del_old_info:
        sub_qa_relations.delete()

    if need_bulk_create:
        bulk_list = [QuestionnaireQaSubRelations(
            questionnaire_theme_id=theme_id,
            questionnaire_question_id=question_id,
            questionnaire_answer_id=answer_id,
            questionnaire_sub_question_id=sub_question_id,
            weight=new_weight,
            can_skip=new_can_skip,
            is_series_answer=new_is_series_answer,
        ) for sub_question_id in new_sub_question_ids]

        QuestionnaireQaSubRelations.objects.bulk_create(bulk_list)

    return {
        "error": 0,
        "message": "创建/修改成功!",
    }


@bind_context(uri_pre + '/choices')
def questionnaire_choices(ctx, q='', page=1, num=30, initial=None):
    page = int(page)
    num = int(num)

    if initial is not None:
        if isinstance(initial, (list, tuple)):
            qry = Q(id__in=initial)
        else:
            qry = Q(id=initial)
    else:
        qry = Q(id__contains=q) | Q(title__contains=q)
    query = QuestionnaireQuestions.objects.using(settings.SLAVE_DB_NAME).filter(qry).order_by('id')
    total_count = query.count()
    start_pos = (page - 1) * num
    start_pos = start_pos if start_pos >= 0 else 0
    results = [
        {
            'id': obj.id,
            'text': obj.title,
        } for obj in query[start_pos: start_pos + num]
    ]
    return {'total_count': total_count, 'results': results, 'page': page, 'num': num}

