# -*- coding: utf-8 -*-
from django.conf import settings
from django.db.models import Q
from gm_types.mimas import (
    TRACTATE_PLATFORM,
    TRACTATE_REPLY_HIGHLIGHT
)
from gm_types.error import ERROR as CODES
from gm_dataquery.dict_mixin import to_dict

from gm_rpcd.all import RPCDFaultException
from utils.rpc import gen, get_current_user
from utils.stat_log import SocialStatLogForUserAction

from talos.cache.base import reply_cache as reply_msg_cache
from talos.tools.replies_tool import ReplyTool
from talos.views.tractate.tractate import update_tractate_special_info

from talos.libs.datetime_utils import get_timestamp_or_none
from qa.utils.decorator import listing
from talos.rpc import bind_context, bind
from talos.services.tractate.tractate import TractateService
from talos.services.tractate.reply import TractateReplyService
from talos.services.tractate.vote import TractateReplyVoteService
from talos.services import get_user_from_context, UserService, UserConvertService
from talos.services.doctor import DoctorService
from talos.tools.tractate_reply_tool import reply_update_cache, get_reply_ids
from talos.tasks.tractate import reply_push

uri_pre = 'mimas/tractate_reply/'


@bind_context(uri_pre + 'create', with_context=True)
def create_tractate_reply(ctx, tractate_id, content, replied_id=None, top_id=None):
    """回复创建"""

    user = get_user_from_context(ctx)
    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    tractate = TractateService.healthy(tractate_id)

    result = {
        "replied_user_id": "",
        "replied_user_portrait": "",
        "replied_user_name": ""
    }
    replied = None

    if not top_id and not replied_id:
        top_id = 0
    if replied_id and not top_id:
        top_id = replied_id

    if replied_id:
        replied_info = TractateReplyService.get_by_id(pk=replied_id)
        replied_user_info = UserConvertService.get_user_info_by_user_id(replied_info.user_id)
        result.update({
            "replied_user_id": replied_user_info.get("user_id", 0),
            "replied_user_portrait": replied_user_info.get("portrait", ""),
            "replied_user_name": replied_user_info.get("user_name", ""),
            "replied_user_info": replied_user_info,
        })

    reply = TractateReplyService.create(
        content=content, user_id=user.id,
        tractate_id=tractate_id, extra={
            "top_id": top_id,
            "replied_id": replied_id,
            "source_id": TRACTATE_PLATFORM.GM
        }
    )

    replied_user_id = replied_info.user_id if replied_id else tractate.user_id
    if user.id != replied_user_id:
        rt = ReplyTool(reply_msg_cache, replied_user_id)
        rt.receive_tractate_reply(reply.id)

    reply_push.delay(user_id=user.id, tractate_id=tractate_id, reply_id=reply.id)

    # 用户行为埋点 评论相关
    SocialStatLogForUserAction.stat_log_for_reply(
        content_type=SocialStatLogForUserAction.CONTENT_TYPE.user_post,
        content_id=tractate_id,
        user_id=user.id
    )

    #更新一级评论下的评论数
    if top_id:
        result.update({"top_id": int(top_id)})
        TractateReplyService.update_reply_count(top_reply_id=top_id)
    else:
        result.update({"replies": []})

    TractateService.incr_tractate_reply(tractate=tractate)

    reply_update_cache(user_id=user.id, tractate_id=tractate_id, reply_id=reply.id)

    result.update({
        'id': reply.id,
        'content': reply.content,
        'create_time': get_timestamp_or_none(reply.create_time),
        "replied_id": int(replied_id) if replied_id else '',
        "user_name": user.nickname,
        "user_id": user.id,
        "user_portrait": user.portrait,
        "is_vote": False,
        "vote_num": 0,
        "status": TRACTATE_REPLY_HIGHLIGHT.DARK,
        "reply_count": 0,
        "reply_user_info": UserConvertService.get_user_info_by_user_id(user.id),
    })
    return result


