# -*- coding: utf-8 -*-
from __future__ import unicode_literals, absolute_import, print_function
import re
import logging
import traceback
import datetime
from cached_property import cached_property
from django.db import models
from django.conf import settings
from django.utils import timezone
from django.utils.html import escape
from data_sync.utils import to_epoch, tzlc

from gm_serializer import fields
from gm_types.gaia import USER_TYPE, VOTEOBJECT, DIARY_CONTENT_LEVEL
from gm_types.mimas import (
    SPAM_LABEL,
    GRABBING_PLATFORM,
    QUESTION_TYPE,
    SEND_ANSWER_STATUS,
    QA_CONTENT_TYPE,
    MEDIA_IMAGE_URL_SOURCE,
    IMAGE_TYPE,
)
from gm_types.mimas.qa import CONTENT_CLASS, VIDEO_SOURCE_TYPE
from gm_upload import ImgUrlField, IMG_TYPE

from talos.services import UserConvertService
from utils.rpc import RPCMixin
from qa.cache import ViewRecord
from qa.utils import const_strings
from qa.utils.image import get_w_path, get_thumb_path, get_half_path
from qa.utils.time import get_humanize_datetime, get_timestamp_or_none, get_timestamp
from qa.utils.user import get_auth_type_by_userid, get_user_level
from qa.utils.get_video_cover import get_video_cover_url
from utils.exceptions import Impossible
from utils.common import convert_image
from utils.user import get_user_gm_url
from utils.protocol import gm_protocol


class UserManager(RPCMixin):
    def __call__(self, pk_list):
        """
        :param pk_list:
        :return:
        """
        return self.call_rpc('api/user/get_fundamental_info_by_user_ids', user_ids=pk_list)


class TagManager(RPCMixin):
    def __call__(self, pk_list):
        return self.call_rpc('api/tag/info_by_ids', tag_ids=pk_list)


class PageGoodClick(models.Model):
    class Meta:
        db_table = 'al_community_detail_page_goodclick_v2'
        app_label = 'doris'

    page_name = models.CharField(max_length=50)
    business_id = models.CharField(max_length=50)
    detail_uv = models.IntegerField()
    detail_gc = models.IntegerField()
    detail_new_gc = models.FloatField()
    avg_new_gc = models.FloatField()
    detail_pv = models.IntegerField()
    create_date = models.CharField(max_length=50)


class ApiAnswerScore(models.Model):
    class Meta:
        db_table = 'api_answer_score'

    answer_id = models.IntegerField(unique=True)
    new_score = models.FloatField(verbose_name=u'新的answer_score', blank=True, default=0)


