# -*- coding: utf8 -*-

from __future__ import unicode_literals, absolute_import, print_function

from collections import defaultdict

from django.conf import settings
from django.utils.html import escape
from gm_types.gaia import DOCTOR_TYPE, MY_COMMENT_TYPE
from gm_types.gaia import PROBLEM_FLAG_CHOICES
from gm_types.gaia import TOPIC_TYPE
from gm_types.gaia import USER_TYPE

from qa.portal import get_unread_count_by_user_id, get_answer_reply_by_pks, update_answer_reply_read_status

from qa.libs import get_answer_reply_new
from ..models.topic import TopicReplyVote, TopicReply
from talos.cache.reply import reply_cache
from talos.libs.datetime_utils import get_timestamp_or_none
from talos.models import ReplyCollect
from talos.rpc import CODES
from talos.rpc import RPCMixin
from talos.rpc import gen
from talos.rpc import get_objects_from_queryset_and_pk_list
from talos.services.doctor import DoctorService
from talos.services.user import UserService
from django.db.models import Q
from qa.models import AnswerReply


def _get_reply_topic_user_nicknames_by_replies(replies):
    ds = replies.values('id', 'replied_topic__user_id', 'problem__user_id')
    replied_topic_user_id_reply_id_dict = {d['replied_topic__user_id']: d['id'] for d in ds if d['replied_topic__user_id']}
    problem_user_id_reply_id_dict = {d['problem__user_id']: d['id'] for d in ds if d['problem__user_id']}
    r_user_ids = replied_topic_user_id_reply_id_dict.keys()
    p_user_ids = problem_user_id_reply_id_dict.keys()
    user_ids = list(r_user_ids) + list(p_user_ids)
    users = UserService.get_users_by_user_ids(user_ids)
    result = {}
    for u in users.values():
        uid = u.id
        if uid in r_user_ids:
            key = replied_topic_user_id_reply_id_dict[uid]
            value = u.nickname
        elif uid in p_user_ids:
            key = problem_user_id_reply_id_dict[uid]
            value = u.nickname
        else:
            continue
        result[key] = value
    return result


def _get_reply_topic_info(reply):
    """
    NOTE:
        获取回复相关的帖子topic信息
    :return:
    """
    topic_info = {
        'id': reply.problem_id,
        'title': (
            reply.replied_topic and reply.replied_topic.id and
            escape(reply.replied_topic.content) or escape(reply.problem.answer)
        ),
        'problem_ask': escape(reply.problem.ask),
        'problem_answer': escape(reply.problem.answer),
        'is_deleted': (
            reply.problem.flag == PROBLEM_FLAG_CHOICES.MARK_DELETED or
            not reply.problem.is_online
        ),
        'user': {
            'id': reply.problem.user_id,
            # 'nickname': reply.replied_topic and self.replied_topic.user.nickname or self.user.nickname
        },
    }
    if reply.problem.topic_type == TOPIC_TYPE.WEIXIN_NUM:
        topic_info['title'] = reply.problem.get_title()

    return topic_info


def _get_reply_diary_info(reply):
    """
    NOTE:
        获取回复相关的日记本信息
        其中 显示的title做特殊处理
        title = 'tag'+'日记'
    :return:
    """
    title = escape(reply.diary.title)

    tags_new_era = reply.diary.tags_new_era
    if tags_new_era:
        title = tags_new_era[0]['name'] + u'日记'

    diary_info = {
        'id': reply.diary.id,
        'title': title,
        'is_deleted': not reply.diary.is_online,
        'user': {
            'id': reply.diary.user_id,
            # 'nickname': UserService.get_user_by_user_id(self.diary.user_id).nickname,
        },
    }

    return diary_info


