# coding=utf8

from __future__ import unicode_literals, absolute_import, print_function

import json
import datetime
import logging
import traceback
from django.conf import settings
from django.db import models
from django.db.models import Count, Q
from django.utils import timezone
from django.utils.html import escape
from django.utils.functional import cached_property
from gm_types.gaia import VOTEOBJECT
from gm_types.gaia import TAG_TYPE
from gm_types.gaia import AUTHOR_TYPE
from gm_types.gaia import CASH_BACK_STATUS
from gm_types.gaia import DOCTOR_TYPE
from gm_types.gaia import PROBLEM_REVIEW_STATUS_CHOICES
from gm_types.gaia import IMAGE_TYPE
from gm_types.gaia import PROBLEM_FLAG_CHOICES
from gm_types.gaia import DIARY_OPERATE
from gm_types.gaia import DIARY_CONTENT_LEVEL
from gm_types.gaia import DIARY_AUDIT_STATUS
from gm_upload import IMG_TYPE, ImgUrlField, batch_move_watermark_pic_to_no_watermark
from talos.libs.datetime_utils import get_timestamp_or_none
from talos.libs.datetime_utils import get_timestamp
from talos.libs.image_utils import get_full_path
from talos.libs.image_utils import get_short_path, get_temp_image_path
from talos.backbone.rpc import logging_exception
from talos.cache import diary_pv_cache
from talos.cache import model_cache
from talos.services.user import UserService
from talos.services.tag import TagService
from talos.services.doctor import DoctorService
from talos.services.order import OrderService
from talos.services.hospital import HospitalService
from talos.services.goods import GoodsService
from api.tool.user_tool import get_social_info