class Question(models.Model):
    class Meta:
        verbose_name = u'问答'
        db_table = 'api_question'
        app_label = 'qa'

    user = fields.MagicField(type=int, manager=UserManager, ttl=60 * 5, db_column="user_id")
    title = models.CharField(max_length=128, null=False, verbose_name=u'问题')
    content = models.TextField(null=True, verbose_name=u'描述')
    cover_url = ImgUrlField(img_type=IMG_TYPE.NOWATERMARK, max_length=300, verbose_name=u'原图片地址', null=True, blank=True,
                            default=None)
    is_online = models.BooleanField(verbose_name='是否在线', default=True)
    is_recommend = models.BooleanField(verbose_name='是否推荐', default=False)
    recommend_xiaochengxu = models.BooleanField(verbose_name='吐槽小程序,是否推荐', default=False)
    like_num = models.IntegerField(verbose_name='点赞数量', default=0)
    create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True)
    # is_spam字段已弃用,请使用spam_label
    is_spam = models.BooleanField(verbose_name=u'是否为垃圾回答', default=False)
    spam_label = models.SmallIntegerField(verbose_name=u'spam标签', default=SPAM_LABEL.NORMAL, choices=SPAM_LABEL)
    question_type = models.IntegerField(verbose_name=u'问题类型', max_length=3, default=QUESTION_TYPE.TRADE,
                                        choices=QUESTION_TYPE)
    # from topic
    problem_id = models.IntegerField(verbose_name='帖子id', null=True, default=None, unique=True)
    city_id = models.CharField(max_length=40, null=True, verbose_name=u'用户对应的城市id')
    is_invite_doctor = models.BooleanField(verbose_name='是否邀请医生回答', default=False)
    platform = models.CharField(u'抓取平台信息', max_length=2, choices=GRABBING_PLATFORM, default=None,
                                null=True)  # 7675后,平台支持富文本展示content格式数据不同 新增类型
    # v 7.7.10 新增内容类型字段 枚举值 用于数据区分及召回
    content_type = models.CharField(u'内容类型', max_length=2, choices=QA_CONTENT_TYPE, default=QA_CONTENT_TYPE.ORDINARY)

    @cached_property
    def tags(self):
        """
        :return:
        """
        return QuestionTag.objects.filter(question=self)

    @staticmethod
    def _get_view_amount_of_id(question_id):
        return ViewRecord(const_strings.QUESTION_VIEW)[question_id] or 0

    @staticmethod
    def set_view_amount_of_id(question_id, num):
        ViewRecord(const_strings.QUESTION_VIEW)[question_id] = str(num)

    @staticmethod
    def _get_vote_amount_of_id(question_id):
        return ViewRecord(const_strings.QUESTION_VIEW)[question_id] or 0

    @property
    def vote_amount(self):
        """7720修改 话题点赞数*7"""
        return int(self._get_vote_amount_of_id(self.id)) * 7

    @cached_property
    def view_amount(self):
        """
        v 7.6.40 浏览量计算规则调整:问题本身浏览量 + 该问题下所有回答浏览量
        v 7.7.20 浏览量*13
        :return:
        """
        num1 = int(self._get_view_amount_of_id(self.id))  # 问题本身的浏览量
        num2 = sum([int(answer.view_amount) for answer in self.answers.filter(is_online=True)])  # 所有回答的浏览量
        return (num1 + num2) * 13

    @property
    def answer_num(self):
        return self.answers.filter(is_online=True).count()

    @property
    def comment_num(self):
        answers_ids = list(self.answers.filter(is_online=True).values_list('id', flat=True))
        if not answers_ids:
            return 0
        answers_reply_num = AnswerReply.objects.filter(is_online=True, answer_id__in=answers_ids).count()  # 所有回答的评论数
        return len(answers_ids) + answers_reply_num

    @property
    def recommend_answer(self):
        answer = self.answers.filter(is_recommend=True, is_online=True)
        if answer:
            return answer.first()
        return None

    @property
    def fisrt_answer(self):
        answer = self.answers.filter(is_recommend=True, is_online=True)
        if answer:
            return answer.first()
        return self.answers.filter(is_online=True).order_by('-like_num').first()

    def data_for_list(self, user=None):

        if self.cover_url:
            cover_url = get_w_path(self.cover_url)
        else:
            cover_url = ''
        if self.content:
            video_urls = re.findall('(' + settings.VIDEO_HOST + '.*?)\"', self.content)
            video_cover_list = get_video_cover_url(source_id=self.id, source_type=VIDEO_SOURCE_TYPE.QUESTION,
                                                   video_urls=video_urls)
        else:
            video_cover_list = None
        data = {
            'user_id': self.user.id,
            'user_name': self.user.nickname,
            'user_portrait': self.user.portrait,
            'membership_level': self.user.membership_level,
            'title': self.title,
            'content': escape(self.content) if self.content else '',
            'row_content': self.content or '',
            'image': cover_url,
            'answer_num': str(self.comment_num),
            'timestamp': int(self.create_time.strftime("%s")),
            'question_id': str(self.id),
            'time': get_humanize_datetime(self.create_time),
            'user_level': get_user_level(self.user),
            'view_num': self.view_amount,
            'tags': [tag.tag for tag in self.tags if tag.tag],
            'content_images': self.content_images,
            'platform': self.platform,
            'question_type': self.question_type,
            'video_cover_list': video_cover_list,
        }
        return data

    def data_for_discovery(self):
        """发现页"""

        if self.cover_url:
            cover_url = get_w_path(self.cover_url)
        else:
            cover_url = ''

        update_time = self.create_time
        answers = self.answers.filter(is_online=True).order_by("-create_time").values("id", "create_time")
        if answers:
            update_time = max(answers[0]["create_time"], update_time)
            ids = [i["id"] for i in answers]
            reply = AnswerReply.objects.filter(is_online=True, answer__in=ids). \
                order_by("-create_time").first()
            if reply:
                update_time = max(reply.create_time, update_time)

        data = {
            "title": self.title,
            "question_id": self.id,
            'title': self.title,
            'content': escape(self.content) if self.content else '',
            'row_content': self.content or '',
            'image': cover_url,
            'question_id': str(self.id),
            'desc': get_humanize_datetime(update_time),
            'tags': [tag.tag for tag in self.tags if tag.tag],
            'content_images': self.content_images,
            'platform': self.platform,
        }

        return data

    def data_for_doctor(self):
        data = {
            'user_id': self.user_id,
            'user_name': self.user.nickname,
            'user_portrait': self.user.portrait,
            'membership_level': self.user.membership_level,
            'title': self.title,
            'answer_num': str(self.answer_num),
            'question_id': str(self.id),
            'time': get_humanize_datetime(self.create_time),
        }
        return data

    def data_for_my_list(self, need_view_amount=True):
        data = {
            'title': self.title,
            'content': escape(self.content),
            'answer_num': str(self.answer_num),
            'vote_num': self.vote_amount,
            'question_id': str(self.id),
            'time': get_humanize_datetime(self.create_time),
            'create_time': self.create_time.strftime('%y-%m-%d'),
            'platform': self.platform
        }
        if need_view_amount:
            data["view_num"] = self.view_amount
        return data

    def data_for_es(self):
        answer = self.fisrt_answer
        if answer:
            return answer.data_for_es()
        return {
            'title': self.title,
            'content': '',
            'vote_num': 0,
            'comment_num': self.answer_num,
            'question_id': self.id,
            'answer_id': ''
        }

    @property
    def content_images(self):
        _m = []
        images = self.images.filter(
            image_url_source=MEDIA_IMAGE_URL_SOURCE.CREATE
        ).all()
        for image in images:
            if image.image_url:
                _m.append(image.image_url)

        return _m