def get_reply_details_by_reply_ids(reply_ids, user_id=None):
    from talos.models.topic import ReplyHeadline

    replies = TopicReply.objects.filter(id__in=reply_ids)
    _replies = get_objects_from_queryset_and_pk_list(replies, reply_ids)
    result = []

    reply_user_ids = list(replies.values_list('user_id', flat=True))
    reply_users = UserService.get_users_by_user_ids(reply_user_ids)
    _reply_doctors = DoctorService.get_doctor_from_user_ids(reply_user_ids)
    reply_doctors = {d.user_id: d for d in _reply_doctors}

    self_reply_doctor_ids = list(replies.values_list('doctor_id', flat=True))
    _doctors = DoctorService.get_doctor_from_doctor_ids(self_reply_doctor_ids)
    self_doctors = {d.id: d for d in _doctors}
    doctor_hospitals = {}
    for d in _doctors:
        if d.hospital_id:
            doctor_hospitals[d.id] = d.hospital

    reply_ids = list(replies.values_list('id', flat=True))
    topicreply_votes = list(TopicReplyVote.objects.filter(topic_reply_id__in=reply_ids).values('topic_reply_id', 'user_id'))
    recommend_reply_ids = ReplyHeadline.get_recommend_reply_ids(reply_ids)
    user_nicknames = _get_reply_topic_user_nicknames_by_replies(replies)

    for reply in _replies:
        if reply.user_id and reply.user_id in reply_users.keys():
            city_name = reply_users[reply.user_id].city_name
            portrait = reply_users[reply.user_id].portrait
        else:
            city_name = u''
            portrait = u''

        user_type = 0
        if reply.user_id and reply.user_id in reply_doctors.keys():
            doctor_info = reply_doctors[reply.user_id]
            if doctor_info.is_online:
                doctor = doctor_info
                if doctor.doctor_type == DOCTOR_TYPE.OFFICER:
                    user_type = USER_TYPE.OFFICER
                    hospital_id = doctor_info.hospital_id
                else:
                    user_type = USER_TYPE.EXPERT
                    hospital_id = None
            else:
                doctor = None
                hospital_id = None
        else:
            doctor = None
            hospital_id = None

        if reply.doctor_id and reply.doctor_id in doctor_hospitals.keys():
            hospital_name_full = doctor_hospitals[reply.doctor_id].name or u''
        else:
            hospital_name_full = u''
        hospital_name = hospital_name_full[:14] if len(hospital_name_full) <= 14 else hospital_name_full[:14] + '...'

        if reply.doctor_id and reply.doctor_id in self_doctors.keys():
            doctor_portrait = self_doctors[reply.doctor_id].portrait
        else:
            doctor_portrait = ''

        if bool(user_id):
            k = {
                'user_id': user_id,
                'topic_reply_id': reply.id,
            }
            is_voted = k in topicreply_votes
        else:
            is_voted = False

        is_recommand = reply.id in recommend_reply_ids

        self_user = reply_users[reply.user_id]
        reply_data = {
            'user': {
                'user_id': reply.user_id,
                'user_name': self_user.nickname,
                'is_doctor': True if doctor else False,
                'is_hospital': True if hospital_id else False,
                'doctor_id': doctor.id if doctor else '',
                'doctor_name': doctor and doctor.name,
                'hospital_id': hospital_id if hospital_id else '',
                'portrait': portrait,
                'user_type': user_type,
                'membership_level': self_user.membership_level,
            },
            'is_private': bool(user_id) and user_id == reply.user_id,
            'doctor_portrait': doctor_portrait,
            'hospital_name': hospital_name,
            'is_recommend_doctor': False,
            'recommend_doctor_title': '',
            'favored': False,
            'images': [],
            'is_star_user': False,
            'city': city_name,
            'is_topic_append': reply.is_topic_append,
            'reply': {
                'reply_id': reply.id,
                'content': escape(reply.content),
                'favor_amount': reply.like_num,
                'reply_time': get_timestamp_or_none(reply.reply_date),
                'is_voted': is_voted,
                'image': reply.image,
                'is_new': reply.is_new,
                'replied_topic_id': reply.replied_topic_id or '',
                'reply_date': get_timestamp_or_none(reply.reply_date),
                'commented_reply_id': reply.replied_topic_id and reply.commented_reply_id or '',
                'like_num': reply.like_num,
                'is_best_reply': reply.is_best_reply(),
                'is_recommand': is_recommand,
                'is_elite': reply.is_elite(),
                'comments_num': reply.comments.count(),
            }
        }

        reply_data['diary'], reply_data['topic'] = None, None
        if reply.id in user_nicknames:
            nickname = user_nicknames[reply.id]
        else:
            nickname = None
        if reply.problem_id:
            topic_info = _get_reply_topic_info(reply)
            topic_info['user']['nickname'] = nickname
            reply_data['topic'] = topic_info

        if reply.diary_id:
            diary_info = _get_reply_diary_info(reply)
            diary_info['user']['nickname'] = nickname
            reply_data['diary'] = diary_info

        result.append(reply_data)
    return result