@bind_context(uri_pre + 'receive', with_context=True)
def get_replies_by_ids(ctx, replies_ids):

    user = get_user_from_context(ctx)
    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    if not replies_ids:
        return {}

    replies_dict = TractateReplyService.get_replies_info(reply_ids=replies_ids)

    user_ids = []
    replied_ids = []
    tractates_ids = []
    for _, reply in replies_dict.items():
        user_ids.append(reply["user_id"])
        replied_ids.append(reply["replied_id"])
        tractates_ids.append(reply["tractate_id"])

    replied_dict = TractateReplyService.get_replies_info(reply_ids=replied_ids)
    users_dict = UserService.get_users_by_user_ids(user_ids)
    tractates_dict = TractateService.list_tractate_by_ids(tractates_ids)

    doctors_dict = {}
    doctors = DoctorService.get_doctor_from_user_ids(user_ids)
    for doctor in doctors:
        doctors_dict[doctor.user_id] = doctor

    result = {}
    for reply_id, reply in replies_dict.items():

        reply_user = users_dict.get(reply["user_id"], {})

        doctor = doctors_dict.get(reply["user_id"], {})
        doctor_info = {}
        if doctor:
            doctor_info = {
                "user_id": doctor.user_id,
                "doctor_id": doctor.id,
                "name": doctor.name,
            }

        replied = {}
        if  reply["replied_id"]:
            item = replied_dict.get(reply["replied_id"], {})
            if item:
                replied = {
                    "id": reply["replied_id"],
                    "content": reply["content"],
                }

        tractate = {}
        tractate_obj = tractates_dict.get(reply["tractate_id"])
        if tractate_obj:
            tractate = {
                "id": tractate_obj.id,
                "content": tractate_obj.content,
                "user_id": tractate_obj.user_id
            }

        info = {
            "id": reply["id"],

            "reply_date": reply["create_time"],
            "reply_content": reply["content"],

            "tractate": tractate,

            "replied": replied,
            "reply_user": {
                "id": reply_user.id,
                "name": reply_user.nickname,
                "portrait": reply_user.portrait,
            },
            "author": {
                "id": user.id,
                "name": user.nickname,
                "portrait": user.portrait,
            },

            "doctor": doctor_info,
        }
        result[str(reply_id)] = info

    return result


@bind(uri_pre + 'top/list')
#@listing()
def list_top_reply(ctx, tractate_id, offset=0, count=10, sort_condition=None):
    """一级回复列表"""
    user = get_user_from_context(ctx)
    tractate = TractateService.healthy(tractate_id)

    replies = TractateReplyService.list_top_reply_by_tractate_id(tractate_id, offset, count)

    user_ids = [reply.get('user_id') for reply in replies]
    users = UserConvertService.get_user_info_by_user_ids(user_ids)

    for reply in replies:
        reply_user_info = users.get(reply.get('user_id'), {})
        if not reply_user_info:
            continue

        reply.update({
            "user_nickname": reply_user_info.get("user_name", ""),
            "user_portrait": reply_user_info.get("portrait", ""),
            "reply_user_info": reply_user_info,
        })

    reply_num_total = tractate.reply_num

    return {
        'replies': replies,
        'reply_num_total': reply_num_total
    }


@bind(uri_pre + 'second_list')
@listing()
def gets_second_reply(reply_id, offset=0, count=10, user_id=None, sort_condition=None):
    """二级回复列表"""
    second_reply = TractateReplyService.get_second_reply_by_top_id(
        top_id=int(reply_id), offset=int(offset), count=int(count), sort_condition=sort_condition)

    user_ids, vote_reply_ids, replied_ids = set(), set(), set()
    for reply_item in second_reply:
        _user_id = reply_item.get("user_id", 0)
        _replied_id = reply_item.get("replied_id", 0)
        _id = reply_item.get("id", 0)

        if _user_id:
            user_ids.add(_user_id)

        if _replied_id:
            replied_ids.add(_replied_id)

        if _id:
            vote_reply_ids.add(_id)

    # 评论数据信息
    replied_infos = TractateReplyService.get_replies_info(reply_ids=replied_ids)
    replyed_user_ids = set(v.get("user_id", 0) for v in replied_infos.values())

    all_user_ids = user_ids | replyed_user_ids
    users = UserConvertService.get_user_info_by_user_ids(all_user_ids)

    for reply in second_reply:
        reply_user_info = users.get(reply.get('user_id', 0), {})
        if not reply_user_info:
            continue

        replied_info = replied_infos.get(reply.get('replied_id'), {})
        replied_user_info = users.get(replied_info.get('user_id', 0), {})
        if not replied_user_info:
            continue

        reply.update({
            "is_vote": True if reply.get('id') in vote_reply_ids else False,
            "user_name": reply_user_info.get("user_name", ""),
            "user_portrait": reply_user_info.get("portrait", ""),
            "replied_user_id": replied_user_info.get("user_id", 0),
            "replied_user_name": replied_user_info.get("user_name", ""),
            "replied_user_portrait": replied_user_info.get("portrait", ""),
            "reply_user_info": reply_user_info,
            "replied_user_info": replied_user_info,
        })

    return second_reply


