#!/usr/bin/env python
# coding=utf-8

from __future__ import unicode_literals, absolute_import, print_function

import json

from django.conf import settings
from django.contrib.auth.models import User
from django.db import models
from django.db import transaction
from django.db.models import Count
from gm_types.doctor import DOCTOR_LICENCE_TYPE, HOSPITAL_MEDICAL_TYPE, HOSPITAL_LEVEL
from gm_types.doctor import HOSPITAL_SCALE
from gm_types.gaia import DOCTOR_TYPE, HOSPITAL_TYPE, VIDEO_CODE_STATUS
from gm_upload import IMG_TYPE, ImgUrlField

from api.models.area import City
from api.models.bodypartsubitem import BodyPartSubItem
from api.tool.image_utils import get_full_path
from rpc.cache import doctor_tags_cache, hospital_search_tags_cache, hospital_sell_amount_cache, \
    hospital_service_tags_distribution_cache
from search.utils.diary import filter_diary
from services.custom_phone_service import PhoneService
from utils.uuid4 import uuid4
from rpc.context import get_rpc_remote_invoker

rpc_invoker = get_rpc_remote_invoker()


class Hospital(models.Model):
    class Meta:
        verbose_name = u'30. 医院'
        verbose_name_plural = u'30. 医院'
        db_table = 'api_hospital'
        app_label = 'api'

    id = models.CharField(max_length=100, primary_key=True, default=uuid4)
    name = models.CharField(max_length=100, unique=True, help_text=u"医院名称")
    alias_name = models.CharField(max_length=100, help_text=u"医院别名", default='')

    # licence两个字段废弃，see _licence_images 20170215
    business_licence = ImgUrlField(img_type=IMG_TYPE.HOSPITAL, max_length=400, help_text=u"营业执照", default='')
    practice_licence = ImgUrlField(img_type=IMG_TYPE.HOSPITAL, max_length=400, help_text=u"医疗机构许可证", default='')
    query_image = ImgUrlField(img_type=IMG_TYPE.HOSPITAL, max_length=400, help_text=u"查询到的图片", blank=True, default='')

    portrait = ImgUrlField(img_type=IMG_TYPE.HOSPITAL, max_length=400, help_text=u"医院头像", blank=True, default='')
    location = models.CharField(max_length=100, help_text=u"地址")
    city = models.ForeignKey(City, verbose_name=u"城市", null=True, blank=True, default=None)
    user = models.OneToOneField(User, default=None, null=True, blank=True)
    body_sub_items = models.ManyToManyField(BodyPartSubItem, blank=True, verbose_name=u'整形细分项目')

    sms_phone = models.CharField(max_length=11, null=True, blank=True, default=None, verbose_name=u'接收短信的号码')
    desk_phone = models.CharField(max_length=20, null=True, blank=True, default=None, verbose_name=u'联系电话（座机）')
    phone_ext = models.CharField(u"分机", max_length=20, null=True, blank=True, default="")
    accept_private_msg = models.BooleanField(default=False, verbose_name=u"是否接受私信")

    google_loc_lng = models.FloatField(default=0, help_text=u"经度(-180~180)")
    google_loc_lat = models.FloatField(default=0, help_text=u"纬度")
    baidu_loc_lng = models.FloatField(default=0, help_text=u"经度(-180~180)")
    baidu_loc_lat = models.FloatField(default=0, help_text=u"纬度")

    description = models.TextField(default=u"", null=True, blank=True, verbose_name=u"医院介绍")
    qualification = models.CharField(default=u"", max_length=100, help_text=u"资质")
    notes = models.CharField(max_length=100, help_text=u"备注", default=u"", null=True, blank=True, verbose_name=u'备注')
    hospital_type = models.CharField(max_length=1, verbose_name=u'医院类型', null=False, blank=False,
                                     default=HOSPITAL_TYPE.PUBLIC, choices=HOSPITAL_TYPE, db_index=True)

    doctor_reply_limit = models.IntegerField(verbose_name=u'医生回复限制', default=3)
    created_time = models.DateTimeField(u"医院生成时间", auto_now_add=True)

    doctor_num = models.IntegerField(verbose_name=u'医生数', default=0)
    share_topic_num = models.IntegerField(verbose_name=u'案例数', default=0)
    is_recommend = models.BooleanField(verbose_name=u'是否推荐', default=False)
    rate = models.FloatField(default=5.0, help_text=u"用户综合评分")
    effect_rating = models.FloatField(default=5.0, help_text=u"用户综合评分")
    attitude_rating = models.FloatField(default=5.0, help_text=u"用户综合评分")
    env_rating = models.FloatField(default=5.0, help_text=u"用户综合评分")

    chief_ph_count = models.IntegerField('主任医师数量', default=0)
    associate_chief_ph_count = models.IntegerField('副主任医师数量', default=0)
    ph_in_charge_count = models.IntegerField('主治医师数量', default=0)
    resident_ph_count = models.IntegerField('住院医师数量', default=0)
    ph_count = models.IntegerField('医师数量', default=0)
    area_count = models.IntegerField('医院平米', default=0)
    city_count = models.IntegerField('开设医院城市数', default=0)
    chain_count = models.IntegerField('连锁医院开设数', default=0)
    operation_room_count = models.IntegerField('手术室数量', default=0)
    injection_room_count = models.IntegerField('注射室数量', default=0)
    laser_room_count = models.IntegerField('激光治疗室数量', default=0)
    is_high_quality = models.BooleanField('是否精品诊所', default=False)
    level = models.CharField('医院分级', max_length=4)
    is_online = models.BooleanField(default=False, help_text=u"是否上线", verbose_name=u"上线")

    @classmethod
    def get_online_hospital_by_id(cls, hospital_id):
        return cls.objects.filter(id=hospital_id).first()

    def get_hospital_replied_problems_count(self, doctor_id):
        """
        查询给定机构回答的问题的数目

        """
        from django.db import connection

        cursor = connection.cursor()
        SQL = "SELECT distinct problem_id FROM api_topicreply a WHERE doctor_id = '%s' and not exists(select 1 " \
              "from api_problem where id=a.problem_id and private_status!='0')" % doctor_id
        return cursor.execute(SQL)

    @property
    def share_diary_num(self):
        """ 4.1.0 开始使用日记本统计案例数
        :return:
        """
        return filter_diary(filters={'hospital_id': self.id}, expose_total=True)['total']

    @property
    def share_diary_topic_num(self):
        '''
        获取医院下的日记帖数量
        '''
        res = rpc_invoker['diary/diary_filter_info'](hospital_id=self.id).unwrap()
        if res:
            return res['topic_count']
        return 0

    @property
    def recommend_services(self):
        recomend_service_list = HospitalRecommendService.objects.filter(
            hospital_id=self.id).values_list('service_id', flat=True)
        from api import Service
        services = Service.objects.filter(id__in=recomend_service_list)
        return [{
                    'id': item.id,
                    'name': item.name,
                    'is_online': item.is_online
                } for item in services]

    @property
    def recommend_doctors(self):
        recommend_doctor_list = HospitalRecommendDoctor.objects.filter(
            hospital_id=self.id).values_list('doctor_id', flat=True)
        from hippo.models import Doctor
        doctors = Doctor.objects.filter(id__in=recommend_doctor_list)
        return [{
                    'id': item.id,
                    'name': item.name,
                    'is_online': item.is_online
                } for item in doctors]

    @transaction.atomic
    def update_recommend_services(self, service_ids):
        HospitalRecommendService.objects.filter(hospital=self).delete()
        [HospitalRecommendService.objects.create(hospital=self, service_id=x) for x in service_ids]

    @transaction.atomic
    def update_recommend_doctors(self, doctor_ids):
        HospitalRecommendDoctor.objects.filter(hospital=self).delete()
        [HospitalRecommendDoctor.objects.create(hospital=self, doctor_id=x) for x in doctor_ids]

    @property
    def video_info(self):
        try:
            video = HospitalVideo.objects.get(hospital_id=self.id)
            return video.get_video_info()
        except HospitalVideo.DoesNotExist:
            return {'video_pic': '', 'video_url': ''}

    def get_doctor_item_list(self, doctor_id=0):
        result = doctor_tags_cache.get(doctor_id)
        item_list_raw = []
        item_list = []

        if not result:
            pass
        else:
            try:
                result = json.loads(result)
                item_list = result['item_list']
                item_list_raw = result['item_list_raw']
            except:
                pass

        return (item_list, item_list_raw)

    def get_hospital_portrait(self):
        doctor = self.officer
        if doctor:
            if doctor.portrait:
                portrait = get_full_path(doctor.portrait)
            else:
                portrait = get_full_path(u'img%2Fyiyuan.png')
        else:
            if self.portrait:
                portrait = get_full_path(self.portrait)
            else:
                portrait = get_full_path(u'img%2Fyiyuan.png')
        return portrait

    def hospital_detail(self, user=None):
        """
        在机构列表中将hospital的信息转换成为机构信息
        @param self:
        @return:
        """
        try:
            phone_ext = ''
            accept_private_msg = False
            accept_call = False
            star = 0.0
            doctor = self.officer

        except models.ObjectDoesNotExist:
            user_id = None
            doctor_id = None

        else:
            if doctor:
                doctor_id = doctor.id
                user_id = doctor.user and doctor.user.id or ''
                accept_private_msg = doctor.accept_private_msg
                accept_call = doctor.accept_call
                phone_ext = doctor.phone_ext
                star = doctor.rate
            else:
                user_id = None
                doctor_id = None

        if doctor_id:
            item_list, item_list_raw = self.get_doctor_item_list(doctor_id)
        else:
            item_list = []
            item_list_raw = []

        if user:
            from social import SocialInfo
            social_info = SocialInfo(uid=user.id)

        if doctor:
            if doctor.portrait:
                portrait = get_full_path(doctor.portrait)
            else:
                portrait = get_full_path(u'img%2Fyiyuan.png')
        else:
            if self.portrait:
                portrait = get_full_path(self.portrait)
            else:
                portrait = get_full_path(u'img%2Fyiyuan.png')

        share_diary_num = self.share_diary_num
        result = {
            "id": self.id,
            "user_id": user_id,
            "doctor_id": doctor_id,
            "name": self.name,
            'hospital_type': self.hospital_type,
            "qualification": self.qualification,
            "portrait": portrait,
            "introduction": self.description,
            "address": self.location,
            "google_loc_lng": self.baidu_loc_lng,
            "google_loc_lat": self.baidu_loc_lat,
            "items": item_list,
            'item_list_raw': item_list_raw,
            "share_amount": share_diary_num,
            'reply_amount': self.get_hospital_replied_problems_count(doctor_id),
            'service_amount': self.service_set.filter(is_online=True).count(),
            'diary_amount': share_diary_num,
            "accept_private_msg": accept_private_msg,
            "accept_call": accept_call,
            "phone": PhoneService.get_phone_prefix(phone_ext),
            'phone_ext': phone_ext,
            'is_following': user and user_id and social_info.is_following_user(uid=user_id) or False,
            'city_name': self.city.name if self.city else '',
            'star': star
        }

        if doctor_id:
            doctor_licence = doctor.get_doctor_lincence('', result['service_amount'])
            result['show_v'] = doctor_licence['show_v']
            result['show_rating'] = doctor_licence['show_rating']
        else:
            result['show_v'] = '0'
            result['show_rating'] = '0'

        return result

    def get_best_sell_tags(self):
        from api.models import Order
        from api.models.coupon import HAS_BOUGHT

        s_map = {x.id: x for x in self.service_set.prefetch_related('tags').filter(is_online=True)}
        s_count = Order.objects.filter(
            service_id__in=s_map.keys(), status__in=HAS_BOUGHT
        ).values('service').annotate(o_count=Count('id')).order_by('-o_count')
        item_list = []
        for item in s_count:
            item_list += [tag.name for tag in s_map[item['service']].tags.all()]
        return item_list

    def sell_amount_display(self):
        if hospital_sell_amount_cache.get(self.id):
            return hospital_sell_amount_cache.get(self.id)
        doctors = self.doctor_hospital.filter(is_online=True)
        sum = 0
        for doctor in doctors:
            sum += doctor.sell_amount_display()
        hospital_sell_amount_cache.setex(self.id, 60 * 60, sum)
        return sum

    def get_hospital_tags(self):
        if hospital_search_tags_cache.get(self.id):
            return json.loads(hospital_search_tags_cache.get(self.id))
        return []

    def get_service_tags_distribution(self):
        try:
            return json.loads(hospital_service_tags_distribution_cache.get(self.id))
        except:
            return []

    def __unicode__(self):
        return self.name

    def data(self):
        _data = {
            "id": self.id,
            "name": self.name,
        }
        return _data

    @property
    def officer(self):
        try:
            doctor = self.doctor_hospital.get(
                doctor_type=DOCTOR_TYPE.OFFICER, is_online=True
            )
        except models.ObjectDoesNotExist:
            return

        return doctor

    def _licence_images(self, licence_type):
        """
        获取 机构的资质/执业证书照片
        机构管理者和医生（即doctor_type） 是不允许改变的
        """
        from api.models.doctor import DoctorLicence
        image_list = DoctorLicence.objects.filter(hospital_id=self.id, type=licence_type)
        images = [item.image_url for item in image_list]
        return images

    @property
    def b_licences(self):
        """资格证"""
        return self._licence_images(DOCTOR_LICENCE_TYPE.BUSINESS)

    @property
    def p_licences(self):
        """执业证"""
        return self._licence_images(DOCTOR_LICENCE_TYPE.PRACTICE)

    @property
    def hospital_medical_type(self):
        hos_ext = Hospital_Extra.objects.filter(hospital_id=self.id).first()
        if hos_ext and hos_ext.hospital_type != HOSPITAL_MEDICAL_TYPE.NONE:
            return HOSPITAL_MEDICAL_TYPE.getDesc(hos_ext.hospital_type)
        return ''