def comment_data_by_reply_ids(reply_ids):
    result = []
    replies = TopicReply.objects.filter(id__in=reply_ids)
    _replies = get_objects_from_queryset_and_pk_list(replies, reply_ids)

    replied_topic_user_ids = list(replies.values_list('replied_topic__user_id', flat=True))
    _replied_doctor_infos = DoctorService.get_doctor_from_user_ids(replied_topic_user_ids)
    replied_doctor_infos = defaultdict(lambda: None)
    for d in _replied_doctor_infos:
        replied_doctor_infos[d.user_id] = d

    _replied_user_infos = UserService.get_users_by_user_ids(replied_topic_user_ids)
    replied_user_infos = defaultdict(lambda: None)
    for k, v in _replied_user_infos.items():
        replied_user_infos[k] = v

    self_user_ids = list(replies.values_list('user_id', flat=True))
    _self_user_infos = UserService.get_users_by_user_ids(self_user_ids)
    self_user_infos = defaultdict(lambda: None)
    for k, v in _self_user_infos.items():
        self_user_infos[k] = v

    _self_user_doctor_infos = DoctorService.get_doctor_from_user_ids(self_user_ids)
    self_user_doctor_infos = defaultdict(lambda: None)
    for d in _self_user_doctor_infos:
        self_user_doctor_infos[d.id] = d

    self_doctor_ids = list(replies.values_list('doctor_id', flat=True))
    _self_doctor_infos = DoctorService.get_doctor_from_doctor_ids(self_doctor_ids)
    self_doctor_infos = defaultdict(lambda: None)
    for d in _self_doctor_infos:
        self_doctor_infos[d.id] = d

    for index, reply in enumerate(_replies):
        if reply.replied_topic:
            if reply.replied_topic.user_id == reply.user_id:
                at_nickname = u''
                at_doctor = None
                at_hospital_id = None
            else:
                if reply.replied_topic.user_id is not None:
                    replied_doctor_info = replied_doctor_infos[reply.replied_topic.user_id]
                    at_doctor = replied_doctor_info
                    if at_doctor and at_doctor.is_online and at_doctor.doctor_type == DOCTOR_TYPE.OFFICER:
                        at_hospital_id = at_doctor.hospital_id
                    else:
                        at_hospital_id = None
                else:
                    at_doctor = None
                    at_hospital_id = None

                at_nickname = replied_user_infos[reply.replied_topic.user_id].nickname or u'昵称未设置'
        else:
            at_nickname = u'昵称未设置'
            at_doctor = None
            at_hospital_id = None

        if reply.user_id:
            portrait = self_user_infos[reply.user_id].portrait
            membership_level = self_user_infos[reply.user_id].membership_level

            if self_user_doctor_infos[reply.user_id] and self_user_doctor_infos[reply.user_id].is_online:
                doctor = self_user_doctor_infos[reply.user_id]
                if doctor.doctor_type == DOCTOR_TYPE.OFFICER:
                    hospital_id = doctor.hospital_id
                else:
                    hospital_id = None
            else:
                doctor = None
                hospital_id = None
        else:
            portrait = ''
            membership_level = None
            doctor = None
            hospital_id = None

        data = {
            'type': 0,
            'content': escape(reply.content),
            'at_nickname': at_nickname,
            'at_doctor_id': at_doctor.id if at_doctor else '',
            'at_hospital_id': at_hospital_id if at_hospital_id is not None else '',
            'user_portrait': portrait,
            'at_user_id': reply.replied_topic.user_id if reply.replied_topic else '',
            'nickname': '',
            'comment_id': reply.id,
            'comment_time': reply.reply_date.strftime('%m.%d'),
            'comment_expert_id': doctor.id if doctor else '',
            'at_expert_id': at_doctor.id if at_doctor else '',
            'user_id': reply.user_id,
            'user_is_doctor': True if doctor else False,
            'user_is_hospital': True if hospital_id is not None else False,
            'doctor_id': doctor.id if doctor else '',
            'hospital_id': hospital_id if hospital_id is not None else '',
            'membership_level': membership_level,
            'is_best_reply': reply.is_best_reply(),
        }

        if self_doctor_infos[reply.doctor_id]:
            d = self_doctor_infos[reply.doctor_id]
            data['nickname'] = d.name
            if d.user_id != settings.SUOZHANG_UID:
                data['nickname'] += u'医生'
        else:
            data['nickname'] = self_user_infos[reply.user_id].nickname or u'昵称未设置'
        result.append(data)
    return result


def get_diary_replies(topic_reply_ids):

    # 我收到的评论
    topic_replies = TopicReply.objects.filter(
        pk__in=topic_reply_ids, is_online=True
    )
    topic_replies_dict = {reply.id: reply for reply in topic_replies}

    return topic_replies_dict