@bind(uri_pre + 'top_list')
@listing()
def list_top_reply_by_tractate_ids(tractate_ids, offset=0, count=2, sort_condition=None):
    """多个帖子一级评论"""
    result, user_ids = {}, []
    for tractate_id in tractate_ids:
        _replies_list = TractateReplyService.list_top_reply_by_tractate_id(
            tractate_id=tractate_id, offset=offset, count=count, sort_condition=sort_condition
        )
        user_ids.extend([reply.get('user_id') for reply in _replies_list])
        result[str(tractate_id)] = _replies_list

    users = UserConvertService.get_user_info_by_user_ids(user_ids)

    for k, item in result.items():
        for reply in item:
            _user_info = users.get(reply.get("user_id", 0), {})
            if not _user_info:
                continue

            reply.update({
                "user_nickname": _user_info.get("user_name", ""),
                "user_portrait": _user_info.get("portrait", ""),
                "reply_user_info": _user_info,
            })

    return result


@bind(uri_pre + 'reply_popup')
@listing()
def get_reply_in_popup(tractate_id, offset=0, count=5, user_id=None, sort_condition=None):
    """评论弹窗~获取评论（一级和二级）"""
    SECOND_COUNT, START_INDEX = 2, 0
    TractateService.healthy(tractate_id)

    # 一级评论数据
    top_reply_infos = TractateReplyService.list_top_reply_by_tractate_id(
        tractate_id=int(tractate_id), offset=int(offset), count=int(count), sort_condition=sort_condition
    )

    top_reply_user_ids, vote_reply_ids = set(), []
    second_user_ids, repied_ids = set(), []

    # 一级评论处理用户，点赞状态，二级评论及子评论逻辑
    for item in top_reply_infos:
        _user_id = item.get("user_id", 0)
        _id = item.get("id", 0)

        if _user_id:
            top_reply_user_ids.add(_user_id)
        if _id:
            vote_reply_ids.append(_id)

        # 二级评论
        second_reply = TractateReplyService.get_second_reply_by_top_id(
            top_id=_id,
            count=SECOND_COUNT,
            offset=START_INDEX,
            sort_condition=sort_condition
        )

        # 处理一级评论的子评论
        item['replies'] = second_reply

        for reply in second_reply:
            _reply_user_id = reply.get("user_id", 0)
            _replied_id = reply.get("replied_id", 0)
            _second_reply_id = reply.get("id", 0)

            if _reply_user_id:
                second_user_ids.add(_reply_user_id)
            if _replied_id:
                repied_ids.append(_replied_id)
            if _second_reply_id:
                vote_reply_ids.append(_second_reply_id)

    # 处理二级评论、被评论用户信息
    replied_infos = TractateReplyService.get_replies_info(reply_ids=repied_ids)
    replyed_user_ids = set(v.get("user_id", 0) for v in replied_infos.values())

    # 取所有用户信息
    _all_user_ids = top_reply_user_ids | second_user_ids | replyed_user_ids
    all_user_infos = UserConvertService.get_user_info_by_user_ids(_all_user_ids)

    # 取所有已经被点赞的评论id
    voted_reply_ids = TractateReplyVoteService.get_vote_status(
        user_id=user_id, tractate_id=tractate_id, reply_ids=vote_reply_ids)

    #评论信息处理
    for top_reply_info in top_reply_infos:

        top_reply_user_info = all_user_infos.get(top_reply_info.get("user_id", 0), {})
        if not top_reply_user_info:
            continue
        top_reply_info.update({
            "user_name": top_reply_user_info.get("user_name", ""),
            "user_portrait": top_reply_user_info.get("portrait", ""),
            "is_vote": bool(top_reply_info.get("id", 0) in voted_reply_ids),
            "top_reply_user_info": top_reply_user_info,
        })

        # 二级评论信息处理
        for second_reply in top_reply_info.get('replies', []):
            second_reply_user_info = all_user_infos.get(second_reply.get("user_id", 0), {})

            if not second_reply_user_info:
                continue

            replied_info = replied_infos.get(second_reply.get('replied_id'), {})
            replied_info_user_info = all_user_infos.get(replied_info.get("user_id", 0), {})
            if not replied_info_user_info:
                continue

            second_reply.update({
                "is_vote": bool(second_reply.get("id", 0) in voted_reply_ids),
                "user_name": second_reply_user_info.get("user_name", ""),
                "user_portrait": second_reply_user_info.get("portrait", ""),
                "replied_user_id": replied_info_user_info.get("user_id", ""),
                "replied_user_name": replied_info_user_info.get("user_name", ""),
                "replied_user_portrait": replied_info_user_info.get("portrait", ""),
                "second_reply_user_info": second_reply_user_info,
                "replied_user_info": replied_info_user_info,
            })

    return top_reply_infos


