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

from itertools import chain
from gm_types.gaia import (
    AI_QA_QUESTION_TYPE,
    AI_QA_NEXT_TYPE,
    AI_QA_MESSAGE_TYPE,
)

from django.db.models import Q
from django.conf import settings

from api.util.user_util import simple_user_info_by_user_ids
from launch.services import (
    ThemeService,
    AIAnswerService,
    AIConsultInfoService,
    AIQAMessageService,
    AIQuestion2AnswerService,
)
from rpc.decorators import bind, cache_page


@bind("api/ai_qa/get_current_valid_theme")
def get_current_valid_theme():
    """
    获取当前有效的主题
    :return:
    """
    valid_theme_data = ThemeService.get_current_valid_theme()
    entrance_question_id = valid_theme_data.get("entrance_question_id", 0)

    ass_uid = valid_theme_data.get("ass_uid", 0)
    user_infos = simple_user_info_by_user_ids([ass_uid])

    valid_theme_data.update({
        "entrance_question": {},
        "ass_user_info": user_infos.get(str(ass_uid), {}),
    })

    # 把问题数据补上
    question_info = AIQuestion2AnswerService.get_qa_infos_by_question_id(entrance_question_id)

    if not question_info:
        return valid_theme_data

    valid_theme_data["entrance_question"] = question_info

    return valid_theme_data


@bind("api/ai_qa/get_qa_next_rel_data_by_answer_id")
def get_qa_next_rel_data_by_answer_id(user_id, answer_id):
    """
    通过回答ID获取问题数据
    :param user_id:
    :param answer_id:
    :return:
    """
    next_rel_data = AIQuestion2AnswerService.get_next_rel_data_by_answer_id(user_id, answer_id)

    return next_rel_data


@bind("api/ai_qa/get_ai_answer_rel_infos")
def get_ai_answer_rel_infos_by_answer_id(answer_id):
    """
    通过回答ID获取关联数据
    :param answer_id:
    :return:
    """
    answer_infos = AIAnswerService.get_answer_infos_by_answer_ids([answer_id])
    rel_v3_tags = AIAnswerService.get_answer_rel_tag_v3_infos_by_answer_ids([answer_id])

    return {
        "answer_info": answer_infos.get(int(answer_id), {}),
        "rel_v3_tags_info": rel_v3_tags.get(int(answer_id), []),
    }


@bind("api/ai_qa/record_leading_words")
def ai_qa_record_leading_words(user_id, msg_type):
    """
    记录引导语
    :param user_id:
    :param msg_type:
    :return:
    """
    result = {
        "status": False
    }
    can_finished = False

    if msg_type == AI_QA_MESSAGE_TYPE.FIRST_WEICOME:  # 开始语
        # 先看下这个用户有没有过消息
        group_result = AIQAMessageService.get_user_last_msg_groups_info(user_id, 1)
        if group_result.get("group_ids"):
            return result

    elif msg_type == AI_QA_MESSAGE_TYPE.CONCLUSION:  # 结束语
        # 产品将意外结束语去掉，则此处还需要判断最后一条是否是推荐卡片类型的数据，若不是则终止会话
        last_msg_info = AIQAMessageService.get_user_lastest_msg_info(user_id)  # 获取最新一条消息的状态
        if not last_msg_info or last_msg_info.get("type") in [
            AI_QA_MESSAGE_TYPE.CONCLUSION,
            AI_QA_MESSAGE_TYPE.RECOMMEND_CARD,
        ]:
            return result

        can_finished = True

    _create_data = AIQAMessageService.write_a_message_in_sql_by_theme(
        user_id, msg_type=msg_type
    )

    if can_finished:
        _group_id = _create_data.get("group_id", "")
        AIQAMessageService.update_msg_group_status(  # 更新消息组状态
            query=Q(user_id=user_id, group_id=_group_id)
        )
        AIQAMessageService.del_cache(user_id)

    result["status"] = _create_data.get("status", False)

    return result


@bind("api/ai_qa/get_user_lastest_msg_info")
def get_user_ai_qa_lastest_msg_info(user_id):
    """
    获取用户最新的一条历史消息
    :param user_id:
    :return:
    """
    result = {}

    lastest_msg_info = AIQAMessageService.get_user_lastest_msg_info(user_id)
    if not lastest_msg_info:
        return result

    users_info_dic = simple_user_info_by_user_ids([lastest_msg_info["ass_uid"], lastest_msg_info["user_id"]])
    lastest_msg_info.update({
        "ass_user_info": users_info_dic.get(str(lastest_msg_info["ass_uid"]), {}),
        "user_info": users_info_dic.get(str(lastest_msg_info["user_id"]), {}),
    })

    return lastest_msg_info


