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

import json
import random
from operator import itemgetter
from django.db.models import Q, Count

from gm_types.gaia import (
    PROBLEM_TYPE
)
from rpc.tool.dict_mixin import to_dict
from launch.models import (
    QuestionnaireTheme,
    QuestionnaireQuestions,
    QuestionnaireQaSubRelations,
    QuestionnaireThemeAndQuestionRelations,
)


class QuestionnaireQuestionService(object):

    @staticmethod
    def get_querysets_data(model_, query, order_by=[], fields=[]):
        query_sets = model_.objects.filter(query).order_by(*order_by)

        if fields:
            query_sets = query_sets.values(*fields)

        return query_sets

    @staticmethod
    def get_valid_theme_info():
        return QuestionnaireTheme.objects.filter(is_online=True).first()

    @classmethod
    def _get_valid_theme_question_infos(cls, theme_id, exclude_question_ids):
        result = {
            "relation_question_ids": [],
            "valid_infos": {}
        }

        relation_questions = QuestionnaireThemeAndQuestionRelations.objects.filter(
            questionnaire_theme_id=theme_id
        ).values("questionnaire_question_id", "can_skip", "rank", "send_message")

        _relation_question_dic, relation_question_ids = dict(), set()

        # 担心出现配置重复的数据，这里以库中保留的、配置顺序在前的有效
        for relation_question_item in relation_questions:
            _id = relation_question_item["questionnaire_question_id"]
            relation_question_ids.add(_id)

            if _id in exclude_question_ids:
                continue

            _relation_question_dic.setdefault(
                _id,
                dict(relation_question_item)
            )

        result.update({
            "relation_question_ids": list(relation_question_ids),
            "valid_infos": _relation_question_dic,
        })

        return result

    @staticmethod
    def get_valid_question_info(question_ids):
        """
        获取有效的问题id
        :param question_ids:
        :return:
        """
        questions = QuestionnaireQuestions.objects.filter(
            pk__in=question_ids,
            is_effect=True,
            is_delete=False
        ).values("id", "title", "problem_type", "is_filter_selected_answer")

        return questions

    @staticmethod
    def format_question(question):
        return {
            "id": question.get("id", 0),
            "title": question.get("title", ""),
            "problem_type": question.get("problem_type", PROBLEM_TYPE.MULTIPLE_PLANS),
            "is_filter_selected_answer": question.get("is_filter_selected_answer", False),
            "can_skip": question.get("can_skip", False),
            "send_message": question.get('send_message', False),
        }

    @classmethod
    def get_theme_valid_question(cls, theme_id, exclude_question_ids):
        """
        获取主题有效的问题信息
        :param theme_id: 主题id
        :param exclude_question_ids:
        :return:
        """
        result = {
            "theme_id": 0,
            "all_valid_question_nums": 0,
            "question_info": {},
        }

        valid_theme_question_infos = cls._get_valid_theme_question_infos(
            theme_id=theme_id,
            exclude_question_ids=exclude_question_ids
        )
        _relation_question_ids = valid_theme_question_infos.get("relation_question_ids")

        if _relation_question_ids:
            questions = cls.get_valid_question_info(question_ids=_relation_question_ids)

            result["all_valid_question_nums"] = questions.count()

            _valid_questions = []
            _valid_infos = valid_theme_question_infos.get("valid_infos", {})
            for item in questions.filter(pk__in=list(_valid_infos.keys())):
                _data = dict(item)
                _other_info = _valid_infos.get(_data["id"], {})

                _data.update({
                    "can_skip": _other_info.get("can_skip", False),
                    "rank": _other_info.get("rank", 999),
                    "send_message": _other_info.get("send_message", False)
                })

                _valid_questions.append(_data)

            question = _valid_questions and sorted(_valid_questions, key=lambda x: x.get("rank", 999))[0] or {}
            if question:
                result["question_info"] = cls.format_question(question)

        return result

    @classmethod
    def get_record_info_by_question_ids(cls, question_ids):
        """
        通过问题id, 获取上报相关信息
        :param question_ids:
        :return:
        """
        query_sets = QuestionnaireQuestions.objects.filter(
            pk__in=question_ids,
            is_effect=True,
            is_delete=False
        ).values("id", "relation_question_id", "is_influence_user_portrait", "portrait_type")

        return {item["id"]: dict(item) for item in query_sets}

    @classmethod
    def get_theme_question_info(cls, theme_id, question_ids):
        """
        获取某个主题下关联的问题基本信息
        :param theme_id:
        :param question_ids:
        :return:
        """
        rel_infos = cls.get_querysets_data(
            model_=QuestionnaireThemeAndQuestionRelations,
            query=Q(questionnaire_theme_id=theme_id, questionnaire_question_id__in=question_ids)
        )

        return {item.questionnaire_question_id: to_dict(item) for item in rel_infos}

    @classmethod
    def get_answer_relation_sub_question_ids(cls, query, question_display_nums=9):
        """
        获取回答关联的子问题信息
        :param query: 查询条件
        :param question_display_nums: 问题展示的数量
        :return:
        """
        # query = Q(
        #     questionnaire_theme_id=theme_id,
        #     questionnaire_question_id=question_id,
        #     questionnaire_answer_id__in=answer_ids
        # )

        rel_sub_question_infos = cls.get_querysets_data(
            model_=QuestionnaireQaSubRelations,
            query=query,
            fields=[
                "questionnaire_answer_id",
                "questionnaire_sub_question_id",
                "weight",
                "can_skip",
                "is_series_answer",
            ]
        )

        result = {}
        for item in rel_sub_question_infos:
            _answer_id = item["questionnaire_answer_id"]
            if _answer_id not in result:
                result[_answer_id] = {
                    "can_skip": item["can_skip"],
                    "weight": item["weight"],
                    "is_series_answer": item["is_series_answer"],
                    "question_ids": [],
                }

            if len(result[_answer_id]["question_ids"]) < question_display_nums:
                result[_answer_id]["question_ids"].append(item["questionnaire_sub_question_id"])

        return result

    @staticmethod
    def get_high_weight_groups_answer_ids(query, nums):
        """
        获取权重最高的前几
        :param query:
        :param nums:
        :return:
        """
        high_weight_groups = list(QuestionnaireQaSubRelations.objects.filter(
            query).values("weight").annotate(c=Count("weight")).values(
            "questionnaire_answer_id", "weight"))

        sorted_answer_ids = []
        for item in sorted(high_weight_groups, key=itemgetter('weight'))[:nums]:
            sorted_answer_ids.append(item["questionnaire_answer_id"])

        return sorted_answer_ids

    @staticmethod
    def get_random_answer_ids(answer_ids, nums=3):
        """
        获取随机数量的回答ID
        :param answer_ids:
        :param nums:
        :return:
        """

        if len(answer_ids) < nums:
            _answer_ids = answer_ids
        else:
            _answer_ids = random.sample(answer_ids, nums)

        return _answer_ids

    @classmethod
    def get_relation_sub_question_ids(cls, theme_id, question_id, answer_ids):
        """
        获取某个主题问题下回答 关联的子问题
        :param theme_id:  主题id
        :param question_id:  问题id
        :param answer_ids:  回答id列表
        :return:
        """
        sub_question_infos = {
            "question_ids": [],
            "can_skip": False,
        }

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

        # 先取权重最高的回答id
        weight_query = base_query & Q(questionnaire_answer_id__in=answer_ids)
        weight_answer_ids = cls.get_high_weight_groups_answer_ids(weight_query, 1)

        # 再取该回答下的子问题列表 + 相关数据
        if weight_answer_ids:
            sub_question_query = base_query & Q(questionnaire_answer_id__in=weight_answer_ids)
            relation_questions = cls.get_answer_relation_sub_question_ids(sub_question_query)
            _data = relation_questions.get(weight_answer_ids[0], {})

            sub_question_infos.update({
                "question_ids": _data.get("question_ids", []),
                "can_skip": _data.get("can_skip", False),
            })

        return sub_question_infos