class QuestionImage(models.Model):
    class Meta:
        verbose_name = u'问答图片'
        db_table = 'api_question_image'
        app_label = 'qa'

    question = models.ForeignKey(Question, related_name='images')
    image_url = ImgUrlField(img_type=IMG_TYPE.TOPICIMAGE, max_length=300, verbose_name=u'图片地址')
    width = models.IntegerField(verbose_name="图片宽度", default=0)
    height = models.IntegerField(verbose_name="图片高度", default=0)
    image_url_source = models.CharField(verbose_name="图片地址来源(创建、富文本)", max_length=3, choices=MEDIA_IMAGE_URL_SOURCE)
    image_type = models.IntegerField(verbose_name="图片类型", default=IMAGE_TYPE.OTHER)
    image_webp = models.CharField(max_length=128, default="", verbose_name=u'webp格式的图片')

    create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True)

    def data(self):
        return {
            'image': get_w_path(self.image_url),
        }

    @property
    def image_info_data(self):
        return {
            "image": self.image_url,
            "width": self.width,
            "height": self.height,
            "image_webp": self.image_webp,
        }


class QuestionTag(models.Model):
    class Meta:
        db_table = 'api_questiontag'
        app_label = 'qa'

    question = models.ForeignKey(Question, related_name='qtags')
    tag = fields.MagicField(type=int, manager=TagManager, ttl=60 * 60 * 24, db_column="tag_id")

    def get_name_list(tag_list):
        logging.info("get tag_list:%s" % tag_list)
        manager = TagManager()
        name = list()
        ma = manager.__call__(tag_list)
        for i in ma:
            logging.info("get manage_name:%s" % i['name'])
            name.append(i['name'])
        return name


class QuestionVote(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = 'api_question_vote'
        verbose_name = u'问答点赞'

    user = fields.MagicField(type=int, manager=UserManager, ttl=60 * 5, db_column="user_id")
    question = models.ForeignKey(Question, related_name="votes")
    unread = models.BooleanField(default=True)
    is_fake = models.BooleanField(default=False, verbose_name=u"是否机器人点赞")
    create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True)