class HospitalFavor(models.Model):
    class Meta:
        unique_together = ("user", "hospital")
        verbose_name = u'医院收藏'
        verbose_name_plural = u'医院收藏'
        app_label = 'api'

    user = models.ForeignKey(User, related_name="hospital_favor_user", help_text=u"用户")
    hospital = models.ForeignKey(Hospital, related_name="hospital_favor_hospital", help_text=u"关注的医院")


class Hospital_Extra(models.Model):
    class Meta:
        verbose_name = u'医院额外属性'
        db_table = 'hippo_hospital_extra'
        app_label = 'hippo'

    hospital = models.OneToOneField(Hospital, verbose_name=u'医院')
    open_time = models.DateField(verbose_name=u'开业时间', null=True, default=None)
    hospital_type = models.IntegerField(verbose_name=u'机构类型', choices=HOSPITAL_MEDICAL_TYPE,
                                        default=HOSPITAL_MEDICAL_TYPE.NONE)  # todo 类型枚举
    hospital_level = models.IntegerField(verbose_name=u'医院等级', choices=HOSPITAL_LEVEL,
                                         default=HOSPITAL_LEVEL.NONE)  # todo 等级枚举
    business_area = models.IntegerField(verbose_name=u'营业面积', default=0)

    is_same_province_chain = models.BooleanField(verbose_name=u'是否有同省连锁机构', default=False)
    is_inter_province_chain = models.BooleanField(verbose_name=u'是否有跨省连锁机构', default=False)
    same_province_chain_hospital = models.ForeignKey(Hospital, verbose_name=u'同省连锁机构医院', null=True, blank=True,
                                                     related_name='same_province_chain_hospital_set')
    inter_province_chain_hospital = models.ForeignKey(Hospital, verbose_name=u'跨省连锁机构医院', null=True, blank=True,
                                                      related_name='inter_province_chain_hospital_set')
    scale = models.PositiveSmallIntegerField(verbose_name="医院规模", choices=HOSPITAL_SCALE, default=HOSPITAL_SCALE.NONE)
    notice = models.TextField(help_text="公告板")
    ad_check_img = ImgUrlField(img_type=IMG_TYPE.HOSPITAL, max_length=256, help_text=u"广审表图片url", null=True)
    ad_check_start_time = models.DateTimeField(verbose_name=u'广审表开始时间', null=True)
    ad_check_end_time = models.DateTimeField(verbose_name=u'广审表结束时间', null=True)
    practice_start_time = models.DateTimeField(verbose_name=u'执业开始时间', null=True)
    practice_end_time = models.DateTimeField(verbose_name=u'执业结束时间', null=True)
    honor_introduction = models.CharField(verbose_name=u'荣誉介绍', default=u'', max_length=3000)
    bed_count = models.IntegerField(verbose_name=u'床位个数', null=True)
    department_count = models.IntegerField(verbose_name=u'科室数量', null=True)

    def get_scale_desc(self):
        """
        liansuo
        :return:
        """
        return HOSPITAL_SCALE.getDesc(self.scale)




