# coding=utf8

from __future__ import unicode_literals, absolute_import, print_function

import datetime

import pili
from django.conf import settings
from django.db import models
from django.db import transaction
from django.utils import timezone
from gm_types.gaia import TOPIC_TYPE, LIVE_MSG_TYPE, LIVE_STATUS
from gm_upload import ImgUrlField, IMG_TYPE

from talos.backbone.rpc import logging_exception
from talos.cache.base import live_view_max_cache
from talos.cache.base import live_view_num_cache, live_user_enter_time_cache
from talos.cache.base import live_view_sum_cache
from talos.libs.datetime_utils import ts_now_as_score
from talos.libs.image_utils import get_full_path
from talos.models.topic.problemtag import ProblemTag
from talos.models.topic.topic import Problem
from talos.services.tag import TagService
from talos.services.user import UserService

from talos.services.goods import GoodsService
from talos.services.hospital import HospitalService
from talos.services.doctor import DoctorService


class ShortvideoBlackList(models.Model):
    class Meta:
        verbose_name = u'小视频黑名单'
        app_label = 'api'
        db_table = 'api_shortvideo_black_list'

    user_id = models.IntegerField(verbose_name=u'小视频用户名')
    is_online = models.BooleanField(verbose_name=u'是否生效')


class LiveChannel(models.Model):
    class Meta:
        verbose_name = u'直播频道'
        app_label = 'talos'
        db_table = 'api_live_channel'

    person_id = models.CharField(verbose_name=u'用户外键id', max_length=64)
    created_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    updated_time = models.DateTimeField(verbose_name=u'更新时间', default=timezone.now)
    title = models.CharField(verbose_name=u'标题', max_length=128, default='')
    cover_url = models.CharField(verbose_name=u'封面地址', max_length=128, default='')
    status = models.BooleanField(verbose_name='是否直播', default=False)

    def data(self, user):
        stream = self.now_stream
        return stream.data(user)

    @property
    def now_stream(self):
        return self.streams.order_by('-id').first()

    @property
    def live_view_num(self):
        return self.now_stream.live_view_num

    def add_view_num(self):
        return self.now_stream.add_view_num()

    def sub_view_num(self):
        return self.now_stream.sub_view_num()