class Answer(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = 'api_answer'
        verbose_name = u'问答回复'

    user = fields.MagicField(type=int, manager=UserManager, ttl=60 * 5, db_column="user_id")
    content = models.TextField(verbose_name='回答', null=False)
    cover_url = ImgUrlField(img_type=IMG_TYPE.NOWATERMARK, max_length=300, verbose_name=u'原图片地址', null=True,
                            blank=True, default=None)
    question = models.ForeignKey(Question, verbose_name=u"话题回复", related_name='answers')
    is_online = models.BooleanField(verbose_name='是否在线', default=True)
    is_recommend = models.BooleanField(verbose_name='是否推荐', default=False)
    like_num = models.IntegerField(verbose_name='点赞数量', default=0)
    create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True)
    # is_spam字段已弃用,请使用spam_label
    is_spam = models.BooleanField(verbose_name=u'是否为垃圾回答', default=False)

    spam_label = models.SmallIntegerField(default=SPAM_LABEL.NORMAL, choices=SPAM_LABEL, verbose_name=u"spam标签")
    level = models.IntegerField('分级', default=0)
    rank = models.IntegerField('展示序列', default=999)

    platform = models.CharField(u'抓取平台信息', max_length=2, choices=GRABBING_PLATFORM, default=None, null=True)
    #  v 7.6.40新加 用于消息 - 回答 计数使用!
    questioner_read = models.BooleanField(verbose_name='提问者是否已读', default=False)
    # v 7.6.70 新增 用户记录:当前回答的用户关联的医生id
    doctor_id = models.CharField(max_length=100, verbose_name="回答用户关联的医生id", default=None, null=True)
    doctor_title = models.CharField(max_length=2, verbose_name="回答用户关联的医生职称", default=None, null=True)
    # v 7.7.10 新增内容类型字段 枚举值 用于数据区分及召回
    content_type = models.CharField(u'内容类型', max_length=2, choices=QA_CONTENT_TYPE, default=QA_CONTENT_TYPE.ORDINARY)

    # from topicreply
    topicreply_id = models.IntegerField(verbose_name='帖子id', null=True, default=None, unique=True)

    low_quality = models.IntegerField(default=0, verbose_name=u'低质量反馈数量', blank=True, null=False)
    low_quality_deal = models.BooleanField(default=False, verbose_name=u'低质量反馈是否处理', blank=True)

    @staticmethod
    def _get_view_amount_of_id(answer_id):
        return ViewRecord(const_strings.ANSWER_VIEW)[answer_id] or 0

    @property
    def view_amount(self):
        return int(self._get_view_amount_of_id(self.id))

    @staticmethod
    def set_view_amount_of_id(answer_id, num):
        ViewRecord(const_strings.ANSWER_VIEW)[answer_id] = str(num)

    @cached_property
    def comment_num(self):
        """
        v 7.6.95变更,评论数为:1级评论 + 子评论
        :return:
        """
        return self.replys.filter(is_online=True).count()

    @cached_property
    def first_reply_num(self):
        return self.replys.filter(is_online=True, first_reply=None).count()

    def get_cover_image(self):
        if self.cover_url:
            return [convert_image(self.cover_url, watermark=True)]
        else:
            return []

    def get_all_images(self):
        data = []
        for image in self.images.filter(image_url_source=MEDIA_IMAGE_URL_SOURCE.CREATE).order_by('id'):
            data.append(image.data())
        return data

    def get_images(self):
        """获取所有的图片"""
        data = []
        for image in self.images.all().order_by('id'):
            data.append(image.data())
        return data

    def data_for_es(self, need_view_amount=True):

        data = {
            'title': self.question.title,
            'content': escape(self.content),
            'vote_num': self.like_num,
            'comment_num': self.comment_num,
            'question_id': self.question_id,
            'answer_id': self.id,
        }

        if need_view_amount:
            data['view_num'] = self.view_amount

        return data

    def data_for_list(self, user=None):
        is_vote = False
        if user:
            is_vote = AnswerVote.objects.filter(user=user, answer=self).exists()

        if self.content:
            video_urls = re.findall('(' + settings.VIDEO_HOST + '.*?)\"', self.content)
            video_cover_list = get_video_cover_url(source_id=self.id, source_type=VIDEO_SOURCE_TYPE.ANSWER,
                                                   video_urls=video_urls)
        else:
            video_cover_list = None
        data = {
            'user_id': self.user_id,
            'title': self.question.title,
            'content': escape(self.content) if self.content else "",
            'raw_content': self.content or "",
            'time': get_humanize_datetime(self.create_time),
            'user_name': self.user.nickname,
            'user_portrait': self.user.portrait,
            'membership_level': self.user.membership_level,
            'vote_num': str(self.like_num),
            'comment_num': str(self.comment_num),
            'answer_id': str(self.id),
            'question_id': str(self.question_id),
            'images': self.get_cover_image(),
            'content_images': self.content_images,
            'is_voted': is_vote,
            'user_level': get_user_level(self.user),
            'view_num': self.view_amount,
            'platform': self.platform,
            'question_type': self.question.question_type,
            'video_cover_list': video_cover_list,
        }
        return data

    def data_for_qa(self, user=None):
        is_vote = False
        if user:
            is_vote = AnswerVote.objects.filter(user=user, answer=self).exists()

        if self.content:
            video_urls = re.findall('(' + settings.VIDEO_HOST + '.*?)\"', self.content)
            video_cover_list = get_video_cover_url(source_id=self.id, source_type=VIDEO_SOURCE_TYPE.ANSWER,
                                                   video_urls=video_urls)
        else:
            video_cover_list = None

        if self.question.content:
            video_urls = re.findall('(' + settings.VIDEO_HOST + '.*?)\"', self.question.content)
            question_video_cover_list = get_video_cover_url(source_id=self.question.id,
                                                            source_type=VIDEO_SOURCE_TYPE.QUESTION,
                                                            video_urls=video_urls)
        else:
            question_video_cover_list = None

        data = {
            'user_id': self.user_id,
            'title': self.question.title,
            'content': escape(self.content) if self.content else "",
            'raw_content': self.content or "",
            'time': get_humanize_datetime(self.create_time),
            'user_name': self.user.nickname,
            'user_portrait': self.user.portrait,
            'membership_level': self.user.membership_level,
            'vote_num': self.like_num,
            'comment_num': self.comment_num,
            'view_num': self.view_amount,
            'answer_id': str(self.id),
            'question_id': str(self.question_id),
            'content_images': self.content_images,
            'video_cover_list': video_cover_list,

            'is_voted': is_vote,
            'user_level': get_user_level(self.user),
            'platform': self.platform,
            'question_type': self.question.question_type,
            'question_content_images': self.question.content_images,
            'question_answer_num': self.question.answer_num,
            'question_videos': question_video_cover_list,
            'question_content': self.question.content,
        }
        return data

    def data_for_detail(self, user):
        is_vote = False
        if user:
            is_vote = AnswerVote.objects.filter(user=user, answer=self).exists()

        if self.user_id == settings.SUOZHANG_UID or self.platform in GRABBING_PLATFORM:
            content = self.content
        else:
            content = escape(self.content)
        return {
            'id': self.id,
            'post_date': self.create_time.strftime('%y-%m-%d'),
            'content': content,
            'vote_count': self.like_num,
            'comment_count': self.comment_num,
            'image': self.get_all_images(),
            'is_online': self.is_online,
            'is_voted': is_vote,
            'tags': [tag.tag for tag in self.question.tags if tag.tag],  # 取其question的tag
            'platform': self.platform,  # 平台信息
            'first_reply_num': self.first_reply_num,  # 回答的一级评论数,用于查看更多一级评论!
            'create_time': self.create_time.timestamp(),
        }

    def get_videos(self):
        if self.content:
            video_urls = re.findall('(' + settings.VIDEO_HOST + '.*?)\"', self.content)
            video_cover_list = get_video_cover_url(source_id=self.id, source_type=VIDEO_SOURCE_TYPE.ANSWER,
                                                   video_urls=video_urls)
        else:
            video_cover_list = []

        return video_cover_list

    def data_for_author(self, user=None):
        user_info = UserConvertService.get_user_info_by_user_id(self.user_id)
        user_info.update({
            'user_type': 0,
            "user_portrait": self.user.portrait,
            'is_following': RPCMixin.call_rpc('api/user/is_following', cuid=user.id,
                                              uid=self.user.id) if user else False,
            'user_level': get_user_level(self.user),
            "college_id": self.user.get("college_id", 0),
            "college_name": self.user.get("college_name", ""),
        })
        return user_info

    @property
    def content_images(self):
        _m = []

        images = self.images.filter(
            image_url_source=MEDIA_IMAGE_URL_SOURCE.CREATE
        ).all()
        for image in images:
            if image.image_url:
                _m.append(image.image_url)

        return _m

    @property
    def get_good_click(self):
        try:
            results = list(
                PageGoodClick.objects.filter(business_id=self.id, page_name="answer_detail")
                    .order_by('-create_date').values_list("avg_new_gc", flat=True))
            good_click_score = results and results[0] or 0
            return good_click_score
        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())
            return 0

    def data_for_received(self):
        data = {
            "user": {
                'doctor_id': '',
                'user_id': self.user_id,
            },
            "answer": {
                "id": str(self.id),
                "content": self.content,
                "create_time": self.create_time.strftime("%Y-%m-%d %H:%M:%S"),
                "is_new": not self.questioner_read,
                "user_id": self.user_id,
                "username": self.user.nickname,
                "portrait": self.user.portrait,
            },
            "question": {
                "nickname": self.question.user.nickname,
                "portrait": self.question.user.portrait,
                "title": self.question.title,
                "is_deleted": not self.question.is_online,
            },
        }
        return data

    def _content_score(self):
        if self.level == CONTENT_CLASS.EXCELLENT:
            return 100
        elif self.level == CONTENT_CLASS.FINE:
            return 70
        elif self.level == CONTENT_CLASS.GENERAL:
            return 10
        elif self.level == CONTENT_CLASS.BAD:
            return 5
        else:
            return 0

    def _social_score(self):
        pass

    def _comment_score(self):
        comment_num = self.comment_num
        if comment_num == 0:
            return 0
        elif 1 <= comment_num <= 10:
            return 20
        elif 11 <= comment_num <= 20:
            return 40
        elif 21 <= comment_num <= 40:
            return 70
        elif 41 <= comment_num:
            return 100
        else:
            raise Impossible

    def _like_score(self):
        like_num = self.like_num
        if like_num == 0:
            return 0
        elif 1 <= like_num <= 10:
            return 20
        elif 11 <= like_num <= 20:
            return 40
        elif 21 <= like_num <= 30:
            return 70
        elif 30 <= like_num:
            return 100
        else:
            raise Impossible

    def _time_score(self):
        created_date = self.create_time.date()
        delta = created_date - settings.FOUNDING_DAY
        return delta.days

    def smart_rank(self):
        content_score = self._content_score()
        social_score = settings.SOCIAL_REPLY_WEIGHT * self._comment_score() + \
                       settings.SOCIAL_LIKE_WEIGHT * self._like_score()
        rank = settings.CONTENT_WEIGHT * content_score + \
               settings.SOCIAL_WEIGHT * social_score + \
               settings.TIME_WEIGHT * self._time_score()
        return rank

    def smart_rank_v2(self):
        try:
            result = ApiAnswerScore.objects.using(settings.DORIS_DB_NAME).filter(answer_id=self.id).first()
            return result.new_score if result else 0.0
        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())
            return 0.0

    def get_hot_score_answer(self):
        try:
            now = datetime.datetime.now()
            three_day = datetime.datetime.now() - datetime.timedelta(days=60)
            yesterday_begin_time = "%s-%s-%s 00:00:00" % (three_day.year, three_day.month, three_day.day)
            # 点赞数+3评论数+5收藏数
            # 获得点赞数
            vote_num = AnswerVote.objects.filter(answer_id=self.id, create_time__gte=yesterday_begin_time,
                                                 create_time__lte=now).count()
            # 获得评论数
            reply_num = AnswerReply.objects.filter(answer_id=self.id, create_time__gte=yesterday_begin_time,
                                                   create_time__lte=now, is_online=True).count()

            return vote_num + 3 * int(reply_num) + 0

        except:

            logging.error("catch exception,err_msg:%s" % traceback.format_exc())
            return []

    def get_last_any_reply_time(self):
        try:
            result = AnswerReply.objects.filter(answer_id=self.id).values_list("create_time", flat=True).order_by(
                "-create_time").first()

            return result

        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())
            return ''

    def get_has_picture(self):
        # 是否有图片
        try:
            answer_content = self.content
            re_pattern = r'.*[img|IMG|video|VIDEO] src="(.*)" .*'
            src_result = re.findall(re_pattern, answer_content)
            if src_result:
                return True
            else:
                return False
        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())
            return False