class HospitalInstrument(models.Model):
    class Meta:
        verbose_name = u'医院仪器信息'
        db_table = 'hippo_hospital_instrument'
        app_label = 'hippo'

    hospital = models.OneToOneField(Hospital, verbose_name=u'医院')
    intro = models.TextField(help_text=u'仪器介绍')
    # content为json字符串，[{name: 仪器名称, cer_image: 证书照片, detail_image: 仪器照片}]
    content = models.TextField(help_text=u'仪器信息')


class HospitalVideo(models.Model):
    class Meta:
        verbose_name = u'医院视频'
        db_table = 'hippo_hospital_video'
        app_label = 'hippo'

    hospital = models.OneToOneField(Hospital, verbose_name=u'医院')
    video_url = models.CharField(max_length=128, verbose_name=u'视屏地址')
    video_pic = models.CharField(max_length=128, verbose_name=u'视屏封面')
    persistentId = models.CharField(max_length=128, verbose_name=u'七牛视频处理id')
    persistent_status = models.IntegerField(default=VIDEO_CODE_STATUS.NOSTART, verbose_name=u"七牛状态", db_index=True)
    water_url = models.CharField(max_length=128, verbose_name=u'水印视屏地址')

    def get_video_info(self):
        if self.video_url:
            if self.video_pic:
                video_pic = get_full_path(self.video_pic, '-w')
            else:
                video_pic = settings.VIDEO_HOST + self.video_url + settings.VIDEO_PIC_URL
        else:
            video_pic = ''

        if self.water_url:
            video_url = self.water_url
        else:
            video_url = self.video_url

        return {
            'video_url': settings.VIDEO_HOST + video_url if video_url else '',
            'video_pic': video_pic
        }

    @classmethod
    def cleaned_video_url(cls, video_url):
        return video_url.replace(settings.VIDEO_HOST, '')


