#!/usr/bin/env python
# -*- coding: utf-8 -*-

# 问卷
from itertools import chain, groupby
from operator import itemgetter
from collections import defaultdict

from django.db.models import Q
from django.conf import settings
from gm_types.gaia import (
    PROBLEM_TYPE,
    PORTRAIT_TYPE,
)

from agile.services import TagV3Service
from rpc.decorators import bind

from launch.models import (
    QuestionnaireQuestions,
    QuestionnaireAnswer,
    QuestionnaireQaSubRelations,
    QuestionnaireAnswerRelationTagV3,
    QuestionnaireAnswerRelationAttrTag,
)
from launch.services import (
    QuestionnaireAnswerService,
    QuestionnaireQuestionService,
)


def answer_rel_sub_questions_data_splicing(questionnaire_question_ids, filter_answer_ids, question_display_nums=3, answer_display_nums=3):
    """
    回答关联的子问题数据拼接
    :param questionnaire_question_ids: 问卷问题id
    :param filter_answer_ids: 需要过滤的回答id
    :param question_display_nums: 问题展示数量
    :param answer_display_nums: 回答展示数量
    :return:
    """
    result = {}
    if not questionnaire_question_ids:
        return result

    need_exclude_ids = set()
    question_info_dic = dict()

    for item in QuestionnaireQuestionService.get_valid_question_info(questionnaire_question_ids):
        question = QuestionnaireQuestionService.format_question(item)
        _id = question.get("id", 0)
        if question.get("is_filter_selected_answer", False):
            need_exclude_ids.add(_id)
        question_info_dic[_id] = question

    if need_exclude_ids:
        need_exclude_names = QuestionnaireAnswerService.get_exclude_names_by_ids(filter_answer_ids)
        exclude_name_answers_dic = QuestionnaireAnswerService.get_questionnaire_answers(
            question_ids=list(need_exclude_ids),
            exclude_names=need_exclude_names,
            display_nums=answer_display_nums
        )
    else:
        exclude_name_answers_dic = {}

    answers_dic = QuestionnaireAnswerService.get_questionnaire_answers(
        question_ids=list(set(question_info_dic.keys()) - need_exclude_ids),
        exclude_names=set(),
        display_nums=answer_display_nums
    )
    answers_dic.update(exclude_name_answers_dic)

    for q_id in questionnaire_question_ids:  # 顺序校验 + 数据格式化
        question_info = question_info_dic.get(q_id, {})
        _answer_list = answers_dic.get(q_id, [])

        if question_info and _answer_list:
            result.update({
                q_id: {
                    "q_id": q_id,
                    "title": question_info.get("title", ""),
                    "classify": question_info.get("problem_type", PROBLEM_TYPE.MULTIPLE_PLANS),
                    "can_skip": question_info.get("can_skip", False),
                    "answers_list": _answer_list,
                },
            })

        if len(result) == question_display_nums:
            break

    return result


@bind("api/launch/get_current_valid_questionnaire")
def get_current_valid_questionnaire(question_ids, answer_ids, theme_id=None, display_answer_nums=9):
    """
    获取当前有效问卷 的 主问题
    :param theme_id: 主题id
    :param question_ids: 问题id列表 (用于去重)
    :param answer_ids: 回答id列表 (用于去重)
    :param display_answer_nums: 回答展示数量
    :return:
    """
    result = {
        "valid_questionnaire": {},  # 有效问卷
        "valid_question_nums": 0,
        "valid_theme_id": 0,
    }
    if not question_ids:
        question_ids = []

    if not theme_id:
        valid_theme_obj = QuestionnaireQuestionService.get_valid_theme_info()
        theme_id = valid_theme_obj and valid_theme_obj.id or 0

        if not theme_id:
            return result

    theme_question_valid_infos = QuestionnaireQuestionService.get_theme_valid_question(
        theme_id=theme_id,
        exclude_question_ids=question_ids
    )
    question = theme_question_valid_infos.get("question_info", {})

    if question:
        _q_id = question.get("id", 0)

        need_exclude_names = set()
        if answer_ids and question.get("is_filter_selected_answer", False):  # 过滤回答内容
            need_exclude_names = QuestionnaireAnswerService.get_exclude_names_by_ids(answer_ids)

        answers_data = QuestionnaireAnswerService.get_questionnaire_answers(
            question_ids=[_q_id, ],
            exclude_names=need_exclude_names,
            display_nums=display_answer_nums
        )

        result.update({
            "valid_theme_id": theme_id,
            "valid_question_nums": theme_question_valid_infos.get("all_valid_question_nums", 0),
            "valid_questionnaire": {
                "q_id": _q_id,
                "title": question.get("title", ""),
                "classify": question.get("problem_type", PROBLEM_TYPE.MULTIPLE_PLANS),
                "can_skip": question.get("can_skip", False),
                "send_message": question.get("send_message", False),
                "answers_list": answers_data.get(_q_id, []),
            },
        })

    return result