class SendAnswer(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = 'api_send_answer'
        verbose_name = u'定时发送回答'

    user_id = models.CharField(max_length=32, verbose_name='用户ID')
    content = models.TextField(verbose_name='回答内容', null=False)
    cover_url = ImgUrlField(img_type=IMG_TYPE.NOWATERMARK, max_length=300, verbose_name=u'运营配位图', null=True,
                            blank=True, default=None)
    question = models.ForeignKey(Question, verbose_name=u"问题")
    create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    push_time = models.DateTimeField(verbose_name=u'定时发送时间')
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True)
    # is_spam字段已弃用,请使用spam_label
    level = models.IntegerField('分级', default=0)
    rank = models.IntegerField('展示序列', default=999)
    status = models.SmallIntegerField(default=SEND_ANSWER_STATUS.WAITTING, choices=SEND_ANSWER_STATUS,
                                      verbose_name=u"定时发送回答状态")
    celery_task_id = models.CharField(verbose_name=u'异步任务ID', max_length=64)

    @property
    def data(self):
        return {
            'user': self.user_id,
            'content': self.content,
            'cover_url': self.cover_url,
            'level': self.level,
            'rank': self.rank,
            'question_id': self.question.id,
            'platform': GRABBING_PLATFORM.HERA,  # 默认为hera后台
        }