@bind(uri_pre + 'light_reply')
def get_light_reply(tractate_id, user_id=None, target_reply_id=None):
    """获取高亮评论"""
    SECOND_COUNT, START_INDEX = 2, 0
    more_highlight = True

    if not target_reply_id:
        return gen(CODES.PARAMS_INCOMPLETE)

    top_info = TractateReplyService.get_highlight_reply(target_reply_id=target_reply_id)

    if not top_info:
        return []

    user_ids, replied_ids, vote_reply_ids = set(), set(), set()

    user_ids.add(top_info.get('user_id'))
    vote_reply_ids.add(top_info.get("id"))

    second_replies = TractateReplyService.get_second_reply_by_top_id(
        top_id=top_info.get('id'), count=SECOND_COUNT, target_reply_id=target_reply_id)

    for reply in second_replies:
        _reply_user_id = reply.get("user_id", 0)
        _replied_id = reply.get("replied_id", 0)
        _second_reply_id = reply.get("id", 0)

        if _reply_user_id:
            user_ids.add(_reply_user_id)

        if _replied_id:
            replied_ids.add(_replied_id)

        if _second_reply_id:
            vote_reply_ids.add(_second_reply_id)

    replied_infos = TractateReplyService.get_replies_info(reply_ids=replied_ids)
    for key, value in replied_infos.items():
        user_ids.add(value.get('user_id', 0))

    #获取用户是否点过赞
    voted_reply_ids = TractateReplyVoteService.get_vote_status(
        user_id=user_id, tractate_id=tractate_id, reply_ids=vote_reply_ids
    )

    # 所有用户
    all_user = UserConvertService.get_user_info_by_user_ids(user_ids)

    for second_reply in second_replies:
        second_reply_user_info = all_user.get(second_reply.get("user_id", 0), {})

        if not second_reply_user_info:
            continue

        replied_info = replied_infos.get(second_reply.get('replied_id'), {})
        replied_info_user_info = all_user.get(replied_info.get("user_id", 0), {})
        if not replied_info_user_info:
            continue

        if not top_info['status'] and second_reply['status'] == TRACTATE_REPLY_HIGHLIGHT.LIGHT:
            more_highlight = False

        second_reply.update({
            "is_vote": True if second_reply.get('id') in voted_reply_ids else False,
            "user_name": second_reply_user_info.get("user_name", ""),
            "user_portrait": second_reply_user_info.get("portrait", ""),
            "replied_user_id": replied_info_user_info.get("user_id", ""),
            "replied_user_name": replied_info_user_info.get("user_name", ""),
            "replied_user_portrait": replied_info_user_info.get("portrait", ""),
            "second_reply_user_info": second_reply_user_info,
            "replied_user_info": replied_info_user_info,
        })

    top_user_info = all_user.get(top_info.get("user_id", 0), {})
    top_info.update({
        "replies": second_replies,
        "user_id": top_user_info.get("user_id", 0),
        "user_name": top_user_info.get("user_name", ""),
        "user_portrait": top_user_info.get("portrait", ""),
        "is_vote": True if top_info.get('id') in voted_reply_ids else False,
        "top_reply_user_info": top_user_info,
    })

    if not top_info['status'] and more_highlight:
        top_info['status'] = TRACTATE_REPLY_HIGHLIGHT.MORE_LIGHT

    return [top_info]