class HospitalRecommendService(models.Model):
    class Meta:
        verbose_name = u'医院推荐美购'
        db_table = 'hippo_hospital_recommendservice'
        app_label = 'hippo'

    hospital = models.ForeignKey(Hospital, verbose_name=u'医院')
    service_id = models.IntegerField(verbose_name=u'美购ID')

    @classmethod
    def recomend_services_info(cls, hospital_id):
        from api.models import Service
        data = cls.objects.filter(hospital_id=hospital_id)
        services = Service.objects.filter(id__in=[x.service_id for x in data])
        return [{'id': x.id, 'name': x.name} for x in services]


class HospitalRecommendDoctor(models.Model):
    class Meta:
        verbose_name = u'医院推荐医生'
        db_table = 'hippo_hospital_recommenddoctor'
        app_label = 'hippo'

    hospital = models.ForeignKey(Hospital, verbose_name=u'医院')
    doctor_id = models.CharField(max_length=100, verbose_name=u'医生ID')

    @classmethod
    def recomend_doctors_info(cls, hospital_id):
        from hippo.models import Doctor
        data = cls.objects.filter(hospital_id=hospital_id)
        doctors = Doctor.objects.filter(id__in=[x.doctor_id for x in data])
        return [{'id': x.id, 'name': x.name} for x in doctors]