class AnswerImage(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = 'api_answer_image'
        verbose_name = u'问答回复图片'

    answer = models.ForeignKey(Answer, related_name='images')
    image_url = ImgUrlField(img_type=IMG_TYPE.TOPICREPLY, max_length=300, verbose_name=u'图片地址')
    width = models.IntegerField(verbose_name="图片宽度", default=0)
    height = models.IntegerField(verbose_name="图片高度", default=0)
    image_url_source = models.CharField(verbose_name="图片地址来源(创建、富文本)", max_length=3, choices=MEDIA_IMAGE_URL_SOURCE)
    image_type = models.IntegerField(verbose_name="图片类型", default=IMAGE_TYPE.OTHER)
    image_webp = models.CharField(max_length=128, default="", verbose_name=u'webp格式的图片')

    create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True)

    def data(self):
        return {
            'image': get_w_path(self.image_url),
        }

    @property
    def image_info_data(self):
        return {
            "image": self.image_url,
            "width": self.width,
            "height": self.height,
            "image_webp": self.image_webp,
        }


class AnswerVote(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = 'api_answer_vote'
        unique_together = ('user', 'answer')

    user = fields.MagicField(type=int, manager=UserManager, ttl=60 * 5, db_column="user_id")
    answer = models.ForeignKey(Answer, verbose_name=u"评论")
    unread = models.BooleanField(default=True)
    is_fake = models.BooleanField(default=False, verbose_name=u"是否机器人点赞")
    create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True)

    def to_dict(self):
        data = {
            'answer_id': self.answer_id,
            'nickname': self.user.nickname,
            'user_id': self.user_id,
            'vote_time': get_timestamp_or_none(self.create_time),
            'image': '',
            'content': escape(self.answer.content),
            'type': VOTEOBJECT.ANSWER,
            'membership_level': self.user.membership_level,
            'portrait': self.user.portrait,

        }
        return data