@bind(uri_pre + 'get_info')
def get_reply_by_id(reply_id):
    if not reply_id:
        return gen(CODES.PARAMS_INCOMPLETE)

    reply = TractateReplyService.get_by_id(pk=int(reply_id))

    reply = to_dict(reply)
    user_info = UserConvertService.get_user_info_by_user_id(reply.get('user_id'))

    reply.update({
        "user_nickname": user_info.get("user_name", ""),
        "user_portrait": user_info.get("portrait", ""),
        "reply_user_info": user_info,
    })

    return reply


@bind(uri_pre + 'get_by_tractate')
#@listing()
def get_reply_by_tractate(user_id, offset=0, count=10, tractate_from='', use_new_query=False):
    """
    :param user_id:
    :param offset:
    :param count:
    :param tractate_from:   7.12.0 帖子入口
    :param use_new_query:    7.12.0  版本兼容
    :return:
    """
    if not user_id:
        return gen(CODES.LOGIN_REQUIRED)

    data = get_reply_ids(user_id=user_id)

    dic_reply = data.get('dic_reply')
    reply_infos = TractateReplyService.get_replies_info(reply_ids=data.get('reply_ids', []))

    _tractate_ids = TractateService.get_tractate_ids_by_query_and_order(
        query=Q(id__in=data.get('tractate_ids', [])),
        order_by=["-id"],
        offset=offset,
        size=count,
        tractate_from=tractate_from,
        use_new_query=use_new_query
    )
    tractate_list = []

    if _tractate_ids:
        tractates_info_dic = TractateService.get_tractate_infos_by_ids(
            tractate_ids=_tractate_ids,
            need_special_info=True,
            tractate_from=tractate_from,
            use_new_query=use_new_query,
        )
        # 增加浏览量
        TractateService.tractate_view_increase_num(tractates_info_dic.get("valid_tractate_ids", []))
        tractate_list = update_tractate_special_info(tractates_info_dic.get("tractate_list", []), _tractate_ids, user_id)

    for tractate in tractate_list:
        if dic_reply.get(tractate.get('tractate_id')):
            tractate['reply'] = reply_infos.get(dic_reply.get(tractate.get('tractate_id')))

    return tractate_list


@bind_context(uri_pre + 'received_aggregation', with_context=True)
def tractate_reply_reseived_aggregation(ctx):

    result = {
        "count": 0,
        "last_user_info": {},
        "create_time": 0,
    }
    user = get_user_from_context(ctx)
    if not user:
        return result

    info = TractateReplyService.get_tractate_reply_count_info(user.id)

    count = info["count"]
    last_user_id = info["last_user_id"]
    created_time = info["create_time"]
    if not count or not last_user_id:
        return result

    last_user_info = UserConvertService.get_user_info_by_user_id(last_user_id)
    result["count"] = count
    result["create_time"] = get_timestamp_or_none(created_time)

    _user_info = {
        "nickname": last_user_info.get("user_name", ""),
        "portrait": last_user_info.get("portrait", ""),
    }

    result["last_user_info"] = _user_info

    return result


@bind(uri_pre + 'read')
def tractate_reply_read():

    user = get_current_user()
    if not user:
        return

    TractateReplyService.read_all(user.id)