@bind("api/launch/get_valid_sub_questionnaire")
def get_valid_sub_questionnaire(theme_id, question_id, main_answer_ids, filter_answer_ids, question_display_nums=3,
                                answer_display_nums=3):
    """
        获取有效的子问题
    :param theme_id: 主题id
    :param question_id: 问题id
    :param main_answer_ids: 主回答ids [] 用户获取子问题
    :param filter_answer_ids: 用户过滤的回答id [] 获取需要过滤的回答内容
    :param question_display_nums: 问题展示的数量
    :param answer_display_nums: 回答展示的数量
    :return:
    """
    result = []

    if not theme_id:
        valid_theme = QuestionnaireQuestionService.get_valid_theme_info()
        theme_id = valid_theme and valid_theme.id or None

    if not all([theme_id, question_id, main_answer_ids]):
        return result

    sub_questions_info = QuestionnaireQuestionService.get_relation_sub_question_ids(
        theme_id=theme_id,
        question_id=question_id,
        answer_ids=main_answer_ids
    )

    _sub_question_ids = sub_questions_info.get("question_ids", [])
    rel_sub_questions = answer_rel_sub_questions_data_splicing(
        questionnaire_question_ids=_sub_question_ids,
        filter_answer_ids=filter_answer_ids,
        question_display_nums=question_display_nums,
        answer_display_nums=answer_display_nums
    )

    for q_id in _sub_question_ids:  # 顺序校验 + 数据格式化
        _data = rel_sub_questions.get(q_id, {})
        if _data:
            _data.update({
                "can_skip": sub_questions_info.get("can_skip", False),
            })
            result.append(_data)

    return result