class AnswerReply(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = 'api_answer_reply'
        verbose_name = u'问答的评论'

    user = fields.MagicField(type=int, manager=UserManager, ttl=60 * 5, db_column="user_id")
    content = models.TextField(verbose_name='回答', null=False)
    answer = models.ForeignKey(Answer, verbose_name=u"话题回复", related_name='replys')
    first_reply = models.ForeignKey('self', related_name=u'fir_comment', verbose_name=u'一级回复id', null=True,
                                    blank=True, default=None)
    commented_reply = models.ForeignKey('self', related_name=u'comments', verbose_name=u'被评论的回复', null=True,
                                        blank=True, default=None)
    is_online = models.BooleanField(verbose_name='是否在线', default=True)
    like_num = models.IntegerField(verbose_name='点赞数量', default=0)
    create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True)
    # is_spam字段已弃用,请使用spam_label
    is_spam = models.BooleanField(verbose_name=u'是否为垃圾回答', default=False)
    spam_label = models.SmallIntegerField(default=SPAM_LABEL.NORMAL, choices=SPAM_LABEL, verbose_name=u"spam标签")

    # from topic
    topicreply_id = models.IntegerField(verbose_name='帖子id', null=True, default=None, unique=True)
    is_read = models.BooleanField(verbose_name='是否已读', default=False)

    @property
    def comment_num(self):
        return self.fir_comment.filter(is_online=True).count()

    def get_comment_data(self):
        if self.commented_reply and self.commented_reply.user == self.user:
            at_nickname = u''
        elif self.commented_reply:
            at_nickname = self.commented_reply.user.nickname
        else:
            at_nickname = u''

        return {
            'content': escape(self.content),
            'comment_id': self.id,
            'comment_user_id': self.user.id,
            # 'comment_user_type': get_auth_type_by_userid(self.user_id),
            'comment_user_type': USER_TYPE.NORMAL,
            "comment_user_gm_url": get_user_gm_url(self.user_id),
            'nickname': self.user.nickname,
            'at_user_id': self.commented_reply.user.id if self.commented_reply else 0,
            # 'at_user_type': get_auth_type_by_userid(self.commented_reply.user_id),
            'at_user_gm_url': get_user_gm_url(self.commented_reply.user_id),
            'at_user_type': USER_TYPE.NORMAL,  # hotfix 修复评论名称点击跳转的问题
            'at_nickname': escape(at_nickname),
        }

    def get_all_comments(self, need_newest=False, start_num=0, count=2, new_order=False):
        """
        获取全部子评论,引用时注意传参,默认获取全部的评论(老逻辑),考虑性能问题不要这么整……
        need_newest 改成了 获取时间最早的两条评论
        :param need_newest: 是否需要最新的
        :param start_num:
        :param count:
        :return:
        """
        comments = AnswerReply.objects.filter(first_reply=self, is_online=True)
        if need_newest and not new_order:
            comments = comments.order_by("-id")[start_num: start_num + count]

        if new_order:
            comments = comments.order_by("id")[start_num: start_num + count]

        result = []
        for comment in comments:
            result.append(comment.get_comment_data())
        return result

    def get_data_for_reply(self, user=None, has_comment=False, need_newest=False, new_order=False):
        is_vote = False
        if user:
            is_vote = AnswerVoteReply.objects.filter(user=user.id, answerreply=self).exists()

        data = {
            'content': escape(self.content),
            'reply_id': self.id,
            'reply_date': get_timestamp_or_none(self.create_time),
            'is_liked': is_vote,
            'favor_amount': self.like_num,
            'reply_count': self.comment_num,
            'user_id': self.user.id,
            'user_type': USER_TYPE.NORMAL,
            'gm_url': get_user_gm_url(self.user.id),
            'user_nickname': self.user.nickname,
            'user_portrait': self.user.portrait,
            'membership_level': self.user.membership_level,
            'comments': [],
            'user_level': get_user_level(self.user),
            "college_id": self.user.get("college_id", 0),
            "college_name": self.user.get("college_name", ""),
        }
        if need_newest and not new_order:
            data['comments'] = self.get_all_comments(need_newest=True)  # 取最新两条
        elif has_comment and not new_order:
            data['comments'] = self.get_all_comments()  # 保留原始逻辑
        elif new_order:
            data['comments'] = self.get_all_comments(new_order=new_order)

        return data

    def reply_data_after_create(self):

        photo = get_thumb_path(u'img%2Fuser_portrait.png')
        portrait = get_thumb_path(self.user.portrait) if self.user.portrait else photo

        user_type = USER_TYPE.NORMAL

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

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

        user_type = USER_TYPE.NORMAL

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

    def get_reply_for_mine(self):
        reply_data = {
            'user': {
                'doctor_name': '',
                'user_name': '',
                'doctor_id': '',
                'user_id': self.user_id,
                'user_portrait': '',
                'doctor_portrait': '',
            },
            'reply': {
                'replied_topic_id': self.commented_reply and self.commented_reply.id or '',
                'content': escape(self.content),
                'reply_id': self.id,
                'commented_reply_id': self.commented_reply and self.commented_reply.id or '',
                'reply_date': get_timestamp_or_none(self.create_time),
                'image': '',
                'is_new': not self.is_read,
                'commented_content': escape(self.commented_reply.content) if self.commented_reply else None,
                'commented_author_id': self.commented_reply.user_id if self.commented_reply else None,
            },
            'answer': {
                'user': {
                    'nickname': '',
                    'id': self.answer.user_id,
                    'portrait': '',
                },
                'id': self.answer_id,
                'title': self.answer.content,
                'is_deleted': not self.answer.is_online
            },
            'topic': None,
            "diary": None,
        }
        return reply_data