@bind("api/ai_qa/get_history_message")
def get_ai_qa_history_message(user_id, n=10):
    """
    获取某个用户的历史消息
    :param user_id:
    :param n: 最近几次的记录
    :return:
    """
    result = {
        "group_ids": [],  # 组ID列表
        "msg_infos": {},  # 消息字典
    }
    # 先获取有效的消息组
    msg_groups_dic = AIQAMessageService.get_user_last_msg_groups_info(user_id, n)
    msg_group_ids = msg_groups_dic.get('group_ids', [])
    _user_ids = set(chain(msg_groups_dic.get("ass_uids", []), [user_id, ]))

    if not msg_group_ids:  # 如果一组消息都没有，则创建一条首次开始的引导语
        can_record_first_status = True

    # 取消息组最新一条有效数据，若无则重新记录首次开始欢迎语
    elif not AIQAMessageService.get_lastest_msg_by_group_ids(msg_group_ids):
        can_record_first_status = True

    else:
        can_record_first_status = False

    if can_record_first_status:
        first_create_data = AIQAMessageService.write_a_message_in_sql_by_theme(
            user_id, msg_type=AI_QA_MESSAGE_TYPE.FIRST_WEICOME
        )
        if not first_create_data["status"]:  # 如果没写成功，就不再往下走了！
            return result

        msg_group_ids = [first_create_data.get("group_id")]
        _user_ids = [first_create_data.get("ass_uid", 0), user_id]

    # 消息组存在，则取对应有效的消息
    message_dic = AIQAMessageService.get_msg_info_by_group_ids(msg_group_ids)
    users_info = simple_user_info_by_user_ids(_user_ids)

    for _, v in message_dic.items():
        for msg_info in v:
            msg_info.update({
                "user_info": users_info.get(str(msg_info["user_id"]), {}),
                "ass_uid_info": users_info.get(str(msg_info["ass_uid"]), {})
            })

    result.update({
        "group_ids": msg_group_ids,
        "msg_infos": message_dic,
    })

    return result


@bind("api/ai_qa/get_info_about_the_user_continue")
def get_info_about_the_user_continue(user_id):
    """
    获取用户断点续传的数据
    :param user_id:
    :return: {'next_type': xx, "next_rel_data": {}}
    """
    result = {}

    msg_lastest_c = AIQAMessageService.get_user_lastest_msg_info(user_id)
    if not msg_lastest_c:
        return result

    _msg_type = msg_lastest_c.get("type")
    _current_completed_id = msg_lastest_c.get("ident")

    # 类型 或 没值
    if not all([_msg_type in AI_QA_MESSAGE_TYPE, _current_completed_id]):
        return result

    result.update({
        "group_id": msg_lastest_c.get("group_id", ""),
        "current_msg_type": _msg_type,
        "next_type": AI_QA_NEXT_TYPE.AI_QUESTION,
        "next_rel_data": {},
    })

    # 流程中的问题走了一半，需要通过回答ID找下一步数据
    if _msg_type in (AI_QA_MESSAGE_TYPE.BUTTON, AI_QA_MESSAGE_TYPE.LIST):
        _data = AIQuestion2AnswerService.get_next_rel_data_by_answer_id(user_id, _current_completed_id)
        result.update(_data)

    # 如果是在刚进来看到欢迎语就结束了, 则需要获取主题关联的问题
    elif _msg_type in (AI_QA_MESSAGE_TYPE.FIRST_WEICOME, AI_QA_MESSAGE_TYPE.REDO_WEICOME):
        valid_theme_data = ThemeService.get_theme_info_by_id(theme_id=_current_completed_id)
        entrance_question_id = valid_theme_data.get("entrance_question_id", 0)

        if not entrance_question_id:
            return result

        question_info = AIQuestion2AnswerService.get_qa_infos_by_question_id(entrance_question_id)
        if not question_info:
            return result

        result["next_rel_data"] = question_info

    # 是推荐卡片 或是意外退出结束语 亦或是问题组 的话，证明结束了! 不再需要数据
    elif _msg_type in (
            AI_QA_MESSAGE_TYPE.QUESTION_GROUP,
            AI_QA_MESSAGE_TYPE.RECOMMEND_CARD,
            AI_QA_MESSAGE_TYPE.CONCLUSION):
        pass

    return result