class LiveStream(models.Model):
    class Meta:
        verbose_name = u'直播流'
        app_label = 'talos'
        db_table = 'api_live_stream'

    channel = models.ForeignKey(LiveChannel, null=True, related_name=u'streams')
    status = models.BooleanField(verbose_name='是否直播', default=False)
    created_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
    updated_time = models.DateTimeField(verbose_name=u'更新时间', default=timezone.now)
    stream_key = models.CharField(verbose_name=u'直播流的key', max_length=128, default='', db_index=True)
    save_replay_url = models.CharField(verbose_name=u'直播流的回放地址', max_length=128, default='', db_index=True)

    title = models.CharField(verbose_name=u'标题', max_length=128, default='')
    cover_url = models.CharField(verbose_name=u'封面地址', max_length=128, default='')
    topic = models.OneToOneField(Problem, related_name=u'stream', null=True)

    is_finish = models.BooleanField(verbose_name='是否关闭', default=False)
    # 这个字段是给统计使用
    max_view_num = models.IntegerField(verbose_name=u'最大在线人数', default=0)

    # 弹幕回放
    replay_danmu = models.TextField(verbose_name=u'弹幕回放')

    # 美购相关
    hospital_id = models.CharField(verbose_name=u'医院外建', null=True, max_length=100)
    service_id = models.CharField(verbose_name=u'美购外建', null=True, max_length=100)

    @property
    def live_status_stream(self):
        if self.is_finish:
            return False

        timedetla = datetime.datetime.now() - self.updated_time
        if timedetla.seconds > settings.LIVE_TIME_OUT and self.status is False:
            return False

        if timedetla.seconds < settings.LIVE_TIME_OUT and self.status is False:
            return True

        return self.status

    @property
    def live_status(self):
        if self.live_status_stream:
            return LIVE_STATUS.LIVE
        else:
            return LIVE_STATUS.NOLIVE

    def data(self, user):
        social_info = None
        if user:
            from social import SocialInfo
            social_info = SocialInfo(uid=user.id)
        self_user = UserService.get_user_by_person_id(self.channel.person_id)
        is_following = social_info and social_info.is_following_user(uid=self_user.id) or False

        channel = self.channel

        return {
            "id": self.id,
            "user_portrait": self_user.portrait,
            "uname": self_user.nickname,
            'title': self.title,
            'audience_num': channel.live_view_num,
            'is_following': is_following,
            'url': self.url,
            'cover_url': get_full_path(self.cover_url, '-w'),
            'user_id': self_user.id,
            'status': self.live_status,
            'm_url': self.m_url,
            'stream_id': self.id,
            'tags': self.get_tags(),
            'channel_id': channel.id,
            'membership_level': self_user.membership_level,
            'user_level': {
                'membership_icon': self_user.membership_icon,
                'level_icon': self_user.level_icon,
                'constellation_icon': self_user.constellation_icon,
            },
        }

    def replay_data(self, user):
        data = self.data_live(user)
        data['status'] = self.live_status
        data['url'] = settings.QINIU_REPLAY_LIVE_DOMAIN + self.save_replay_url
        data['topic_id'] = self.topic.id

        view_num = int(self.topic.view_num)
        data['audience_num'] = str(view_num + self.live_view_num)

        return data

    def get_topic_reply_info(self):
        return {
            'source': settings.QINIU_REPLAY_LIVE_DOMAIN + self.save_replay_url,
            'cover': get_full_path(self.cover_url, '-w'),
            'content': self.title
        }

    @property
    def url(self):
        return pili.rtmp_play_url(settings.QINIU_LIVE_DOMAIN,
                                  settings.QINIU_HUB_NAME, self.stream_key)

    @property
    def m_url(self):
        return pili.hls_play_url(settings.QINIU_LIVE_DOMAIN,
                                 settings.QINIU_HUB_NAME, self.stream_key)

    @property
    def live_view_num(self):
        try:
            num = live_view_num_cache.get(str(self.id))
            if num:
                num = int(num)
                return self.display_num(num)
            else:
                return 0
        except ValueError:
            return 0

    def display_num(self, num):
        if 0 < num <= 10:
            result = num
        elif 10 < num <= 50:
            result = num * 53
        elif num > 50:
            result = num * 103
        else:
            result = 0
        return int(result + self.get_addition_view_num())

    @property
    def tags(self):
        tag_ids = LiveStreamTag.objects.filter(live_stream_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

    def get_tags(self):
        """problems's tags."""
        ts = []
        for tag in self.tags:
            data = {'name': tag.name, 'tag_id': tag.id}
            ts.append(data)
        return ts

    def set_first_user_enter_time_cache(self):
        start_time = ts_now_as_score()
        if not live_user_enter_time_cache.get(str(self.id)):
            live_user_enter_time_cache.set(str(self.id), start_time)

    def clear_redis_info(self):
        from talos.manager.livemsg import LiveMsgManager
        live_msg_manager = LiveMsgManager()
        live_msg_manager.clear_redis(self.id)
        # 删除统计相关星系
        self.max_view_num = live_view_max_cache.get(str(self.id))
        self.save()
        live_view_max_cache.delete(str(self.id))
        live_view_sum_cache.delete(str(self.id))

    def add_view_num(self):
        try:
            live_view_num_cache.incr(str(self.id), 1)
            live_view_sum_cache.incr(str(self.id))
            self.set_live_view_max_num()
        except:
            logging_exception()

    def get_addition_view_num(self):
        result = 0
        start_time = live_user_enter_time_cache.get(str(self.id))
        if not start_time:
            return 0
        now_time = ts_now_as_score()
        if start_time:
            num = int(now_time) - int(start_time)
            if num <= 0:
                result = 0
            elif 1 <= num <= 300:
                result = num * 34
            elif 301 <= num <= 600:
                result = int(32.78 * num + 333.22)
            elif 601 <= num <= 1200:
                result = int(8.35 * num + 14982.87)
            elif num >= 1200:
                result = 25003
        return result

    def set_live_view_max_num(self):
        try:
            num = live_view_max_cache.get(str(self.id))
            now_num = live_view_num_cache.get(str(self.id))
            if num and now_num and int(num) < int(now_num):
                live_view_max_cache.set(str(self.id), now_num)
            elif int(now_num):
                live_view_max_cache.set(str(self.id), now_num)
        except ValueError:
            logging_exception()

    def sub_view_num(self):
        try:
            num = live_view_num_cache.decr(str(self.id))
            if num <= 0:
                live_view_num_cache.incr(str(self.id))
        except:
            logging_exception()

    def set_status(self, flag):
        now = datetime.datetime.now()
        channel = self.channel
        with transaction.atomic():
            self.status = flag
            channel.status = flag
            self.updated_time = now
            channel.updated_time = now
            self.save(update_fields=['status', 'updated_time'])
            channel.save(update_fields=['status', 'updated_time'])

    def data_live(self, user):
        result = self.data(user)
        hospital_data = {}
        if self.hospital_id:
            hospital = HospitalService.get_hospital_info_by_hospital_id(self.hospital_id)
            if hospital:
                hospital_data = hospital
                hospital_data['portrait'] = get_full_path(hospital['portrait'], '-half')
        result['hospital'] = hospital_data
        result['show_hospital'] = True if hospital_data else False
        service_data = {}
        if self.service_id:
            service = GoodsService.get_live_service_info_by_id(self.service_id)
            if service:
                service_data = service
        result['service'] = service_data
        result['show_service'] = True if service_data else False
        result['is_doctor'] = DoctorService.if_person_is_doctor(self.channel.person_id)
        return result


class LiveStreamTag(models.Model):
    class Meta:
        app_label = 'talos'
        db_table = 'api_streamtag'

    live_stream = models.ForeignKey(LiveStream)
    tag_id = models.IntegerField()

    def __unicode__(self):
        return "%s:%d" % (self.tag_id, self.live_stream_id)


class LiveWhiteList(models.Model):
    class Meta:
        verbose_name = u'直播白名单'
        app_label = 'talos'
        db_table = 'api_live_white_list'

    user_id = models.IntegerField(verbose_name=u'用户外键id')
    is_online = models.BooleanField(verbose_name=u'是否生效')


class LiveMsg(models.Model):
    class Meta:
        verbose_name = u'弹幕数据'
        app_label = 'talos'
        db_table = 'api_live_msg'

    person_id = models.CharField(verbose_name=u'用户外键id', max_length=64)
    stream = models.ForeignKey(LiveStream)
    msg = models.CharField(verbose_name=u'标题', max_length=128, default='')
    created_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now, db_index=True)
    type = models.IntegerField(verbose_name=u'消息类型', default=LIVE_MSG_TYPE.TEXT_MSG)
    is_vest_send = models.BooleanField(verbose_name=u'是否为马甲用户发送', default=False)

    def data(self):
        if self.type == int(LIVE_MSG_TYPE.NOTIFI_MSG):
            uname = ''
        else:
            self_user = UserService.get_user_by_person_id(self.person_id)
            uname = self_user.nickname

        return {
            'id': self.id,
            'text': self.msg,
            'name': uname,
            'type': self.type
        }