@bind("api/launch/get_valid_several_groups_sub_questionnaire")
def get_valid_several_groups_sub_questionnaire_v2(theme_id, question_id, main_answer_ids, filter_answer_ids, **kwargs):
    """
    获取有效的几组子问题
    :param theme_id:
    :param question_id:
    :param main_answer_ids:
    :param filter_answer_ids:
    :return:
    """
    result = {}

    if not theme_id:
        valid_theme = QuestionnaireQuestionService.get_valid_theme_info()
        theme_id = valid_theme and valid_theme.id or None

    if not all([theme_id, question_id, main_answer_ids]):
        return result

    # 获取几组判断， 返回值是字典
    rel_info = (QuestionnaireQuestionService.get_theme_question_info(
        theme_id=theme_id,
        question_ids=[question_id]
    ) or {}).get(question_id, {})

    base_query = Q(questionnaire_theme_id=theme_id, questionnaire_question_id=question_id)

    # 获取权重最高的几个回答id，返回值是列表
    # high_weight_answer_ids = QuestionnaireQuestionService.get_high_weight_groups_answer_ids(
    #     query=base_query & Q(questionnaire_answer_id__in=main_answer_ids),
    #     nums=rel_info.get("sub_questions_show_nums", 0)
    # )

    # v 7.27.0 update 改为随机取后台配置的个数
    _valid_answer_ids = QuestionnaireQuestionService.get_querysets_data(
        model_=QuestionnaireQaSubRelations,
        query=base_query & Q(questionnaire_answer_id__in=main_answer_ids),
    ).values_list("questionnaire_answer_id", flat=True).distinct()
    high_weight_answer_ids = QuestionnaireQuestionService.get_random_answer_ids(
        _valid_answer_ids,
        nums=rel_info.get("sub_questions_show_nums", 0)
    )

    # 获取子问题信息, 返回值是字典
    answer_rel_sub_questions_info = QuestionnaireQuestionService.get_answer_relation_sub_question_ids(
        query=base_query & Q(questionnaire_answer_id__in=high_weight_answer_ids),
        question_display_nums=kwargs.get("question_display_nums", 99)
    )
    # 封装子问题及回答数据， 返回值是字典
    rel_sub_questions = answer_rel_sub_questions_data_splicing(
        questionnaire_question_ids=list(chain(*(item.get("question_ids", []) for item in answer_rel_sub_questions_info.values()))),
        filter_answer_ids=filter_answer_ids,
        question_display_nums=kwargs.get("question_display_nums", 99),
        answer_display_nums=kwargs.get("answer_display_nums", 99)
    )

    result = []
    for a_id, sub_infos in answer_rel_sub_questions_info.items():
        _can_skip = sub_infos.get("can_skip", False)
        _is_series_answer = sub_infos.get("is_series_answer", False)

        sub_questions = []
        for _sub_ques_id in sub_infos.get('question_ids', []):
            _ques_info = rel_sub_questions.get(_sub_ques_id, {})

            if not _ques_info:
                continue

            _ques_info.update({
                "can_skip": _can_skip,
                "is_series_answer": _is_series_answer,
            })
            sub_questions.append(_ques_info)

        result.append({
            "answer_id": a_id,
            "weight": sub_infos.get("weight", 999),
            "sub_questions": sub_questions,
        })

    return result


@bind("api/launch/get_questionnaire_conclusion_v2")
def get_questionnaire_conclusion_v2(q_ids, a_ids):
    """
    获取问卷结论
    :param q_ids: 问题ids []
    :param a_ids: 回答ids []
    :return: {"q_id": _data}}  大概结构是这样 backend 校验顺序
    """
    questions_dic = QuestionnaireQuestionService.get_record_info_by_question_ids(q_ids)
    answers_dic = QuestionnaireAnswerService.get_record_info_by_answer_ids(a_ids)
    # 回答关联的感兴趣问题ID
    answer_rel_interest_questions = QuestionnaireAnswerService.get_questionnaire_answer_questions_of_interest(a_ids)

    result = {}
    for q_id in q_ids:
        question_info = questions_dic.get(q_id, {})
        answers = answers_dic.get(q_id, [])

        for answer_info in answers:
            _a_id = answer_info.get("questionnaire_answer_id", 0)
            answer_info.update({
                "interest_question_ids": answer_rel_interest_questions.get(_a_id, [])
            })

        if all([question_info, answers]):
            _data = {
                "is_influence_user_portrait": question_info.get("is_influence_user_portrait", False),
                "relation_question_id": question_info.get("relation_question_id", 0),
                "portrait_type": question_info.get("portrait_type", PORTRAIT_TYPE.INTERESTED),
                "answers": answers,
            }
            result[str(q_id)] = _data

    return result