class HospitalRestAssured(models.Model):
    class Meta:
        verbose_name = u'医院放心购'
        db_table = u'hippo_hospital_rest_assured'
        app_label = u'hippo'

    hospital = models.ForeignKey(Hospital, verbose_name=u'医院', related_name="rest_assured")
    escort = models.BooleanField(verbose_name=u'全程服务', default=False)
    one_to_one_consulation = models.BooleanField(verbose_name=u'一对一问诊', default=False)
    regular_return_visit = models.BooleanField(verbose_name=u'定期回访', default=False)

    def to_dict(self):
        return {
            "escort": self.escort,
            "one_to_one_consulation": self.one_to_one_consulation,
            "regular_return_visit": self.regular_return_visit,
        }

    @classmethod
    def default_value_to_dict(self):
        return {
            "escort": False,
            "one_to_one_consulation": False,
            "regular_return_visit": False,
        }


class HospitalSpecialService(models.Model):
    class Meta:
        verbose_name = u'特色服务'
        db_table = u'hippo_hospital_special_service'
        app_label = u'hippo'

    hospital = models.ForeignKey(Hospital, verbose_name=u'医院', related_name="special_service")
    wifi = models.BooleanField(verbose_name=u'免费wifi', default=False)
    independent_treatment_room = models.BooleanField(verbose_name=u'独立诊疗室', default=False)
    dressing_room = models.BooleanField(verbose_name=u'化妆间', default=False)
    free_parking_space = models.BooleanField(verbose_name=u'免费停车位', default=False)
    paid_parking = models.BooleanField(verbose_name=u'付费停车位', default=False)
    smoking_room = models.BooleanField(verbose_name=u'吸烟室', default=False)
    free_drink = models.BooleanField(verbose_name=u'免费饮品', default=False)
    free_snack = models.BooleanField(verbose_name=u'免费小吃', default=False)
    swip = models.BooleanField(verbose_name=u'刷卡', default=False)

    def to_dict(self):
        return {
            "wifi": self.wifi,
            "independent_treatment_room": self.independent_treatment_room,
            "dressing_room": self.dressing_room,
            "free_parking_space": self.free_parking_space,
            "paid_parking": self.paid_parking,
            "smoking_room": self.smoking_room,
            "free_drink": self.free_drink,
            "free_snack": self.free_snack,
            "swip": self.swip,
        }

    @classmethod
    def default_value_to_dict(self):
        return {
            "wifi": False,
            "independent_treatment_room": False,
            "dressing_room": False,
            "free_parking_space": False,
            "paid_parking": False,
            "smoking_room": False,
            "free_drink": False,
            "free_snack": False,
            "swip": False,
        }