class ZhiboConfig(models.Model):
    class Meta:
        verbose_name = u'直播配置信息'
        verbose_name_plural = u'直播配置信息'
        db_table = 'api_zhiboconfig'
        app_label = 'talos'

    description = models.CharField(max_length=10, verbose_name=u'描述')
    foreshowcover_img = ImgUrlField(img_type=IMG_TYPE.ZHIBO, max_length=128, verbose_name=u'预告封面图片')
    foreshowpage_img = ImgUrlField(img_type=IMG_TYPE.ZHIBO, max_length=128, verbose_name=u'预告页面图片')
    # 首页Feed流所需图片
    trailer_image = ImgUrlField(img_type=IMG_TYPE.ZHIBO, max_length=128, verbose_name=u'首页直播预告')
    cover_image = ImgUrlField(img_type=IMG_TYPE.ZHIBO, max_length=128, verbose_name=u'首页直播封面')
    anchor_user_id = models.IntegerField(verbose_name=u'用户外键id')
    start_time = models.DateTimeField(verbose_name=u'开始时间')
    end_time = models.DateTimeField(verbose_name=u'结束时间')
    zhibo_time = models.DateTimeField(verbose_name=u'直播时间')
    is_online = models.BooleanField(default=False, verbose_name=u'是否上线')
    is_shouyejingxuan = models.BooleanField(default=False, verbose_name=u'是否在首页－精选显示')
    is_shouyezhibo = models.BooleanField(default=False, verbose_name=u'是否在首页－直播显示')
    is_zhiboliebiao = models.BooleanField(default=False, verbose_name=u'是否在直播列表页显示')
    adorder_id = models.CharField(max_length=12, verbose_name=u'广告订单ID', null=True)
    # 完整描述 2017-05-15
    full_desc = models.CharField(max_length=500, verbose_name=u'完整描述', default='')