@bind("api/launch/get_video_context_data_by_user_submit_records")
def get_video_context_data_by_user_submit_records(submit_record_list):
    """
    通过用户提交记录获取视频展示文案
    :param submit_record_list:
    :return:
    """

    def get_question_info(question_infos, ques_type, param):
        """
        获取单个问题信息
        :param question_infos:
        :param ques_type:
        :return:
        """
        _info = {}
        for ques_info in question_infos:
            if ques_info[param] == ques_type:
                _info = dict(ques_info)
                break

        return _info

    result = {
        "question_id": 0,
        "ques_type": "",
        "answer_id": 0,
        "answer_rel_v3_tags": [],
        "answer_rel_v3_attr_tags": [],
        "answer_explicit_text": ""
    }

    question_ids = list(map(lambda item: item[0], submit_record_list))
    sql_questions_info = QuestionnaireQuestionService.get_querysets_data(
        model_=QuestionnaireQuestions,
        query=Q(pk__in=question_ids, is_effect=True, is_delete=False)
    ).values("id", "portrait_type")

    sorted_question_infos = sorted(sql_questions_info, key=lambda item: question_ids.index(item["id"]))
    question_info = get_question_info(sorted_question_infos, PORTRAIT_TYPE.EXPERIENCED, "portrait_type") or \
                    get_question_info(sorted_question_infos, PORTRAIT_TYPE.INTERESTED, "portrait_type")

    if not question_info:
        return result

    answer_id = list(filter(lambda item: item[0] == question_info["id"], submit_record_list))[0][1][0]
    answer_explicit_text = QuestionnaireAnswerService.get_querysets_data(
        query=Q(pk=answer_id)
    ).values("questionnaire_display_content", "questionnaire_content").first()
    if not answer_explicit_text:
        answer_explicit_text = {}

    v3_tag_ids = QuestionnaireAnswerRelationTagV3.objects.filter(
        questionnaire_answer_id=answer_id).values_list("tag_v3_id", flat=True)
    v3_attr_tag_ids = QuestionnaireAnswerRelationAttrTag.objects.filter(
        questionnaire_answer_id=answer_id).values_list("attr_tag_id", flat=True)

    attr_tags_info = TagV3Service.get_attr_tag_info_by_attr_ids(v3_attr_tag_ids)
    v3_tags_info = TagV3Service.get_tags_v3_by_ids(v3_tag_ids)

    result.update({
        "question_id": question_info["id"],
        "ques_type": question_info["portrait_type"],
        "answer_id": answer_id,
        "answer_rel_v3_tags": list(v3_tags_info.values()),
        "answer_rel_v3_attr_tags": list(attr_tags_info.values()),
        "answer_explicit_text": answer_explicit_text.get("questionnaire_display_content", ""),
        "questionnaire_content": answer_explicit_text.get("questionnaire_content", ""),
    })

    return result


@bind('api/launch/get_answer_tags')
def get_kyc_answer_tag_v3(answer_ids):
    if not answer_ids:
        return []

    v3_tag_ids = list(QuestionnaireAnswerRelationTagV3.objects.using(settings.SLAVE_DB_NAME).filter(
        questionnaire_answer_id__in=answer_ids
    ).values_list("tag_v3_id", flat=True))

    v3_tags_info = TagV3Service.get_tags_v3_by_ids(v3_tag_ids)

    return {
        'tag_v3': list(v3_tags_info.values()),
    }


@bind('api/launch/answer_tags')
def get_kyc_answers_tags(answer_ids):
    if not answer_ids:
        return []

    answer_tags = list(QuestionnaireAnswerRelationTagV3.objects.using(settings.SLAVE_DB_NAME).filter(
        questionnaire_answer_id__in=answer_ids
    ).values("tag_v3_id", "questionnaire_answer_id"))

    answer_tags_dict = defaultdict(list)
    for item in answer_tags:
        answer_tags_dict[item["questionnaire_answer_id"]].append(item["tag_v3_id"])
    tag_ids = [item["tag_v3_id"] for item in answer_tags]

    tags_info = TagV3Service.get_tags_v3_by_ids(tag_ids)

    tags = defaultdict(list)
    for answer_id, tag_ids in answer_tags_dict.items():
        for tag_id in tag_ids:
            tag = tags_info.get(tag_id)
            if not tag:
                continue
            tags[str(answer_id)].append(tag)

    return {"answer_tags": tags}