def get_my_replies(user_id, send_or_receive, start_num, count):
    if settings.REPLIES_READ_MYSQL_FLAG:
        return get_my_replies_mysql(user_id, send_or_receive, start_num, count)
    else:
        return get_my_replies_redis(user_id, send_or_receive, start_num, count)


def get_my_replies_redis(user_id, send_or_receive, start_num, count):
    def cmp(x, y):
        if x > 0 and y > 0:
            return int(y)-int(x)
        return int(x)-int(y)

    if send_or_receive == MY_COMMENT_TYPE.RECEIVED:
        reply_ids = reply_cache.get_received_comment_ids(user_id)
    elif send_or_receive == MY_COMMENT_TYPE.SENT:
        reply_ids = reply_cache.get_sent_comment_ids(user_id)
    else:
        return gen(CODES.OPERATION_NOT_SUPPORTED)

    reply_ids = sorted(reply_ids, cmp=cmp)
    reply_ids = reply_ids[start_num:start_num + count]

    answer_reply_pks = [pk.replace("-", "") for pk in reply_ids if pk.startswith("-")]
    topic_reply_pks = [pk for pk in reply_ids if not pk.startswith("-")]

    answer_reply = get_answer_reply_by_pks(pks=answer_reply_pks)
    update_answer_reply_read_status(answer_reply_pks)  # 更新回答回复的已读状态
    topic_reply = TopicReply.objects.filter(pk__in=topic_reply_pks, is_online=True)

    return topic_reply_pks, answer_reply + topic_reply


def get_my_replies_mysql(user_id, send_or_receive, start_num, count):
    if send_or_receive == MY_COMMENT_TYPE.RECEIVED:
        replys = ReplyCollect.objects.filter(reply_user_id=user_id).exclude(
            answer_id__isnull=False, user_id=user_id).order_by('-created_time')[start_num: start_num+count]
    elif send_or_receive == MY_COMMENT_TYPE.SENT:
        replys = ReplyCollect.objects.filter(user_id=user_id).order_by('-created_time')[start_num:start_num+count]
    else:
        return gen(CODES.OPERATION_NOT_SUPPORTED)

    answer_reply_pks = [collect.answer_id for collect in replys if collect.answer_id]
    topic_reply_pks = [collect.topic_reply_id for collect in replys if collect.topic_reply_id]

    answer_replies = get_answer_reply_by_pks(pks=answer_reply_pks)
    update_answer_reply_read_status(answer_reply_pks)  # 更新回答回复的已读状态
    topic_replies = TopicReply.objects.filter(pk__in=topic_reply_pks, is_online=True)
    answer_replies_dict = {reply['reply']['reply_id']: reply for reply in answer_replies}
    topic_replies_dict = {reply.id: reply for reply in topic_replies}
    sorted_replies = []
    for reply in replys:
        if reply.answer_id:
            _r = answer_replies_dict.get(reply.answer_id, False)
            if _r:
                sorted_replies.append(_r)
        if reply.topic_reply_id:
            _r = topic_replies_dict.get(reply.topic_reply_id, False)
            if _r:
                sorted_replies.append(_r)

    return topic_reply_pks, sorted_replies


def get_my_replies_count_from_mysql(user_id, send_or_receive=MY_COMMENT_TYPE.RECEIVED):
    if send_or_receive == MY_COMMENT_TYPE.RECEIVED:
        replies = ReplyCollect.objects.filter(reply_user_id=user_id).exclude(answer_id__isnull=False,
                                                                             user_id=user_id).order_by('-created_time')
        if replies.filter(answer_id__isnull=False).exists():
            answer_replies_count = get_unread_count_by_user_id(user_id)  # 排除自己给自己评论的数据
        else:
            answer_replies_count = 0

        topic_reply_pks = [collect.topic_reply_id for collect in replies if collect.topic_reply_id]
        topic_replies_count = TopicReply.objects.filter(id__in=topic_reply_pks, is_new=True, is_online=True).count()
        count = topic_replies_count + answer_replies_count
        return {
            "count": count,
            "last_user_id": replies.first().user_id if count else None,
            "created_time": replies.first().created_time if count else None,
        }

    elif send_or_receive == MY_COMMENT_TYPE.SENT:
        replies = ReplyCollect.objects.filter(user_id=user_id).order_by('-created_time')
        count = replies.count()
        return {
            "count": count,
            "last_user_id": replies.first().reply_user_id if count else None,
            "created_time": replies.first().created_time if count else None,
        }
    else:
        return gen(CODES.OPERATION_NOT_SUPPORTED)