class Diary(models.Model):
    """
        日记本
    """

    class Meta:
        verbose_name = u'日记本'
        verbose_name_plural = u'日记本'
        app_label = 'talos'
        db_table = 'api_diary'

    title = models.CharField(verbose_name=u'标题', max_length=128, default='')
    user_id = models.IntegerField()

    order_id = models.CharField(null=True, blank=True, verbose_name=u'关联的订单外键id', max_length=12)
    service_id = models.IntegerField(null=True, blank=True, 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')
    raw_doctor = models.CharField(verbose_name=u'医生（名称）', blank=True, default='', max_length=200)
    raw_hospital = models.CharField(verbose_name=u'医院（名称）', blank=True, default='', max_length=200)
    rating = models.FloatField(verbose_name=u'评价', blank=True, default=0)
    operation_effect_rating = models.FloatField(verbose_name=u'术后效果评分',
                                                blank=True, default=0)
    doctor_attitude_rating = models.FloatField(verbose_name=u'医生态度评分',
                                               blank=True, default=0)
    hospital_env_rating = models.FloatField(verbose_name=u'医院环境评分',
                                            blank=True, default=0)
    comment = models.TextField(verbose_name=u'评价文字', blank=True, default='')
    price = models.IntegerField(verbose_name=u'价格', blank=True, default=0)
    created_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    last_modified = models.DateTimeField(verbose_name=u'最后修改时间', default=timezone.now)
    last_topic_add_time = models.DateTimeField(verbose_name=u'最后发帖时间', blank=True, null=True, default=None)
    operation_time = models.DateTimeField(verbose_name=u'手术时间', blank=True, null=True, default=None)
    is_fake_operation_time = models.BooleanField(verbose_name=u'手术时间为假', default=False,
                                                 help_text=u'当用户选择忘记了手术日期的时候，此字段为真')
    pre_operation_image = ImgUrlField(img_type=IMG_TYPE.DIARY, verbose_name=u'术前图', max_length=128, default='',
                                      blank=True, null=True)
    post_operation_image = ImgUrlField(img_type=IMG_TYPE.DIARY, verbose_name=u'术后图', max_length=128, default='',
                                       blank=True, null=True)
    is_headline = models.BooleanField(verbose_name=u"首页推荐", default=False, db_index=True)
    sell_point = models.CharField(verbose_name=u'卖点', max_length=32, default='')
    headline_time = models.DateTimeField(
        verbose_name=u'设为首页推荐的时间', null=True, default=None,
        help_text='如果取消首页推荐, 该字段设为None',
    )
    is_online = models.BooleanField(verbose_name=u'是否上线', default=True, db_index=True)
    is_real_case = models.BooleanField(verbose_name=u'真人案例', default=False)
    is_sink = models.BooleanField(verbose_name=u'是否下沉', default=False, db_index=True)
    is_spam = models.BooleanField(verbose_name=u'是否为疑似广告', default=False, db_index=True)
    note = models.TextField(verbose_name=u'注释', max_length=200, default='', blank=True)
    reply_num = models.IntegerField(verbose_name=u'回复数量', default=0)
    is_identification = models.BooleanField(verbose_name=u"是否认证", default=False, db_index=True)
    is_essence = models.BooleanField(default=False, help_text=u"是否精华帖", verbose_name=u"精华帖")
    # TODO Deprecated since 1.6.0
    pre_operation_image_for_doctor = ImgUrlField(
        img_type=IMG_TYPE.DIARY,
        verbose_name=u'医生术前图',
        max_length=128,
        default=None,
        blank=True,
        null=True
    )
    # TODO Deprecated since 1.6.0
    post_operation_image_for_doctor = ImgUrlField(
        img_type=IMG_TYPE.DIARY,
        verbose_name=u'医生术后图',
        max_length=128,
        default=None,
        blank=True,
        null=True
    )
    # 医生版1.9.1添加，每个医生的帖子列表中只能有一个置顶的 2016-02-23
    sticky_post = models.BooleanField(default=False, help_text=u"是否置顶", verbose_name=u"置顶帖")

    # added at 5.8
    like_num = models.IntegerField(default=0, verbose_name=u"赞的数目")

    # added at 5.9.3
    # http://wiki.gengmei.cc/pages/viewpage.action?pageId=1842494
    rate_count = models.IntegerField(default=0, verbose_name=u'评价次数', blank=True, null=False)

    is_choice = models.BooleanField(verbose_name=u'是否是精选日记本', default=False)
    is_choice_content = models.TextField(verbose_name=u'精选日记本描述', default='', blank=True)
    audit_status = models.CharField(verbose_name=u'审核状态', max_length=1, choices=DIARY_AUDIT_STATUS,
                                    default=DIARY_AUDIT_STATUS.UNAUDITED)
    audit_time = models.DateTimeField(
        verbose_name=u'最终审核时间', null=True, default=None, help_text='',
    )
    content_level = models.CharField(verbose_name=u'内容等级', max_length=3, choices=DIARY_CONTENT_LEVEL,
                                     default=DIARY_CONTENT_LEVEL.UNAUDITED)
    stick_priority = models.PositiveIntegerField(verbose_name=u'置顶优先级', default=255)
    is_import = models.BooleanField(verbose_name=u'是否是导入数据', default=False, blank=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)

    def get_index_rank(self):
        """获取首页排序评分(Tuple3)
        """
        # 热度分
        try:
            heat_score = self.diary_rank.heat_score
            # calculate the loss caused by time
            from talos.tools.diary_rank_tool import DiaryRankTool
            loss = DiaryRankTool.get_loss_score_by_time(self.id, heat_score)
            heat_score_now = heat_score - loss
            heat_score = max(0, min(heat_score_now, settings.DIARY_HEAT_RANK['max_score']))

        except Exception:
            heat_score = 0.0

        # 质量分
        if self.diary_check.exists():
            audit = self.diary_check.all().order_by('id').last()
            audit_score_map = {
                DIARY_CONTENT_LEVEL.UNAUDITED: settings.DIARY_CONTENT_LEVEL_SCORE['UNAUDITED'],
                DIARY_CONTENT_LEVEL.ILLEGAL: settings.DIARY_CONTENT_LEVEL_SCORE['ILLEGAL'],
                DIARY_CONTENT_LEVEL.BAD: settings.DIARY_CONTENT_LEVEL_SCORE['BAD'],
                DIARY_CONTENT_LEVEL.GENERAL: settings.DIARY_CONTENT_LEVEL_SCORE['GENERAL'],
                DIARY_CONTENT_LEVEL.FINE: settings.DIARY_CONTENT_LEVEL_SCORE['FINE'],
                DIARY_CONTENT_LEVEL.EXCELLENT: settings.DIARY_CONTENT_LEVEL_SCORE['EXCELLENT'],
                DIARY_CONTENT_LEVEL.BETTER: settings.DIARY_CONTENT_LEVEL_SCORE['BETTER'],
            }
            audit_score = audit_score_map[audit.content_level]
        else:
            audit_score = 0.0

        # 医生抽成分
        choucheng_score = DoctorService.get_discount_score_for_diary_index(self.doctor_id)

        return heat_score, audit_score, choucheng_score

    # 获取日记帖内容
    def get_diary_answer(self):
        try:
            result = Problems.objects.filter(user_id=self.user_id, topic_type__in=["0", "1", "2"], diary_id=self.id,
                                             is_online=True).order_by('-last_modified').values_list(
                "answer", flat=True).first()

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


    def get_new_diary_score(self):
        try:
            result = ApiDiaryScore.objects.using(settings.DORIS_DB_NAME).filter(diary_id=self.id).first()
            return result.new_score if result else -400.0
        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())
            return ''


    def get_hot_score(self, reply_num):
        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 = self.diary_votes.filter(vote_time__gte=yesterday_begin_time,
                                               vote_time__lte=now).count()

            logging.info("get vote_num:%s" % vote_num)
            # 获得该日记本下的日记帖
            # data = Problems.objects.filter(user_id=self.user_id, topic_type__in=["0", "1", "2"],
            #                                diary_id=self.id, is_online=True).values_list("id", flat=True)
            #
            # logging.info("get data:%s" % data)
            #
            # # 根据日记帖去拿评论
            # reply_num = self.topicreply_set.filter(problem_id__in=data, reply_date__gte=yesterday_begin_time,
            #                                        reply_date__lte=now, is_online=True).count()
            #
            # logging.info("get reply_num:%s" % reply_num)

            # 获得点赞数
            click_num = self.favor_diary_diary.filter(is_deleted=False,
                                                      created_time__gte=yesterday_begin_time,
                                                      created_time__lte=now).count()
            logging.info("get click_num:%s" % click_num)
            return int(vote_num) + 3 * int(reply_num) + 5 * int(click_num)

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

    @property
    def comment_count(self):
        return self.rate_count

    @property
    def get_good_click(self):
        try:
            results = list(
                PageGoodClick.objects.using(settings.DORIS_DB_NAME).filter(business_id=self.id, page_name="diary_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

    @property
    def get_low_quality(self):
        try:
            results = list(HighQualityContent.objects.using(settings.DORIS_DB_NAME).filter(id=self.id,
                                                                                           card_type="diary").values_list(
                "id", flat=True))
            if results and results[0]:
                return False
            else:
                return True
        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())
            return True

    @property
    def get_cpc(self):
        try:
            id_list = list(
                CpcCommunity.objects.using(settings.ARTEMIS_DB_NAME).filter(related_id=str(self.id))
                    .values_list("id", flat=True))
            if id_list:
                cpc_list = list(
                    CpcPromote.objects.using(settings.ARTEMIS_DB_NAME).filter(communitycpc_id=id_list[0])
                        .values_list("is_promote", flat=True))
                if cpc_list and cpc_list[0]:
                    return True
                else:
                    return False
            else:
                return False
        except:
            logging.error("catch exception,err_msg:%s" % traceback.format_exc())
            return False

    @property
    def has_commented(self):
        """日记本评价"""
        return bool(self.rating or self.comment)

    @property
    def title_style_type(self):
        return ''

    def tags_sort_for_special(self, tags):
        result = self.get_tags_from_tags_by_types(
            tags, [
                TAG_TYPE.BODY_PART, TAG_TYPE.BODY_PART_SUB_ITEM, TAG_TYPE.ITEM_WIKI
            ]
        )

        result += self.get_tags_from_tags_by_types(
            tags, [
                TAG_TYPE.CITY, TAG_TYPE.PROVINCE, TAG_TYPE.COUNTRY
            ]
        )
        result += self.get_tags_from_tags_by_types(tags, [TAG_TYPE.FREE])

        return result

    def get_tags_from_tags_by_types(self, tags, types):
        result = []
        for tag in tags:
            if tag.name in settings.UNSHOW_TAGS:
                continue
            if tag.tag_type in types:
                result.append(tag)
        return result

    @cached_property
    def tags_new_era(self):
        result = []
        for tag in self.tags:
            # 添加热门tag后 跟日记本相关的显示部分 热门tag作为3级tag来显示
            d = {'name': tag.name, 'id': tag.id, 'type': tag.tag_type, 'tag_id': tag.id}

            if hasattr(tag, 'itemwiki'):
                d['type'] = TAG_TYPE.ITEM_WIKI
                d['wiki_id'] = tag.itemwiki

            result.append(d)
        result = result[0:4]
        return result

    @cached_property
    def wiki_info(self):
        result = []

        for tag in self.tags_new_era:
            if 'wiki_id' not in tag:
                continue

            obj = {
                'id': tag['wiki_id'],
                'name': tag['name'],
                'tag_id': tag['id'],
            }
            result.append(obj)

        return result

    @cached_property
    def operation_tags(self):
        # get all operation tags
        tags = filter(lambda x: x.tag_type in (TAG_TYPE.ITEM_WIKI, TAG_TYPE.BODY_PART_SUB_ITEM), self.tags)
        return tags

    @cached_property
    def vote_num(self):
        # TODO: 为了性能转成预处理
        # 医生版2.1.0 把评论的赞数也统计上了 2016-04-20
        # 日记贴里面把获取点赞数逻辑放入了redis，日记本取的是原生,是否考虑将
        # 日记本的点赞逻辑也放入redis

        # 6.5.0 用户感知去掉
        # comment_votes = sum(int(reply.like_num) for reply in self.topicreply_set.all())

        return sum(int(topic.vote_amount) for topic in self.topics.all()) + self.like_num

    @property
    def cover(self):
        """
        封面
        v5.4.0 重新整理
        case1：日记本的所有贴子里术前术后图都至少有一张
          case1：日记本术前图术后图都已经设置了，正常显示
          case2：日记本术前图or术后图未设置，从所有贴子里取最新的术前或术后图补上，作为对比图封面
        case2：整个日记本缺少术前图
          case1：已经设置了日记本术后图，显示这张图片作为封面
          case2：未设置日记本术后图，显示最新的术后图作为封面
        case3：整个日记本缺少术后图
          case1：已经设置了日记本术前图，显示这张图片作为封面
          case2：未设置日记本术前图，显示最新的术前图作为封面
        case4：日记本无图，列表里不显示图片
        """
        # diary_cover = []
        # pre_image = self.pre_operation_image
        # post_image = self.post_operation_image
        #
        # if self.pre_operation_image:
        #     # 获取日记本术前图
        #     pre_image = self.pre_operation_image
        #
        # if self.post_operation_image:
        #     # 获取日记本术后图
        #     post_image = self.post_operation_image
        #
        # if not pre_image or not post_image:
        #     # 没有术前或者术后图 从帖子中找
        #     post_type = IMAGE_TYPE.POST_OPERATION_IMAGE
        #     pre_type = IMAGE_TYPE.PRE_OPERATION_IMAGE
        #     topic_images = TopicImage.objects.filter(topic__diary=self,
        #                                              topic__is_online=True)
        #     pre_images = topic_images.filter(image_type=pre_type).order_by('-id')
        #     pre_images_new = self.pre_operation_images.all().order_by('-is_cover', '-id')
        #
        #     # 如果已经有术前图，则不会再覆盖
        #     if not pre_image:
        #         if pre_images:
        #             pre_image = pre_images[0].image_url
        #         if pre_images_new:
        #             pre_image = pre_images_new[0].image_url
        #
        #     # 如果已经有术后图，则不会再覆盖
        #     if not post_image:
        #         post_images = topic_images.filter(image_type=post_type).order_by(
        #             '-is_cover', '-topic__operation_date', '-id')
        #
        #         if post_images:
        #             post_image = post_images[0].image_url
        #
        # if pre_image:
        #     pre_operation_image_data = {
        #         'image': get_full_path(pre_image),
        #         'desc': 'Before'
        #     }
        #     diary_cover.append(pre_operation_image_data)
        #
        # if post_image:
        #     post_operation_image_data = {
        #         'image': get_full_path(post_image),
        #         'desc': 'After',
        #     }
        #     diary_cover.append(post_operation_image_data)
        #
        # for image in diary_cover:
        #     image_url = image['image']
        #     image.update(self._format_pic_dict(image_url))
        #
        # return diary_cover

        # 日记本封面图新逻辑,数据全部按照新版逻辑获取，潜在问题浩楠已知晓

        from talos.models.topic.topicimage import TopicImage
        base_query = Q(topic__diary=self, topic__is_online=True, topic__flag=PROBLEM_FLAG_CHOICES.NORMAL)
        diary_operation_time = self.operation_time or self.created_time

        # 获取日记本术前封面图
        if self.pre_operation_image:
            pre_image = self.pre_operation_image
        else:
            pre_operation_image = self.pre_operation_images.all().order_by("-is_cover", "-id").first()
            if pre_operation_image:
                pre_image = pre_operation_image.image_url
            else:
                query = base_query & Q(topic__operation_date__lte=diary_operation_time)
                pre_topic_image = TopicImage.objects.filter(query).order_by("topic__operation_date", "id").first()
                pre_image = pre_topic_image.image_url if pre_topic_image else ""

        # 获取日记本术后封面图
        if self.post_operation_image:
            post_image = self.post_operation_image
        else:
            query = base_query & Q(topic__operation_date__gt=diary_operation_time)
            post_topic_image = TopicImage.objects.filter(query).order_by("-topic__operation_date", "-id").first()
            post_image = post_topic_image.image_url if post_topic_image else ""

        diary_cover = []
        if pre_image:
            pre_operation_image_data = {
                'image': get_full_path(pre_image),
                'desc': 'Before'
            }
            pre_operation_image_data.update(self._format_pic_dict(pre_image))
            diary_cover.append(pre_operation_image_data)

        if post_image:
            post_operation_image_data = {
                'image': get_full_path(post_image),
                'desc': 'After',
            }
            post_operation_image_data.update(self._format_pic_dict(post_image))
            diary_cover.append(post_operation_image_data)

        return diary_cover

    @staticmethod
    def _format_pic_dict(image_url):
        data = {
            'image': get_full_path(image_url),
            'image_thumb': get_full_path(image_url, '-thumb'),
            'image_half': get_full_path(image_url, '-half'),
            'image_wide': get_full_path(image_url, '-w'),
        }
        return data

    def has_cover(self):
        return bool(self.cover)

    @property
    def has_video_cover(self):
        if self.latest_topic:
            video_url = self.latest_topic.has_video_url()
            return bool(video_url)
        else:
            return False

    @property
    def video_cover(self):
        data = {'video_pic': '', 'video_url': ''}

        if not settings.SHOW_VIDEO_COVER:
            data.update({'video_cover': ''})
            return data

        if self.latest_topic and self.latest_topic.can_video_cover:
            data = self.latest_topic.get_video_info()

        # 为客户端添加：｀video_cover｀ 字段
        data.update({'video_cover': data['video_pic']})
        return data

    @property
    def operator_is_hospital_officer(self):
        return self.doctor and self.doctor.doctor_type == DOCTOR_TYPE.OFFICER or False

    @cached_property
    def doctor(self):
        if not self.doctor_id:
            return

        doctor = DoctorService.get_doctor_from_doctor_id(self.doctor_id)
        if not doctor:
            return

        return doctor

    def tag_count(self):
        return len(self.tags)

    @cached_property
    def related_service_name(self):
        if not self.order_id:
            return None

        order = OrderService.get_order_data_for_update_diary_operation_info(order_id=self.order_id)
        if order:
            return order['service_name']
        else:
            return None

    def get_operation_info_for_topic_detail(self):
        """get diary operaiton info for topic detail.

        TODO:
            refactor topic detail page(pc, m, backend, doctor), get diary info from diary api
            instead of "api/topic"
        """
        result = {
            'operation_items': map(
                lambda x: {'tag_id': x.id, 'name': x.name, 'id': ''}, self.operation_tags
            ),
            'rating': self.rating or 0,
            'price': self.price,
            'operation_timestamp': None,
            'comment': self.comments,

            'service_id': '',
            'service_name': '',

            'hospital_name': self.raw_hospital or u'',

            'doctor_id': '',
            'doctor_name': self.raw_doctor or u'',
        }

        if self.operation_time:
            result['operation_timestamp'] = get_timestamp(self.operation_time)

        if self.order_id:
            # if diary related to an order, get doctor/service info from order
            order = OrderService.get_order_data_for_update_diary_operation_info(order_id=self.order_id)
            if order:
                result['service_id'] = order['service_id']
                result['service_name'] = order['service_name']
                result['hospital_name'] = order['hospital_name']
                result['doctor_id'] = order['doctor_id']
                result['doctor_name'] = order['doctor_name']

        else:
            # get service doctor hospital by related id(diary.doctor_id, diary.hospital_id)
            if self.doctor:
                result['doctor_id'] = self.doctor.id
                result['doctor_name'] = self.doctor.name

            if self.hospital_id:
                hospital = HospitalService.get_hospital_from_hospital_id(self.hospital_id)
                if hospital:
                    result['hospital_name'] = hospital.name

        return result

    def _set_service_info(self, info, service):
        if service is not None:
            info['service_id'] = service.id
            info['service_name'] = service.name
            info['service_short_description'] = service.short_description
            info['service_image'] = service.image_header

    def _set_doctor_info(self, info, service):
        doctor = DoctorService.get_doctor_from_doctor_id(self.doctor_id)
        if doctor is not None:
            info['doctor_id'] = doctor.id
            info['doctor_name'] = doctor.name
            info['doctor_is_online'] = doctor.is_online
            info['doctor_portrait'] = doctor.portrait
        else:
            info['doctor_id'] = ''
            info['doctor_name'] = self.raw_doctor or u''
            info['doctor_portrait'] = ''

        if info['doctor_portrait'] == '' and service is not None:
            d_id = service.doctor.id
            d = DoctorService.get_doctor_from_doctor_id(d_id)
            if d is not None:
                info['doctor_portrait'] = d.portrait
            else:
                info['doctor_portrait'] = ''

    def _set_hospital_info(self, info):
        hospital = HospitalService.get_hospital_from_hospital_id(self.hospital_id)
        if hospital is not None:
            info['hospital_id'] = hospital.id
            info['hospital_name'] = hospital.name

        else:
            info['hospital_id'] = ''
            info['hospital_name'] = self.raw_hospital or u''

    def _set_order_info(self, info):
        order = OrderService.get_order_from_order_id(self.order_id)
        if order is not None:
            s_id = order.service
            s = GoodsService.get_service_by_service_id(s_id)
            info['order_info'] = {
                'title': s.name,
                'image': s.image_header,
                'order_id': order.id,
                'validate_time': get_timestamp_or_none(order.validate_time),
            }

            info['order_id'] = order.id
            if not info['service_id']:
                ss = json.loads(order.service_snapshot)
                if ss is None:
                    logging_exception()

                info['service_id'] = ss.get('id', '')
                info['service_name'] = ss.get('name', '')
                info['service_short_description'] = ss.get('short_description', '')
                info['service_image'] = ss.get('image_header', '')
                doctor = DoctorService.get_doctor_from_doctor_id(ss.get('doctor'))
                if doctor is None:
                    info['operator_is_hospital_officer'] = False
                else:
                    info['operator_is_hospital_officer'] = True if doctor.doctor_type == DOCTOR_TYPE.OFFICER else False
        else:
            info['order_id'] = ''
            info['order_info'] = {}

    def _get_all_pre_operation_images(self):
        pre_operation_images = self.pre_operation_images.all()
        images = []
        temp_image = []
        for image in pre_operation_images:
            is_cover = False
            if self.pre_operation_image:
                if image.image_url == self.pre_operation_image or image.cover_image_url == self.pre_operation_image:
                    is_cover = True
            elif image.is_cover:
                is_cover = True

            image_info = image.get_image_info()
            image_info['is_cover'] = is_cover
            temp_image.append(get_short_path(image.image_url))
            images.append(image_info)
        new_images = batch_move_watermark_pic_to_no_watermark(temp_image, 'wanmeizhensuo', 'wanmeizhensuo-tmp')
        i = 0
        for image_info in images:
            if image_info['image_name'] in new_images:
                image_info['source_image'] = get_temp_image_path(image_info['image_name'])
            else:
                image_info['source_image'] = image_info['image']
            i += 1
        return images

    def _set_operation_image_info(self, info):
        info['pre_operation_images'] = self._get_all_pre_operation_images()

        amount = len(info['pre_operation_images'])
        info['pre_operation_image_amount'] = u'{} 张'.format(amount) if amount else u''

        if self.pre_operation_image:
            info['pre_operation_image'] = {
                'image': get_full_path(self.pre_operation_image, '-w'),
                'image_thumb': get_full_path(self.pre_operation_image, '-thumb'),
                'image_half': get_full_path(self.pre_operation_image, '-half'),
                'image_wide': get_full_path(self.pre_operation_image, '-wide'),
                'desc': ''
            }
        else:
            info['pre_operation_image'] = {}

        if self.post_operation_image:
            info['post_operation_image'] = {
                'image': get_full_path(self.post_operation_image, '-w'),
                'image_thumb': get_full_path(self.post_operation_image, '-thumb'),
                'image_half': get_full_path(self.post_operation_image, '-half'),
                'image_wide': get_full_path(self.post_operation_image, '-wide'),
                'desc': ''
            }
        else:
            info['post_operation_image'] = {}

    def _set_operation_info(self, info):
        if self.operation_time:
            info['operation_timestamp'] = get_timestamp(self.operation_time)

        if self.operation_time:
            interval = datetime.datetime.now() - self.operation_time
            if interval.days >= 0:
                info['interval'] = u'{}'.format(interval.days + 1)
            else:
                info['interval'] = u''
        else:
            info['interval'] = u''

    def operation_info(self):
        operation_item_amount = self.tag_count()
        info = {
            'operation_item_amount': u'{} 项'.format(operation_item_amount) if operation_item_amount else u'',
            # TODO: delete id:'' @594, this is only for compatible
            'operation_items': map(
                lambda x: {'tag_id': x.id, 'name': x.name, 'id': ''}, self.operation_tags
            ),
            'rating': self.rating or 0,
            'operation_effect_rating': self.operation_effect_rating or 0,
            'doctor_attitude_rating': self.doctor_attitude_rating or 0,
            'hospital_env_rating': self.hospital_env_rating or 0,
            'price': self.price,
            'operation_timestamp': None,
            'operator_is_hospital_officer': self.operator_is_hospital_officer,
            'comment_count': self.comment_count,
        }

        info['service_id'] = ''
        info['service_name'] = ''
        info['service_short_description'] = ''
        info['service_image'] = ''

        service = GoodsService.get_service_by_service_id(self.service_id)

        self._set_service_info(info, service)
        self._set_doctor_info(info, service)
        self._set_hospital_info(info)
        self._set_order_info(info)
        self._set_operation_image_info(info)
        self._set_operation_info(info)

        info['comment'] = self.comments
        info['has_topics'] = self.topics.filter(is_online=True, flag=PROBLEM_FLAG_CHOICES.NORMAL).count() > 0

        info['operation_effect_rating'] = self.operation_effect_rating
        info['doctor_attitude_rating'] = self.doctor_attitude_rating
        info['hospital_env_rating'] = self.hospital_env_rating
        info['show_comment'] = self.has_commented
        info['comment_count'] = self.comment_count

        return info

    @property
    def comments(self):
        # 可供选择的评论
        comments_choice = {
            'good': [
                {'name': u'效果非常好', 'select': 0},
                {'name': u'医生技术好', 'select': 0},
                {'name': u'医生态度好', 'select': 0},
                {'name': u'医院环境好', 'select': 0},
                {'name': u'价格超便宜', 'select': 0},
                {'name': u'性价比很高', 'select': 0},
                {'name': u'会推荐朋友', 'select': 0},
            ],
            'bad': [
                {'name': u'还挺一般的', 'select': 0},
                {'name': u'医院老推销', 'select': 0},
                {'name': u'效果不理想', 'select': 0},
            ]
        }

        if self.comment:
            return json.loads(self.comment)
        else:
            return comments_choice

    @property
    def pre_operation_images_info(self):
        return [get_full_path(i.image_url) for i in self.pre_operation_images.all()]

    def is_voted_by(self, user):
        from .diaryvote import DiaryVote
        if not user:
            return False

        try:
            DiaryVote.objects.get(user_id=user.id, diary=self)
            is_voted = True

        except DiaryVote.DoesNotExist:
            is_voted = False

        return is_voted

    @cached_property
    def latest_topic(self):
        latest_topic = self.topics.filter(
            is_online=True,
            flag=PROBLEM_FLAG_CHOICES.NORMAL
        ).select_related('video').order_by('-operation_date', '-id').first()
        # v 7.6.25 变更 日记帖取设置的术后日期离今天最近的一篇,时间相同取id最大
        return latest_topic

    @property
    def author_type(self):
        return AUTHOR_TYPE.USER

    # def get_simple_diary(self, user=None):
    #     social_info = get_social_info(user)
    #     is_following = social_info and social_info.is_following_user(uid=self.user_id) or False
    #
    #     latest_topic = self.latest_topic
    #     latest_topic_id = latest_topic and latest_topic.id or 0
    #     content = latest_topic and escape(latest_topic.answer) or ''
    #
    #     hospital = HospitalService.get_hospital_from_hospital_id(self.hospital_id)
    #     if hospital is not None:
    #         hospital_name = hospital.name
    #     else:
    #         hospital_name = self.raw_hospital or u''
    #
    #     doctor = DoctorService.get_doctor_from_doctor_id(self.doctor_id)
    #
    #     diary_author = UserService.get_user_by_user_id(self.user_id)
    #
    #     # TO DO:
    #     # diary_num 在IOS客户端全局无使用, 安卓客户端某个不确定版本已废弃
    #     # 当前最新线上版本v6.4.0,期望在某个版本迭代后将此字段删除
    #     data = {
    #         'title_style_type': self.title_style_type,
    #         'reply_num': self.reply_num,
    #         'is_following': is_following,
    #         'city': diary_author.city_name,
    #         'user_id': self.user_id,
    #         'title': self.title if self.title else '',
    #         'user_portrait': diary_author.portrait,
    #         'latest_topic_id': latest_topic_id,
    #         'diary_id': self.id,
    #         'vote_num': self.vote_num,
    #         'content': content,
    #         'user_nickname': diary_author.nickname,
    #         'author_type': AUTHOR_TYPE.USER,
    #         'tags': self.tags_new_era,
    #         'images': self.cover,
    #         'sticky_post': self.sticky_post,
    #         'membership_level': diary_author.membership_level,
    #         'view_num': self.view_num,
    #         'diary_amount': self.extra_info.topic_count if hasattr(self, 'extra_info') else 0,
    #         'is_voted': self.is_voted_by(user),
    #         'vote_num_gained': diary_author.vote_count,
    #         'topic_num_posted': diary_author.topic_count,
    #         'diary_num': self.topic_num,
    #         'doctor_id': self.doctor_id,
    #         'doctor_name': doctor and doctor.name,
    #         'hospital_name': hospital_name,
    #         'created_time': get_timestamp_or_none(self.created_time),
    #         # TO DO:
    #         # 以下字段为本次上线需要兼容backend做的冗余,下次迭代需删除
    #         'is_identification': self.is_identification,
    #         'tags_new_era': self.tags_new_era,
    #         'date': get_timestamp_or_none(self.last_modified),
    #         'user': {
    #             'vote_num_gained': diary_author.vote_count,
    #             'topic_num_posted': diary_author.topic_count,
    #             'portrait': diary_author.portrait,
    #             'user_name': diary_author.nickname,
    #             'membership_level': diary_author.membership_level,
    #             'city': diary_author.city_name,
    #             'user_id': self.user_id,
    #         },
    #         'user_level': {
    #             'membership_icon': user.membership_icon if user and user.membership_icon else '',
    #             'level_icon': user.level_icon if user and user.level_icon else '',
    #             'constellation_icon': user.constellation_icon if user and user.constellation_icon else '',
    #         },
    #         # 以下为兼容医生版的字段, 下次迭代需跟医生版上来商量删除
    #         'tags_info': [],
    #         'rating': self.rating,  # 给美购的评分
    #     }
    #     return data
    #
    # def get_diary_info(self, simple=False, user=None):
    #     # NOTE: if simple is True, operation info wont be return
    #     #       all diary list should call this method with simple=True
    #     social_info = None
    #     if user:
    #         from social import SocialInfo
    #         social_info = SocialInfo(uid=user.id)
    #
    #     doctor = DoctorService.get_doctor_from_doctor_id(self.doctor_id)
    #
    #     diary_author = UserService.get_user_by_user_id(user_id=self.user_id)
    #     diary_data = {
    #         'user': {
    #             'user_id': self.user_id,
    #             'user_name': diary_author.nickname,
    #             'portrait': diary_author.portrait,
    #             'city': diary_author.city_name,
    #             'membership_level': diary_author.membership_level,
    #             'doctor_id': '',
    #             'hospital_id': '',
    #             'vote_num_gained': diary_author.vote_count,
    #             'topic_num_posted': diary_author.topic_count,
    #         }
    #     }
    #
    #     user_bz = UserService.get_doctor_hospital_id_by_user_id(self.user_id)
    #     if user_bz:
    #         diary_data['user_id'] = user_bz['user_id']
    #         diary_data['doctor_id'] = user_bz['doctor_id']
    #         diary_data['hospital_id'] = user_bz['hospital_id']
    #
    #     diary_data['raw_doctor'] = self.raw_doctor if self.raw_doctor else ''
    #     diary_data['raw_hospital'] = self.raw_hospital if self.raw_hospital else ''
    #     diary_data['diary_id'] = self.id
    #     diary_data['diary_amount'] = self.topics.filter(is_online=True).count()
    #     diary_data['reply_num'] = self.reply_num
    #     diary_data['reply_num_for_diary'] = self.topicreply_set.filter(is_online=True).count()
    #     diary_data['vote_num'] = self.vote_num
    #     diary_data['view_num'] = self.view_num
    #
    #     # get doctor info
    #     hospital = HospitalService.get_hospital_from_hospital_id(self.hospital_id)
    #
    #     diary_data['doctor_id'] = self.doctor_id or ''
    #     diary_data['doctor_name'] = doctor and doctor.name or ''
    #     diary_data['hospital_name'] = hospital and hospital.name or ''
    #     diary_data['hospital_id'] = self.hospital_id or ''
    #
    #     latest_topic = self.topics.filter(
    #         is_online=True,
    #         flag=PROBLEM_FLAG_CHOICES.NORMAL
    #     ).last()
    #
    #     diary_data.update(self.video_cover())
    #
    #     order = OrderService.get_order_from_order_id(self.order_id)
    #     if order is not None and order.cash_back_status == CASH_BACK_STATUS.SUCCESS:
    #         is_cash_back = True
    #     else:
    #         is_cash_back = False
    #
    #     diary_data.update({
    #         'images': self.cover,
    #         'title': self.title if self.title else '',
    #         'last_modified': get_timestamp_or_none(self.last_modified),
    #         'created_time': get_timestamp_or_none(self.created_time),
    #         'is_identification': self.is_identification,
    #         'is_headline': self.is_headline,
    #         'is_essence': self.is_essence,
    #         'is_online': self.is_online,
    #         'is_sink': self.is_sink,
    #         'is_cash_back': is_cash_back,
    #         'is_favored': self.favor_diary_diary.filter(user_id=user.id, is_deleted=False).exists() if user else False,
    #         'is_following': social_info and social_info.is_following_user(uid=self.user_id) or False,
    #         'latest_topic_id': latest_topic and latest_topic.id or 0,
    #
    #         'tags_new_era': self.tags_new_era,
    #         'tags': self.wiki_info,
    #         'zones': [],
    #         'tags_info': [],
    #
    #         'is_voted': self.is_voted_by(user),
    #         'sticky_post': self.sticky_post,
    #     })
    #
    #     author_type = self.author_type
    #
    #     diary_data.update({
    #         'title_style_type': self.title_style_type,
    #         'author_type': author_type,
    #         'content': latest_topic and escape(latest_topic.answer) or '',
    #         'date': get_timestamp_or_none(self.last_modified),
    #     })
    #
    #     if simple:
    #         return diary_data
    #
    #     diary_data['operation_info'] = self.operation_info()
    #     return diary_data

    @property
    def extra_diary_images(self):
        return [get_full_path(topic.image_url) for topic in self.topics.last().images.all()]

    def newest_cover(self):
        """ v5.3.0 获取日记本最新的帖子的图片 作为封面
        规则:
        1.最新的帖子
        2.术后图
        3.术前图
        """
        topics = self.topics.all().order_by('-created_time')
        image = settings.DIARY_COVER_DEFAULT
        for topic in topics:
            images = topic.images.all()
            if images:
                image = images[0].image_url
                break
        return image

    def get_simple_tags(self):
        tags = self.tags
        return tags[0:4]

    def simple_data(self):
        """ v5.3.0
        """
        is_service_diary = False
        tags = [t.name for t in self.get_simple_tags()]

        service = GoodsService.get_service_by_service_id(self.service_id)
        if service:
            tags = [service.name]
            is_service_diary = True

        return {
            'is_service_diary': is_service_diary,
            'id': self.id,
            'topics_num': self.topics.filter(is_online=True, flag=PROBLEM_FLAG_CHOICES.NORMAL).count(),
            'tags': tags,
            'title': self.title,
            'image': self.newest_cover(),
            'created_time': get_timestamp(self.created_time),
            'last_modified': get_timestamp(self.last_modified),
            'review_count': self.review_count,
            'vote_count': self.vote_num,
            'comment_count': self.comment_count if self.order_id is not None else 0,
            'type': VOTEOBJECT.DIARY,
        }

    def topics_data(self):
        topics = []
        for topic in self.topics.filter(is_online=True, flag=PROBLEM_FLAG_CHOICES.NORMAL):
            topics.append(
                {
                    "id": topic.id,
                    "title": topic.get_title(),
                    "review_status": topic.review_status,
                    "review_reason": PROBLEM_REVIEW_STATUS_CHOICES.getDesc(topic.review_status)
                }
            )
        return topics

    @property
    def cashback_topic_num_limit(self):
        service = GoodsService.get_service_by_service_id(self.service_id)
        if service:
            # self.service 不是NoneType时
            return service.cashback_limit
        else:
            return 0

    @property
    def review_count(self):
        return self.topics.filter(review_status=PROBLEM_REVIEW_STATUS_CHOICES.OK, is_online=True).count()

    @property
    def diary_first_topic(self):
        return self.topics.filter(is_online=True, flag=PROBLEM_FLAG_CHOICES.NORMAL).order_by('created_time').first()

    @property
    def view_num(self):
        # todo 7675 上线后，可删
        num1 = diary_pv_cache.get(self.id)
        num2 = sum(int(topic.view_num) for topic in self.topics.all())
        if num1 is None:
            num1 = 0
        if num2 is None:
            num2 = 0
        return str(int(num1) + int(num2))

    @cached_property
    def topic_num(self):
        num = self.topics.filter(flag=PROBLEM_FLAG_CHOICES.NORMAL, is_online=True).count()
        return num

    @property
    def get_diary_operate(self):
        from .diaryoperate import DiaryOperate
        '''
        :return: 用户的更新操作
        '''
        if self.audit_time is not None:
            audit_time = self.audit_time
        else:
            audit_time = datetime.datetime.fromtimestamp(0)

        update_info_list = DiaryOperate.objects.filter(
            diary__id=self.id,
            operate_time__gte=audit_time,
            operation=DIARY_OPERATE.UPDATE_INFO,
        ).values('topic').annotate(Count('topic'))

        update_topic_list = DiaryOperate.objects.filter(
            diary__id=self.id,
            operate_time__gte=audit_time,
            operation=DIARY_OPERATE.UPDATE_TOPIC,
        ).values('topic').annotate(Count('topic'))

        delete_topic_list = DiaryOperate.objects.filter(
            diary__id=self.id,
            operate_time__gte=audit_time,
            operation=DIARY_OPERATE.DELETE_TOPIC,
        ).values('topic').annotate(Count('topic'))

        add_topic_list = DiaryOperate.objects.filter(
            diary__id=self.id,
            operate_time__gte=audit_time,
            operation=DIARY_OPERATE.ADD_TOPIC,
        ).values('topic').annotate(Count('topic'))

        read = u''

        if len(update_info_list) != 0:
            read += u'更新术前资料\n'
        if len(update_topic_list) != 0:
            read += u'修改%s篇帖子\n' % str(len(update_topic_list))
        if len(delete_topic_list) != 0:
            read += u'删除%s篇帖子\n' % str(len(delete_topic_list))
        if len(add_topic_list) != 0:
            read += u'新增%s篇帖子\n' % str(len(add_topic_list))

        return read[:-1]

    def set_diary_operate(self, operation, topic=''):
        from .diaryoperate import DiaryOperate
        if operation in DIARY_OPERATE:
            diary_operate = DiaryOperate()
            diary_operate.diary_id = self.id
            diary_operate.operate_time = datetime.datetime.now()
            diary_operate.operation = operation
            diary_operate.topic = topic
            diary_operate.save()
            if self.audit_status != DIARY_AUDIT_STATUS.UNAUDITED:
                self.audit_status = DIARY_AUDIT_STATUS.REAUDIT
                self.save()

    @cached_property
    def tags(self):
        # 日记本关联的tag数量有限的话 可以这么做
        from .diarytag import DiaryTag
        tag_ids = DiaryTag.objects.filter(diary_id=self.id).values_list('tag_id', flat=True)
        tag_ids = list(tag_ids)
        tags = TagService.get_tags_by_tag_ids(tag_ids)
        tags = self.tags_sort_for_special(tags)
        return tags or []

    @cached_property
    def all_tags(self):
        # 日记本关联的tag数量有限的话 可以这么做
        from .diarytag import DiaryTag
        tag_ids = DiaryTag.objects.filter(diary_id=self.id).values_list('tag_id', flat=True)
        tag_ids = list(tag_ids)
        tags = TagService.get_tags_by_tag_ids(tag_ids)
        return tags or []

    def add_tags(self, tag_ids):
        from .diarytag import DiaryTag
        for tag_id in tag_ids:
            DiaryTag.objects.get_or_create(diary_id=self.id, tag_id=tag_id)

    def upd_tags(self, tag_ids):
        new_tags = set([int(tag_id) for tag_id in tag_ids if str(tag_id).isdigit()])
        old_tags = set([tag.id for tag in self.all_tags])
        self.add_tags(list(new_tags - old_tags))
        self.del_tags(list(old_tags - new_tags))

    def del_tags(self, tag_ids):
        from .diarytag import DiaryTag
        DiaryTag.objects.filter(diary_id=self.id, tag_id__in=tag_ids).delete()

    def delete_all_tags(self):
        from .diarytag import DiaryTag
        DiaryTag.objects.filter(diary_id=self.id).delete()

    @property
    def is_operation(self):
        if not self.order_id:
            return False

        order = OrderService.get_order_data_for_update_diary_operation_info(order_id=self.order_id)
        if order:
            return order['is_operation']
        else:
            return False


class Problems(models.Model):
    """
        问题
        """

    class Meta:
        verbose_name = u'问题'
        verbose_name_plural = u'问题'
        app_label = 'talos'
        db_table = 'api_problem'

    user_id = models.IntegerField(verbose_name=u'用户ID', max_length=11)
    answer = models.TextField(verbose_name="内容", blank=True, default="")
    topic_type = models.CharField(verbose_name="类型", max_length=10)
    diary_id = models.IntegerField(verbose_name="日记ID", max_length=11)
    last_modified = models.DateTimeField(verbose_name=u'最后修改时间', default=datetime.datetime.fromtimestamp(0))
    is_online = models.BooleanField(verbose_name=u'是否上线', default=True, db_index=True)
    created_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True, null=True, blank=True)


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 CpcPromote(models.Model):
    class Meta:
        db_table = 'cpc_community_communitypromote'

    doctor_id = models.CharField(max_length=100)
    merchant_id = models.CharField(max_length=64)
    communitycpc_id = models.IntegerField()
    budget = models.IntegerField()
    click_price = models.IntegerField()
    start_time = models.DateTimeField(verbose_name=u'起始时间')
    end_time = models.DateTimeField(verbose_name=u'结束时间')
    is_delay = models.IntegerField()
    is_suspend = models.IntegerField()
    create_time = models.DateTimeField(verbose_name=u'创建时间')
    is_promote = models.IntegerField()
    promote_flag = models.IntegerField()
    backup_daily_click = models.IntegerField()
    start_hour = models.IntegerField()
    end_hour = models.IntegerField()


class CpcCommunity(models.Model):
    class Meta:
        db_table = 'cpc_community_communitycpc'

    related_id = models.CharField(max_length=100)
    related_type = models.IntegerField()


class ReductionWeight(models.Model):
    class Meta:
        db_table = 'reduction_weight_content'

    card_type = models.CharField(max_length=100)
    reason_type = models.CharField(max_length=100)
    date = models.CharField(max_length=100)


class HighQualityContent(models.Model):
    class Meta:
        db_table = 'high_quality_content'

    id = models.TextField(verbose_name="卡片id", primary_key=True, blank=True, default="")
    card_type = models.TextField(verbose_name="卡片类型", blank=True, default="")


class ApiDiaryScore(models.Model):
    class Meta:
        db_table = 'api_diary_score'

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