# coding=utf8

from __future__ import unicode_literals, absolute_import, print_function

from django.conf import settings
from django.db import models
from django.db.models import Q
from django.utils import timezone
from django.utils.html import escape

from gm_types.gaia import USER_TYPE
from gm_types.gaia import DOCTOR_TYPE
from gm_types.gaia import PROBLEM_FLAG_CHOICES
from gm_types.gaia import TOPIC_TYPE

from gm_upload import ImgUrlField
from gm_upload import IMG_TYPE

from talos.services.user import UserService
from talos.services.doctor import DoctorService
from talos.services.hospital import HospitalService

from talos.libs.datetime_utils import get_timestamp_or_none
from talos.libs.datetime_utils import get_humanize_datetime
from talos.libs.datetime_utils import get_timestamp

from talos.backbone.rpc import logging_exception
from talos.backbone.rpc import gen
from talos.backbone.rpc import CODES

from .topic import Problem
from ..diary.diary import Diary


class TopicReply(models.Model):
    """
        回复的内容
    """

    class Meta:
        verbose_name = u'011.话题回复'
        verbose_name_plural = u'011. 话题回复'
        db_table = 'api_topicreply'
        app_label = 'talos'

    diary = models.ForeignKey(Diary, verbose_name=u"关联的日记本", null=True, blank=True, default=None)
    problem = models.ForeignKey(Problem, verbose_name=u"话题", null=True, blank=True, default=None)
    user_id = models.IntegerField(verbose_name=u'用户外键id')
    doctor_id = models.CharField(max_length=100, null=True, blank=True, verbose_name=u'医生外键id')
    hospital_id = models.CharField(max_length=100, null=True, blank=True, verbose_name=u'关联的医院外键id')

    replied_topic = models.ForeignKey("self", default=None, null=True, blank=True, verbose_name=u"被回复的信息")
    commented_reply = models.ForeignKey('self', related_name=u'comments', verbose_name=u'被评论的回复', null=True,
                                        blank=True, default=None)
    content = models.TextField(verbose_name=u"回复内容")
    image = ImgUrlField(img_type=IMG_TYPE.TOPICREPLY, max_length='100', default="", verbose_name=u"图片", null=True,
                        blank=True)
    audio = models.TextField(default="", verbose_name=u"音频", null=True, blank=True)
    is_new = models.BooleanField(default=True, verbose_name=u"是否新的回复", db_index=True)
    is_spam = models.BooleanField(verbose_name=u'是否为疑似广告', default=False, db_index=True)

    like_num = models.IntegerField(default=0, verbose_name=u"赞的数目")
    dislike_num = models.IntegerField(default=0, verbose_name=u"踩的数目")

    # FIXME: reply_date重命名成reply_time，避免混淆含义
    reply_date = models.DateTimeField(verbose_name=u"回复时间", db_index=True, default=timezone.now)
    is_topic_append = models.BooleanField(verbose_name=u'是否是更新', default=False, db_index=True)
    is_online = models.BooleanField(default=True, help_text=u"是否可以上线", verbose_name=u"上线")
    is_fake = models.BooleanField(default=False, verbose_name=u"是否是灌水数据")

    def is_voted(self, user, reply):
        # TODO CR
        from .topicreplyvote import TopicReplyVote
        """
        NOTE:
            对一级评论进行点赞
        """
        is_voted = TopicReplyVote.objects.filter(user_id=user.id, topic_reply=reply).exists() if user else False
        return is_voted

    def get_reply_info(self):
        data = {
            'id': self.id,
            'uid': self.user_id,
            'nickname': self.user.nickname,
            'content': escape(self.content),
            'reply_time': get_timestamp_or_none(self.reply_date),
            'images': [],
            'is_online': self.is_online,
            'can_reply': not self.replied_topic,
        }

        return data

    def get_reply_info_for_doctor(self):
        data = {
            'topic_id': self.problem.id,
            'reply_date': get_timestamp_or_none(self.reply_date),
            'like_num': self.like_num,
            'my_content': escape(self.content),
            "old_content": self.replied_topic.content if self.replied_topic_id else (
                    self.problem.ask or self.problem.answer)
        }

        return data

    def __unicode__(self):
        return self.content

    def reply_data_after_create(self):
        if self.user_id:
            portrait = self.user.portrait
        else:
            portrait = u''

        user_type = USER_TYPE.NORMAL
        user_id = self.user_id
        if self.doctor_id:
            d = DoctorService.get_doctor_from_doctor_id(self.doctor_id)

            if d.doctor_type == DOCTOR_TYPE.OFFICER:
                user_type = USER_TYPE.OFFICER
                user_id = d.hospital_id
            elif d.doctor_type == DOCTOR_TYPE.DOCTOR:
                user_type = USER_TYPE.EXPERT
                user_id = self.doctor_id

        reply_data = {
            'reply_id': self.id,
            'user_type': user_type,
            'user_id': user_id,
            'user_nickname': escape(self.user.nickname) or u'昵称未设置',
            'user_portrait': portrait,
            'content': escape(self.content),
            'reply_date': get_humanize_datetime(self.reply_date),
            'reply_timestamp': get_timestamp(self.reply_date),
            'comments': [],
            'reply_count': self.comments.count(),
            'vote_count': self.like_num,
        }
        return reply_data

    def comment_data_after_create(self):
        if self.replied_topic and self.replied_topic.user_id == self.user_id:
            at_nickname = u''
        elif self.replied_topic:
            at_nickname = self.replied_topic.user.nickname
        else:
            at_nickname = u''

        user_type = 0
        if self.doctor_id:
            d = DoctorService.get_doctor_from_doctor_id(self.doctor_id)

            if d.doctor_type == DOCTOR_TYPE.OFFICER:
                user_type = 2
            elif d.doctor_type == DOCTOR_TYPE.DOCTOR:
                user_type = 1

        data = {
            'comment_id': self.id,
            'nickname': escape(self.user.nickname) or u'昵称未设置',
            'reply_id': self.replied_topic and self.replied_topic.id or '',
            'at_nickname': escape(at_nickname),
            'at_user_id': self.replied_topic.user_id if self.replied_topic else 0,
            'at_user_type': user_type,
            'comment_user_id': self.user_id,
            'comment_user_type': '',
            'content': escape(self.content),
            'reply_count': self.comments.count(),
            'vote_count': self.like_num,
        }
        return data

    def is_elite(self):
        """
        判断是否是热门回复
        """
        return self.like_num >= settings.ELITE_LIKE_NUM and True or False

    def get_reply_detail(self, user_id=None):
        from .replyheadline import ReplyHeadline  # 避免循环引用

        if self.user_id:
            city_name = self.user.city_name
            portrait = self.user.portrait
        else:
            city_name = u''
            portrait = u''

        user_type = 0
        doctor_info = UserService.get_doctor_from_user_id(self.user_id)
        if doctor_info is not None and 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

        hospital = HospitalService.get_hospital_from_doctor_id(self.doctor_id)
        if hospital is not None:
            hospital_name_full = hospital.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] + '...'

        reply_data = {
            'user': {
                'user_id': self.user_id,
                'user_name': self.user.nickname,
                'is_doctor': True if doctor else False,
                'is_hospital': True if hospital_id is not None else False,
                'doctor_id': doctor.id if doctor else '',
                'doctor_name': doctor and doctor.name,
                'hospital_id': hospital_id if hospital_id is not None else '',
                'portrait': portrait,
                'user_type': user_type,
                'membership_level': self.user.membership_level,
            },
            'is_private': bool(user_id) and user_id == self.user_id,
            'doctor_portrait': DoctorService.get_doctor_from_doctor_id(
                self.doctor_id).portrait if self.doctor_id else '',
            'hospital_name': hospital_name,

            'is_recommend_doctor': False,
            'recommend_doctor_title': '',

            'favored': False,
            'images': [],
            'is_star_user': False,
            'city': city_name,
            'is_topic_append': self.is_topic_append,
            'reply': {
                'reply_id': self.id,
                'content': escape(self.content),
                'favor_amount': self.like_num,
                'reply_time': get_timestamp_or_none(self.reply_date),
                'is_voted': bool(user_id) and self.topicreplyvote_set.filter(user_id=user_id,
                                                                             topic_reply=self).exists(),
                'image': self.image,
                'is_new': self.is_new,
                'replied_topic_id': self.replied_topic and self.replied_topic.id or '',
                'reply_date': get_timestamp_or_none(self.reply_date),
                'commented_reply_id': (
                        self.replied_topic and self.commented_reply and
                        self.commented_reply.id or ''
                ),
                'like_num': self.like_num,
                'is_best_reply': self.is_best_reply(),
                'is_recommand': ReplyHeadline.is_recommend(self.id),  # TODO CR 修改这个函数
                'is_elite': self.is_elite(),
                'comments_num': self.comments.count(),
            }
        }
        try:
            reply_data['diary'], reply_data['topic'], reply_data['answer'] = None, None, None
            if self.problem:
                topic_info = self.get_reply_topic_info()
                reply_data['topic'] = topic_info

            if self.diary:
                diary_info = self.get_reply_diary_info()
                reply_data['diary'] = diary_info

            author_id = self.problem and self.problem.user_id or self.diary.user_id
            if self.user_id == author_id:
                reply_data['user_titles'] = [{'title_type': 0, 'title_text': u'楼主'}, ]
            else:
                reply_data['user_titles'] = []

            if self.is_topic_append:
                # 增加术后第几天的展示
                if self.problem.operation_time:
                    interval = self.reply_date.date() - self.problem.operation_time
                    if interval.days >= 0:
                        reply_data['interval'] = u'{}'.format(interval.days + 1)
                    else:
                        reply_data['interval'] = u'以前'
                else:
                    reply_data['interval'] = u''
        except:
            logging_exception()

        return reply_data

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

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

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

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

        return diary_info

    def is_best_reply(self):
        """
            是否是优质问答
        """
        return self.replyheadline_set.filter(is_online=True).exists()

    def update_reply_num(self, is_online=False):
        real_replynum = 1 + TopicReply.objects.filter(commented_reply=self).count()
        if self.problem:
            if is_online:
                self.problem.reply_num += real_replynum
                self.problem.update_reply_num(is_online=True, reply_num=real_replynum)
            else:
                self.problem.reply_num -= real_replynum
                self.problem.update_reply_num(is_online=False, reply_num=real_replynum)

            if self.problem.reply_num < 0:
                return False
            self.problem.save()

        elif self.diary:
            if is_online:
                self.diary.reply_num += real_replynum
            else:
                self.diary.reply_num -= real_replynum

            if self.diary.reply_num < 0:
                return False
            self.diary.save()

        return True

    @property
    def user(self):
        if hasattr(self, '_user_obj'):
            return self._user_obj

        self._user_obj = UserService.get_user_by_user_id(self.user_id)
        return self._user_obj

    @property
    def doctor(self):
        return DoctorService.get_doctor_from_doctor_id(self.doctor_id)

    @property
    def hospital(self):
        return HospitalService.get_hospital_from_hospital_id(self.hospital_id)

    @classmethod
    def get_replys(cls, problem_id, last_id, size):
        """
        获取一级评论和次级评论，一级评论按照时间先后排序，次级评论紧跟一级评论
        :return:
        """
        replys = list()
        top_replys = list(cls.objects.filter(
            problem_id=problem_id,
            commented_reply__isnull=True,
            is_online=True,
            id__gt=last_id
        )[0: size])

        # 依次查一级评论下二级评论，总数够size则返回
        for top_reply in top_replys:
            replys.append(top_reply)
            if len(replys) == size:
                break

            # 查询当前一级评论的次级评论
            sub_replys = list(cls.objects.filter(
                commented_reply_id=top_reply.id,
                problem_id=problem_id,
                is_online=True,
            )[0: size - len(replys)])

            replys.extend(sub_replys)

            if len(replys) == size:
                break

        return replys

    @classmethod
    def get_sub_reply_ids(cls, reply_id):
        reply_ids = cls.objects.filter(replied_topic_id=reply_id, is_online=True).values_list('id', flat=True)
        sub_reply_ids = []
        sub_reply_ids.extend(reply_ids)
        for reply_id in reply_ids:
            sub_reply_ids.extend(cls.get_sub_reply_ids(reply_id))
        return sub_reply_ids