@bind('api/ai_qa/msg_record')
def ai_qa_msg_record(user_id, answer_id, record_type, com_question_ids=None, community_question_msg=""):
    '''
    消息记录
    :param user_id: int 用户ID
    :param answer_id: int
    :param record_type: 数据上报要记录类型, 通过 AI_QA_MESSAGE_TYPE 这个枚举调整
    :param com_question_ids: list 问题组ID
    :param community_question_msg: string 问题组标题串
    :return:
    '''
    # 通过 answer_id 找关联的问题ID.
    # 通过问题ID 找问题标题 + 问题类型记录
    # 若是问题组。则需要记录 问题组引导语、推荐卡片引导语、问题组消息、推荐卡片数据。消息结束，删除缓存
    result = AIQAMessageService.msg_record(
        user_id, answer_id, record_type,
        {
            "com_question_ids": com_question_ids,
            "community_question_msg": community_question_msg,
        }
    )

    if result.pop("can_finished", False):
        _group_id = result.get("group_id", "")
        AIQAMessageService.update_msg_group_status(  # 更新消息组状态
            query=Q(user_id=user_id, group_id=_group_id)
        )
        AIQAMessageService.del_cache(user_id)

    return result


@bind('api/ai_qa/msg_restart_record')
def ai_qa_msg_restart_record(user_id):
    """
    重新开始消息记录
    :param user_id:
    :return:
    """
    # 重新开始
    # 1. 切换消息组状态  - date 2020.08.24 update -> 若消息组数据为空，则不再重新生成新的消息组
    # 2. 删缓存
    # 3. 重新生成消息组数据
    # 4. 写入重新开始消息语

    result = {
        "restart_status": False,
    }

    # 取最新的消息组数据
    lastest_msg_info = AIQAMessageService.get_user_lastest_msg_info(user_id)
    if lastest_msg_info:  # 若有数据，则执行更新消息组状态 + 删缓存记录 的逻辑
        # 切换消息组状态
        AIQAMessageService.update_msg_group_status(query=Q(user_id=user_id, finished=False))

        # 删缓存
        AIQAMessageService.del_cache(user_id)

    # 记录数据: 重新开始欢迎语
    _data = AIQAMessageService.write_a_message_in_sql_by_theme(
        user_id, msg_type=AI_QA_MESSAGE_TYPE.REDO_WEICOME
    )
    result.update(_data)

    return result


@bind("api/ai_qa/get_msg_group_unread_count")
def get_user_msg_group_unread_count(user_id):
    """
    获取用户未读的数量
    :param user_id:
    :return:
    """
    result = {
        "unread_count": AIQAMessageService.get_user_unread_msg_group_count(user_id),
    }

    return result


@bind("api/ai_qa/update_msg_unread_status")
def update_ai_qa_msg_unread_status(user_id):
    """
    更新未读状态
    :param user_id:
    :return:
    """
    return AIQAMessageService.update_user_unread_msg_group_status(user_id)


@bind("api/ai_qa/get_ass_user_info")
def get_ai_qa_ass_user_info(user_id):
    """
    通过用户ID取下聊天中的用户信息
    :param user_id:
    :return:
    """
    _base_data_from_cache = AIQAMessageService.get_group_id_and_ass_uid(user_id, only_get_ass_uid=True)
    ass_uid = _base_data_from_cache.get("ass_uid", 0)

    user_infos = simple_user_info_by_user_ids([ass_uid])

    return {
        "ass_user_info": user_infos.get(str(ass_uid), {}),
    }


@bind("api/ai_qa/all_consult_infos")
def get_ai_qa_all_consult_infos(count=10):
    """
    获取咨询时，配置的所有问题文案
    :return:
    """
    return AIConsultInfoService.get_all_consult_infos(count)


@bind("api/ai_qa/get_selected_answer_rel_tags_for_scheme")
@cache_page(settings.AI_QA_SELECTED_ANSWER_CACHE_TIME)
def get_selected_answer_rel_tags_for_scheme(user_id, msg_group_id):
    """
    通过消息的组ID，获取消息内容
    :param user_id:
    :param msg_group_id:
    :return:
    """
    result = {}

    valid_obj = AIQAMessageService.get_msg_group_by_query(
        query=Q(user_id=user_id, group_id=msg_group_id)
    ).first()

    if not valid_obj:
        return result

    # 获取该消息组对应的详细消息
    msg_infos_dic = AIQAMessageService.get_msg_info_by_group_ids([msg_group_id])
    # 获取类型是问题类的数据
    valid_msg_list = list(filter(
        lambda item: item.get("type") in [AI_QA_MESSAGE_TYPE.BUTTON, AI_QA_MESSAGE_TYPE.LIST],
        msg_infos_dic.get(msg_group_id, [])
    ))

    selected_answer_ids = set(map(lambda item: item.get("ident", 0), valid_msg_list))
    _rel_tag_infos = AIAnswerService.get_answer_rel_tag_v3_infos_by_answer_ids(selected_answer_ids)
    result = AIAnswerService.get_answer_rel_tag_expand_infos(list(chain.from_iterable(_rel_tag_infos.values())))
    # 直连标签
    result['direct_related_tag'] = _rel_tag_infos

    return result