class AnswerVoteReply(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = 'api_answerreply_vote'
        unique_together = ('user', 'answerreply')

    user = fields.MagicField(type=int, manager=UserManager, ttl=60 * 5, db_column="user_id")
    answerreply = models.ForeignKey(AnswerReply, verbose_name=u"评论")
    unread = models.BooleanField(default=True)
    create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    update_time = models.DateTimeField(verbose_name=u'更新时间', auto_now=True)

    def to_dict(self):
        data = {
            'reply_id': self.answerreply_id,
            'nickname': "",
            'user_id': self.user_id,
            'vote_time': get_timestamp_or_none(self.update_time),
            'membership_level': "",
            'type': VOTEOBJECT.ANSWER_REPLY,
            'portrait': "",
        }

        return data


class UserAnswerQuestion(models.Model):
    """
    过渡方案,用于用户的问题与答案混排
    """

    class Meta:
        app_label = 'qa'
        db_table = 'api_user_question_answer'
        verbose_name = u'用户问答混排表'

    user = fields.MagicField(type=int, manager=UserManager, ttl=60 * 5, db_column="user_id")
    answer = models.ForeignKey(Answer, verbose_name=u'用户回答', blank=True, null=True)
    question = models.ForeignKey(Question, verbose_name=u'用户提问', blank=True, null=True)
    create_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    is_online = models.BooleanField(verbose_name=u'问答及其相关是否在线', default=True)


class AnswerTop(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = 'api_answer_top'

    question = models.ForeignKey(Question, default=None)
    answer = models.ForeignKey(Answer, default=None)
    order = models.IntegerField('展示顺序', unique=True, default=0)
    top_type = models.IntegerField('置顶类型', default=0)
    start_time = models.DateTimeField('上线时间', default=None)
    end_time = models.DateTimeField('下线时间', default=None)
    enable = models.BooleanField('是否上线', default=True)
    create_time = models.DateTimeField(auto_now_add=True)


class ZoneManager(RPCMixin):
    def __call__(self, pk_list):
        return self.call_rpc('api/zone/list', pks=pk_list)


class OverHeadAnswer(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = "api_overheadanswer"
        verbose_name = u'圈子推荐回答'

    zone = fields.MagicField(type=int, manager=ZoneManager, ttl=60, db_column="zone_id")
    answer = models.ForeignKey(Answer, help_text=u'回答', null=False, default='')
    rank = models.IntegerField(help_text=u'排序顺序', null=False, default=0)
    created_time = models.DateTimeField(help_text=u'创建时间', auto_now_add=True)
    deleted = models.BooleanField(help_text=u'是否已删除', default=False)


class OverHeadQuestion(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = "api_overheadquestion"
        verbose_name = u'圈子推荐问题'

    zone = fields.MagicField(type=int, manager=ZoneManager, ttl=60, db_column="zone_id")
    question = models.ForeignKey(Question, help_text=u'问题', null=False, default='')
    rank = models.IntegerField(help_text=u'排序顺序', null=False, default=0)
    created_time = models.DateTimeField(help_text=u'创建时间', auto_now_add=True)
    deleted = models.BooleanField(help_text=u'是否已删除', default=False)


class QuestionDoctor(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = 'api_question_doctor'
        verbose_name = u'问题tag相关联的美购智能推荐前20个医生'

    question = models.ForeignKey(Question)
    doctor_id = models.CharField(max_length=100, verbose_name=u'医生ID')
    unread = models.BooleanField(default=True, verbose_name=u'消息是否已读')
    create_time = models.DateTimeField(auto_now_add=True)


class QuestionInviter(models.Model):
    class Meta:
        app_label = 'qa'
        db_table = "api_question_inviter"
        verbose_name = u'邀请回答'

    user = fields.MagicField(type=int, manager=UserManager, ttl=60 * 5, db_column="user_id", verbose_name="邀请人")  # 邀请人
    inviter = fields.MagicField(type=int, manager=UserManager, ttl=60 * 5, db_column="inviter_id",
                                verbose_name="被邀请人")  # 被邀请人
    invite_time = models.DateTimeField(verbose_name="邀请时间", auto_now_add=True)
    question = models.ForeignKey(Question, verbose_name="被邀请的问题", related_name="invite_question", null=True, blank=True)
    answer = models.ForeignKey(Answer, verbose_name="被邀请的问题回答", related_name="invited", null=True, blank=True)
    user_read = models.BooleanField(verbose_name="邀请者对被邀请人的回答,是否已读", default=False)


class QuestionAnswer(models.Model):
    class Meta:
        app_label = 'doris'
        db_table = "question_answer"
        verbose_name = u'最佳回答'

    question_id = models.CharField(max_length=64, verbose_name="问题id")
    answer_id = models.CharField(max_length=64, verbose_name="回答id")