# coding=utf-8
# owner: lipeng or zhouyang
#
#
from __future__ import unicode_literals, absolute_import, print_function

import datetime
from django.db.models import Q, Avg
from django.conf import settings
import itertools
import math
import json

from api.models import Doctor
from api.models import DoctorRegisterInfo
from api.models import Hospital
from api.models import DOCTOR_ORDER_TYPE, ORDER_STATUS, DOCTOR_TYPE, TOPIC_TYPE
from api.models import Service
from api.models import Order
from api.models import DoctorCountRecord
from api.models import FamousDoctorClient, PhoneCallRecord
from api.models import ServiceComment
from lasker.models import AwardResult


from api.tool.image_utils import get_full_path
from api.tool.user_tool import get_user_city_tagid
from api.tool.user_tool import get_user_from_context
from api.tool.user_tool import get_doctor_by_user_id
from api.tool.geo_tool import get_location_tag_id_by_city_id
from api.tool.common_tool import number_floor
from api.tool.datetime_tool import (
    get_timestamp_or_none,
    get_datetime,
)
from api.tool.log_tool import logging_exception

from gaia.routers import thread_local
from gm_types.doctor import DOCTOR_TITLE_TYPE
from gm_types.gaia import HOSPITAL_TYPE, SERVICE_FLAG
from gm_types.user_hierarchy import EventType

from rpc.context import get_gaia_local_invoker, get_rpc_remote_invoker
from rpc.decorators import list_interface
from rpc.tool.error_code import gen, CODES
from rpc.tool.param_check import assert_uint
from rpc.decorators import bind, bind_context, cache_page
from statistic.models import DoctorView

from search.utils.doctor import filter_doctor
from social import SocialInfo
from mimas.tasks import send_event_task

# TODO: TALOS MIGRATE
from talos.models.diary import Diary
from services.custom_phone_service import PhoneService

from category.models import CategoryPolymer

PAY_STATUS_LIST = (
    ORDER_STATUS.USED, ORDER_STATUS.SETTLED, ORDER_STATUS.PAID,
    ORDER_STATUS.WAIT_REFUNDED, ORDER_STATUS.OTHER,
    ORDER_STATUS.AUDITING, ORDER_STATUS.SETTLING
)

USED_STATUS_LIST = (
    ORDER_STATUS.USED,
    ORDER_STATUS.SETTLED,
    ORDER_STATUS.OTHER,
    ORDER_STATUS.AUDITING,
    ORDER_STATUS.SETTLING,
)

DOCTOR_TAG_LIMIT = 6


def get_doctor_card_info_by_ids(ids):
    doctors = Doctor.objects.select_related('hospital').filter(id__in=ids, is_online=True)

    if not doctors:
        return []

    result = []
    for d in doctors:
        result.append({
            'id': d.id,
            'name': d.name,
            'portrait': d.portrait,
            'title': d.title,
            'hospital': d.hospital.name,
            'tags': d.get_doctor_item_list()[0]
        })

    return result


@bind_context("api/doctor/common_filter")
@list_interface(
    offset_name='offset', limit_name='limit',
    element_model=Doctor, element_func_list=[Doctor.doctor_detail_v2]
)
def api_filter_doctor_common(
        ctx, order_by=DOCTOR_ORDER_TYPE.DEFAULT2,
        filters=None, offset=0, limit=10, current_city_id=None, with_count=False, query=""):
    filters = filters or {}
    sort_params = {}

    #获取当前城市和国家的tag
    user = ctx.session.user
    user_city_tag_id = get_user_city_tagid(user.id)
    if user_city_tag_id is not None:
        user_city_tag_id = assert_uint(user_city_tag_id)

    country_tagid, city_tagid = get_location_tag_id_by_city_id(current_city_id)
    user_city_tag_id = city_tagid and city_tagid or user_city_tag_id
    if user_city_tag_id is not None:
        sort_params['user_city_tag_id'] = user_city_tag_id

    if 'adver_position' in filters:
        need_adver_info = True
        sort_params['adver_position'] = filters['adver_position']
        if 'adver_word' in filters:
            sort_params['adver_word'] = filters['adver_word']
        # @desc 当取广告时 如果没有用户地区信息，取当前用户所在城市做筛选， 确保用户只能看到当前城市的广告。
        # @pm 李浩楠 @rd 郑伟
        # @date 20170601
        if 'area_tag_id' not in filters and city_tagid:
            filters['area_tag_id'] = city_tagid
    else:
        need_adver_info = False

    offset = assert_uint(offset, 0)
    limit = assert_uint(limit, 10)

    # @desc 当用户没有设置城市信息时， 不展示广告
    # http://wiki.gengmei.cc/pages/viewpage.action?pageId=4149581
    # @pm 李浩楠 @rd 郑伟
    # @date 20170606
    if need_adver_info:
        if 'area_tag_id' not in filters:
            result = []
            if with_count:
                return {
                    'doctors': result,
                    'total_count': 0,
                }
            else:
                return result

    doctor_search_result = filter_doctor(
        offset=offset, size=limit,
        sort_type=order_by,
        filters=filters,
        sort_params=sort_params
    )
    high_light_list_data = doctor_search_result.get('hits', [])
    ids = doctor_search_result["doctor_ids"]
    if need_adver_info:
        doctor_adver_id_map = doctor_search_result['adver_id_map']
    doctors = Doctor.objects.prefetch_related(
        'business_partener', 'hospital__city__province', 'hospital__hospital_extra', 'hospital__doctor_hospital', 'tags'
    ).filter(id__in=ids)
    doctors = {d.id: d for d in doctors}

    result = []
    for did in ids:
        if did not in doctors:
            continue

        if need_adver_info:
            advertise_id = doctor_adver_id_map[did] if did in doctor_adver_id_map else None
        else:
            advertise_id = None
        add_data = doctors[did].doctor_detail_v2(advertise_id=advertise_id, query=query)

        # 7765 高亮
        single_high_light = list(filter(lambda x: x.get('id') == did, high_light_list_data))
        if single_high_light:
            add_data.update({'highlight': single_high_light[0].get('highlight', {})})
        # 7680添加外显两个美购
        result.append(add_data)

    if not with_count:
        return result

    return {
        'doctors': result,
        'total_count': doctor_search_result['total_count']
    }


@bind_context("api/doctor/filter")
@list_interface(
    offset_name='offset', limit_name='limit',
    element_model=Doctor, element_func_list=[Doctor.doctor_detail_v2]
)
def api_filter_doctor(
        ctx, order_by=DOCTOR_ORDER_TYPE.DEFAULT2,
        filters=None, offset=0, limit=10, current_city_id=None, with_count=False):
    filters = filters or {}
    sort_params = {}

    # get country/city tagid
    user = ctx.session.user
    user_city_tag_id = get_user_city_tagid(user.id)
    if user_city_tag_id is not None:
        user_city_tag_id = assert_uint(user_city_tag_id)

    country_tagid, city_tagid = get_location_tag_id_by_city_id(current_city_id)
    user_city_tag_id = city_tagid and city_tagid or user_city_tag_id
    if user_city_tag_id is not None:
        sort_params['user_city_tag_id'] = user_city_tag_id

    # 2016.04.12 不再使用本国id作为筛选
    # if 'area_tag_id' not in filters and country_tagid:
    #     filters['area_tag_id'] = country_tagid

    offset = assert_uint(offset, 0)
    limit = assert_uint(limit, 10)

    # 只返回医生类型的doctor(排除机构管理者)
    filters['doctor_type'] = DOCTOR_TYPE.DOCTOR

    data = filter_doctor(
        offset=offset, size=limit,
        sort_type=order_by,
        filters=filters,
        sort_params=sort_params
    )
    ids = [doc['_id'] for doc in data["hits"]]
    doctors = Doctor.objects.prefetch_related(
        'business_partener', 'hospital__city__province', 'hospital__hospital_extra', 'hospital__doctor_hospital', 'tags'
    ).filter(id__in=ids)
    doctors = {d.id: d for d in doctors}

    result = []
    for did in ids:
        if did not in doctors:
            continue
        doctor = doctors[did]
        # 7745 医生/医院双证有其一 且 关联了商务才展示
        if not all([doctor.business_partener, doctor.b_licences or doctor.p_licences]):
            continue
        single_doctor_data = doctor.doctor_detail_v2()
        current_doctor_filter = filter(lambda x: x.get('id', '') == did, data["hits"])
        if len(current_doctor_filter) > 0:
            first_filter_data = current_doctor_filter[0]
            single_doctor_data.update({'highlight': first_filter_data.get('highlight', {})})
        result.append(single_doctor_data)

    if not with_count:
        return result

    return {
        'doctors': result,
        'total_count': data['total_count'],
    }


@bind_context('api/doctor/officer_filter')
@list_interface(
    offset_name='offset', limit_name='limit', element_model=Doctor,
    element_func_list=[Doctor.doctor_detail_v2]
)
def api_filter_officer(
        ctx, order_by=DOCTOR_ORDER_TYPE.DEFAULT2,
        filters=None, offset=0, limit=10, current_city_id=None,
        with_count=False
):
    '''机构管理者过滤器.

    TODO: refactor this func and api/doctor/filter
    '''
    filters = filters or {}
    sort_params = {}

    user = ctx.session.user
    user_city_tag_id = get_user_city_tagid(user.id)
    if user_city_tag_id is not None:
        user_city_tag_id = assert_uint(user_city_tag_id)

    country_tagid, city_tagid = get_location_tag_id_by_city_id(current_city_id)
    user_city_tag_id = city_tagid and city_tagid or user_city_tag_id
    if user_city_tag_id is not None:
        sort_params['user_city_tag_id'] = user_city_tag_id

    # 2016.11.10 不再使用本国id作为筛选
    # if 'area_tag_id' not in filters and country_tagid:
    #     filters['area_tag_id'] = country_tagid

    offset = assert_uint(offset, 0)
    limit = assert_uint(limit, 10)

    # 只返回机构管理者类型的doctor
    filters['doctor_type'] = DOCTOR_TYPE.OFFICER

    data = filter_doctor(
        offset=offset, size=limit,
        sort_type=order_by,
        filters=filters,
        sort_params=sort_params
    )
    ids = [doc['_id'] for doc in data["hits"]]
    doctors = Doctor.objects.prefetch_related(
        'business_partener', 'hospital__city__province', 'hospital__hospital_extra', 'hospital__doctor_hospital', 'tags'
    ).filter(id__in=ids)
    doctors = {d.id: d for d in doctors}

    result = []
    for did in ids:
        if did not in doctors:
            continue
        doctor = doctors[did]
        # 7745 医生/医院双证有其一 且 关联了商务才展示
        if not all([doctor.business_partener, doctor.b_licences or doctor.p_licences]):
            continue

        detail = doctor.doctor_detail_v2()
        detail['item_list'] = doctor.hospital.get_best_sell_tags() if getattr(doctor, "hospital_id") else []
        result.append(detail)

    if not with_count:
        return result

    return {
        'hospitals': result,
        'total_count': data['total_count'],
    }


@bind_context("api/doctor")
def get_doctor_info(ctx, id):
    """
    医生主页
    id: 医生ID
    """
    user = get_user_from_context(ctx)
    try:
        doctor = Doctor.objects.get(id=id)
        result = doctor.doctor_detail(user)
        return result
    except Doctor.DoesNotExist:
        return gen(CODES.DOCTOR_NOT_FOUND)


@bind("api/doctor/extra_info")
def get_doctor_extra_info(id):
    """
    v 7.6.25
    通过医生id,获取额外的其他信息

    :param id: 医生id
    :return: extra_data 字典
    """
    try:
        doctor = Doctor.objects.prefetch_related('tags').get(id=id)

        # v 7.6.25  获取医生的预约总数, 计算规则: 医生所有美购(在线 + 下线) 预约数总和
        nums = sum([service.sell_amount_display for service in doctor.services.all()])

        # 医生相册 新加字段
        doctor_album = doctor.personalized_photo_album and [{
            "image_half": get_full_path(url, "-half"),
            "image_w": get_full_path(url, "-w"),
        } for url in doctor.personalized_photo_album]

        # 医生职业编号，执业时间
        extra = doctor.extra_info
        serial_number = extra and extra["professional_certificate_num"]  # 职业编号
        time_stamp = extra and extra["professional_certificate_time_float"]  # 注册时间 时间戳
        year = time_stamp and (datetime.datetime.now() - get_datetime(time_stamp)).days // 365

        # 热卖美购
        # service_ids = doctor.service_ranks.all().order_by('rank')\
        #     .values_list("service_id", flat=True)
        # diary_ids = doctor.diary_ranks.all().order_by('rank')\
        #     .values_list("diary_id", flat=True)

        extra_data = {
            "doctor_title": doctor.doctor_title_display or "执业医师",  # 职称
            "practice_time": year or 0,  # 执业年限
            "subscribe_num": nums,  # 预约数
            "doctor_new_rate": doctor.rate,  # update 7.6.55 总分
            "doctor_type": _get_doctor_type(doctor),  # 公立,民营,管理者
            "b_licences": [get_full_path(url, "-wwtm") for url in doctor.b_licences],  # 资格证
            "p_licences": [get_full_path(url, "-wwtm") for url in doctor.p_licences],  # 执业证
            "doctor_tags": doctor.personalized_label,  # 新增字段,获取医生设置标签
            "operate_tag": doctor.operate_tag()[:DOCTOR_TAG_LIMIT],  # 获取运营标签
            "badges": doctor.badges(),  # 名医大赏标签
            "doctor_album": doctor_album,  # 新增字段,获取医生个人相册,
            "doctor_services": [],  # 医生热卖美购,根据后台排名设置获取.
            "doctor_diaries": [],  # 推荐日记本id,根据医生后台排名
            "serial_number": serial_number or "",  # 新加字段 资格编号 !!!
        }
        return extra_data
    except Doctor.DoesNotExist:
        return gen(CODES.DOCTOR_NOT_FOUND)


def _get_doctor_type(doctor):
    """
    v 7.6.25 获取医生 所属医院类型标签
    :return:
    """
    if doctor.hospital.hospital_type == HOSPITAL_TYPE.PUBLIC:
        return HOSPITAL_TYPE.PUBLIC

    if doctor.doctor_type != DOCTOR_TYPE.OFFICER:
        return HOSPITAL_TYPE.PRIVATE

    return None


@bind("api/doctor/detail")
def get_doctor_detail(id, is_favored=False, need_intro=False):
    """get doctor info with doctor detail v2."""
    try:
        doctor = Doctor.objects.get(id=id, is_online=True)
        result = doctor.doctor_detail_v2(is_favored, need_intro)
        return result
    except Doctor.DoesNotExist:
        return gen(CODES.DOCTOR_NOT_FOUND)


@bind('api/doctor/multi_detail')
def multiget_doctor_detail(id_list, is_favored=False, need_intro=False, query=""):
    """get doctor info with doctor detail v2."""
    doctors = Doctor.objects.filter(id__in=id_list, is_online=True)
    res = {
        'doctor_info': {}
    }
    for doctor in doctors:
        res['doctor_info'][doctor.id] = doctor.doctor_detail_v2(is_favored, need_intro, query=query)
    return res


@bind_context('api/doctor/my/operate_service', login_required=True)
@list_interface(offset_name='start_num', limit_name='count', element_model=Service)
def api_doctor_operate_service(ctx, start_num=0, count=10):
    results = []
    user = get_user_from_context(ctx)
    doctor = Doctor.objects.get(user=user)

    user_services = Service.objects.filter(doctor=doctor)
    for service in user_services[start_num:start_num + count]:
        service_data = {
            'name': service.name,
            'pay_num': service.order_set.filter(status__in=PAY_STATUS_LIST).count(),
            'use_num': service.order_set.filter(status__in=USED_STATUS_LIST).count()
        }
        results.append(service_data)

    return results


@bind_context('api/doctor/my/order_validate')
@list_interface(offset_name='start_num', limit_name='count', element_model=Order)
def api_doctor_order_validate(ctx, start_num=0, count=10, ids=None):
    results = []

    user = get_user_from_context(ctx)
    validated_orders = Order.objects.filter(operate_user=user).order_by('-validate_time')
    if ids:
        if isinstance(ids, list):
            q = Q(id__in=ids)
        else:
            q = Q(id__contains=ids)
        validated_orders = validated_orders.filter(q)
    validated_orders = validated_orders[start_num:start_num + count]

    for validated_order in validated_orders:
        results.append(validated_order.data())
    return results


@bind_context("api/doctor/add_follow", login_required=True)
def doctor_add_follow(ctx, doctor_id):
    """
    专家添加关注
    :param doctor_id: 需要关注的专家ID
    :return:
    """
    try:
        doctor = Doctor.objects.get(id=doctor_id)
        if not doctor.user:
            return

        user = get_user_from_context(ctx)
        social_info = SocialInfo(uid=user.id)
        social_info.follow(uid=doctor.user.id)
        event_data = send_event_task(user_id=user.id, event_type=EventType.FOLLOW_MULTI_TIMES, related_item=doctor_id)
        growth_value, point_value = event_data['growth_value'], event_data['point_value']
        submit_count = event_data['submit_count']
        return {'growth_value': growth_value, 'point_value': point_value, 'submit_count': submit_count}
    except Doctor.DoesNotExist:
        return gen(CODES.USER_NOT_FOUND)


@bind_context("api/doctor/del_follow", login_required=True)
def doctor_del_follow(ctx, doctor_id):
    """
    专家取消关注
    :param doctor_id: 需要取消关注的专家ID
    :return:
    """
    try:
        doctor = Doctor.objects.get(id=doctor_id)
        user = get_user_from_context(ctx)
        social_info = SocialInfo(uid=user.id)
        social_info.unfollow(uid=doctor.user.id)
    except Doctor.DoesNotExist:
        return gen(CODES.USER_NOT_FOUND)
    return None


@bind('api/doctor/famous_doctors/get')
@cache_page(3 * 3600)
def get_famous_doctors_info(id):
    """
    用于名医大赏，根据医生ID返回基本信息
    :param id:
    :return: {"doctor_id": 1001,
              "name": "test",
              "portrait": "",
              "description": "",
              "hospital": '',
              "case_num": 0, 已服务消费者数=医生订单数*10+答疑数*2
              "title": '',
              }
    """
    rpc = get_rpc_remote_invoker()
    doctor = Doctor.objects.filter(id=id).first()
    if not doctor:
        return {}
    is_doctor = doctor.doctor_type == DOCTOR_TYPE.DOCTOR
    if is_doctor:
        doctor_ids = [doctor.id]
    else:
        doctor_ids = list(Doctor.objects.filter(hospital=doctor.hospital).values_list('id', flat=True))
    try:
        hospital = doctor.hospital.name
    except:
        hospital = None
    order_case = Order.objects.filter(service__doctor__in=doctor_ids, status=ORDER_STATUS.PAID).count()
    filters = {
        'doctor_ids': doctor_ids
    }
    try:
        diary_count = rpc["doris/search/query_filter_diary"](
            size=1, filters=filters, expose_total=True
        ).unwrap()['total']
    except:
        logging_exception()
        diary_count = 0
    case_num = order_case * 10 + diary_count

    return {
        "doctor_id": doctor.id,
        "is_hospital": not is_doctor,
        "name": doctor.name if is_doctor else doctor.hospital.name,
        "portrait": doctor.portrait,
        "description": doctor.introduction,
        "hospital": hospital if is_doctor else '',
        "case_num": case_num,
        "title": DOCTOR_TITLE_TYPE.getDesc(doctor.title)
        if is_doctor and doctor.title != DOCTOR_TITLE_TYPE.EMPTY else '',
    }


@bind('api/doctor/query_info')
@list_interface(limit_name='limit')
@thread_local(DB_FOR_READ_OVERRIDE=settings.SLAVE_DB_NAME)
def query_doctor_info(name=None, limit=50):
    """
    NOTE:
        DESC: 根据name模糊查询doctor信息
        :type limit: object
        :param name:
        :return:
        change log: 2015-12-08
    """

    if not name:
        return []

    def get_data(f, default=None):
        try:
            return f()
        except Exception:
            return default

    def get_doctor_data(doctor):
        assert isinstance(doctor, Doctor)
        title = DOCTOR_TITLE_TYPE.getDesc(doctor.title) if doctor.title != DOCTOR_TITLE_TYPE.EMPTY else ''

        return {
            'id': doctor.id,
            'name': doctor.name,
            'is_hospital': False,
            'portrait': doctor.portrait,
            'type': 0,
            'title': title,
            'hospital': get_data(lambda: doctor.hospital.name),
            'city': get_data(lambda: doctor.hospital.city.name),
        }

    def get_hospital_data(hospital):
        assert isinstance(hospital, Hospital)
        return {
            'id': hospital.officer and hospital.officer.id,
            'name': hospital.name,
            'is_hospital': True,
            'portrait': hospital.officer and hospital.officer.portrait or hospital.portrait,  # 机构默认头像
            'type': 1,
            'title': None,
            'hospital': '',
            'city': get_data(lambda: hospital.city.name),
        }

    doctor_queryset = Doctor.objects.filter(is_online=True, name__contains=name)[:limit]
    hospital_queryset = Hospital.objects.filter(name__contains=name)[:limit]

    data = []
    queryset = itertools.chain(doctor_queryset, hospital_queryset)

    doctor_id_set = set()
    for obj in queryset:
        if isinstance(obj, Doctor):
            if obj.doctor_type == DOCTOR_TYPE.DOCTOR:
                participant = get_doctor_data(obj)
            elif obj.doctor_type == DOCTOR_TYPE.OFFICER and obj.hospital:
                participant = get_hospital_data(obj.hospital)
        elif isinstance(obj, Hospital):
            participant = get_hospital_data(obj)
        else:
            participant = None

        if not participant:
            continue

        if participant["id"] and participant['id'] not in doctor_id_set:
            doctor_id_set.add(participant['id'])
            data.append(participant)

    return data


@bind('api/doctor/can_create_topic')
def can_create_topic(id=0, user_id=0):
    try:
        if id:
            doctor = Doctor.objects.get(id=id, is_online=True)
        elif user_id:
            doctor = Doctor.objects.get(user_id=user_id)
        can_create_topic = doctor.can_create_topic()
        result = {
            'can_create_topic': can_create_topic
        }
        return result
    except Doctor.DoesNotExist:
        return gen(CODES.DOCTOR_NOT_FOUND)


@bind('api/doctor/iterator')
@list_interface(limit_name='count')
def doctor_iterator(start_num=0, count=10, is_online=True):
    doctors = Doctor.objects.filter(is_online=is_online, doctor_type=DOCTOR_TYPE.DOCTOR)
    return [d.data() for d in doctors[start_num:start_num + count]]


@bind('api/doctor_officer/iterator')
@list_interface(limit_name='count')
def doctor_iterator(start_num=0, count=10, is_online=True):
    '''
    自身在线，并且美购在线的机构管理者(name同机构名)
    '''
    doctors = Doctor.objects.filter(is_online=is_online, services__is_online=is_online, doctor_type=DOCTOR_TYPE.OFFICER)
    return [d.data() for d in doctors[start_num:start_num + count]]


@bind('api/doctor/recommend')
def doctor_recommend(doctor_id=0):
    # todo 7660 上线后可删，已无调用
    result = {}
    try:
        doctor = Doctor.objects.get(id=doctor_id, is_online=True)
    except:
        return result

    rate = doctor.rate
    if rate - math.trunc(rate) >= 0.5:
        star = math.trunc(rate) + 0.5
    else:
        star = math.trunc(rate)

    number = Diary.objects.filter(
        doctor_id=doctor.id,
        is_online=True,
        rating__gt=0
    ).distinct().count()

    result = {
        'star': round(star, 1),
        'number': number,
        'effect_rating': number_floor(doctor.effect_rating, 1),
        'attitude_rating': number_floor(doctor.attitude_rating, 1),
        'env_rating': number_floor(doctor.env_rating, 1),
    }
    return result


@bind('api/doctor/recent_join')
@list_interface(limit_name='count')
def recent_join_doctors(start_num=0, count=10, is_online=True):
    doctors = Doctor.objects.filter(is_online=is_online).order_by('-created_at')[:count]
    return [doctor.doctor_detail_v2() for doctor in doctors]


@bind('api/doctor/basic_info')
def basic_info(doctor_ids):
    if len(doctor_ids) > 100:
        doctor_ids = doctor_ids[:100]  # 防止数量,防止被爬库
    result = Doctor.objects.filter(id__in=doctor_ids).select_related('hospital').only('id', 'name', 'portrait', 'hospital') \
        .filter(is_online=True)
    data = []
    for res in result:
        doctor = {
            'doctor_id': res.id,
            'doctor_name': res.name,
            'doctor_portrait': res.portrait,
            'hospital_name': res.hospital.name if res.hospital else u'',
            'hospital_id': res.hospital.id if res.hospital else u'',
            'hospital_portrait': res.hospital.portrait if res.hospital else u'',
            'user_id': res.user_id
        }
        data.append(doctor)
    return data


@bind('api/doctor/active')
def add_doctor_active(user_id):
    doctor = get_doctor_by_user_id(user_id)
    if doctor:
        day = datetime.date.today()
        doctor_view, new = DoctorView.objects.get_or_create(stat_date=day, doctor=doctor)
        doctor_view.is_active = True
        doctor_view.save()


@bind('api/doctor/sitemap')
def get_doctorlist_sitemap(doctor_type=DOCTOR_TYPE.DOCTOR,
                           count=settings.BUILD_SITEMAP_COUNT):
    doctor_info = []
    doctor_list = Doctor.objects.filter(doctor_type=doctor_type).order_by('-online_time')
    doctor_list = doctor_list[0:count]
    for doctor in doctor_list:
        doctor_info.append({
            'id': doctor.id,
            'online_time': get_timestamp_or_none(doctor.online_time),
        })
    return doctor_info


@bind('api/doctor/register_apply')
def client_doctor_register(doctor_info):
    dr = DoctorRegisterInfo.objects.filter(phone=doctor_info['phone'])
    if dr.count() == 0:
        try:
            DoctorRegisterInfo.objects.create(**doctor_info)
            return True
        except:
            logging_exception()
            return gen(CODES.UNKNOWN_ERROR)
    else:
        return gen(CODES.USER_ALREADY_REIGST)


@bind('api/doctor/diary_index_discount_score')
def doctor_discount(id):
    try:
        d = Doctor.objects.get(id=id)
    except Doctor.DoesNotExist:
        return gen(CODES.DOCTOR_NOT_FOUND)
    discount = DoctorCountRecord.get_diary_index_score(d)
    return discount


@bind('api/doctor/phone_ext')
def get_doctor_phone_ext(ext=None):
    result = []
    doctors = Doctor.objects.filter(phone_ext=ext).values('phone')
    for doctor in doctors:
        phone = doctor['phone']
        result.append(phone)

    return result


@bind('api/phone/record_ext_and_call_id')
def get_record_ext_and_call_id(ext, call_id):
    result = {'recorded': False}

    if not (call_id and ext):
        return result

    objs = PhoneCallRecord.objects.filter(call_id=call_id)
    if objs.exists():
        return result

    phone_call_record = PhoneCallRecord()
    phone_call_record.phone_ext = ext
    phone_call_record.call_id = call_id
    phone_call_record.save()
    result['recorded'] = True

    return result


@bind('api/doctor/hera_search')
def doctor_hera_search(id_query=None, doctor_type=None, offset=0, size=10):
    assert id_query is not None
    doctors = Doctor.objects.filter(id__startswith=id_query)
    if doctor_type is not None:
        doctors = doctors.filter(doctor_type=doctor_type)
    doctors = doctors[offset:size]
    res = []
    for doctor in doctors:
        res.append(doctor.doctor_detail_v2(is_favored=False, need_intro=False))

    return res


@bind('api/doctor/get_id_by_tags')
def get_doctor_id_by_tags(tag_ids, offset=0, size=10, sort_type=DOCTOR_ORDER_TYPE.DEFAULT2):
    doctor_ids = []
    filters = {'tag_ids': tag_ids}
    doctors_result = filter_doctor(
        offset=offset, size=size,
        filters=filters, sort_type=sort_type
    )
    doctor_ids.extend(doctors_result.get('doctor_ids'))
    return doctor_ids


@bind('api/doctor/get_famous_doctor_badge')
@cache_page(10*60)
def get_famous_doctor_badge(ids=[], query_type=SERVICE_FLAG.DOCTOR):
    """
    :return {"doctor_id1": ["最佳鼻部", "最佳眼眉"], "doctor_id2": ["最佳眼眉"], "doctor_id3": [], ...}
     """
    res = {}
    if query_type == 'normal':
        ars = AwardResult.objects.filter(laureate_id__in=ids)
    elif query_type == SERVICE_FLAG.DOCTOR:
        ars = AwardResult.objects.filter(laureate_type=SERVICE_FLAG.DOCTOR)
    else:
        ars = AwardResult.objects.filter(laureate_type=SERVICE_FLAG.HOSPITAL)

    ars = ars.filter(is_deleted=False)
    for ar in ars:
        res[ar.laureate_id] = ar.award_name.split(',')

    return res


@bind('api/doctor/iterator_for_inner')
def doctor_iterator_for_inner(start_num=0, count=10):
    '''仅供内部调用!!!'''
    return_dict = {
        'ids': [],
        "doctors": {},  # todo 等 mip 上线之后删除，勿动！！！
    }

    doctors = Doctor.objects.filter(is_online=True)
    for d in doctors[start_num:start_num + count]:
        return_dict['ids'].append(d.id)
        user_id = d.user_id
        if user_id:
            return_dict["doctors"].update({
                user_id: {
                    "doctor_id": d.id,
                    "doctor_title": d.title,
                }
            })

    return return_dict


@bind("api/doctor/list_by_service_ids")
def get_doctors_list_by_service_ids(service_ids):
    """根据美购ID获取对应的医生。"""

    services = Service.objects.filter(id__in=service_ids).select_related("doctor")
    if not services:
        return {}

    res = {}
    for service in services:
        res[service.id] = {
            "id": service.doctor_id,
            "hospital_id": service.doctor.hospital_id,
        }

    return res


@bind('api/batch_get_doctor_info_by_doctor_ids')
@cache_page(2 * 60)
def batch_get_doctor_info_by_doctor_ids(doctor_ids, with_fields=None):
    """
    :param doctor_ids:
    :param with_fields:
    :return:
    """
    result = {}
    if with_fields is None:
        with_fields = []
    doctors = Doctor.objects.filter(id__in=doctor_ids).all()
    for doctor in doctors:
        data = {}
        if 'meta' in with_fields:
            data['meta'] = {
                'id': doctor.id,
                'name': doctor.name,
                'display_title': doctor.doctor_title_display or "执业医师",
                'title': doctor.title,
                'doctor_type': doctor.doctor_type,
                'portrait': get_full_path(doctor.portrait or settings.DOCTOR_DEFAULT_PORTRAIT_KEY),
            }
        result[str(doctor.id)] = data
    return result


@bind_context('api/doctor_toc_doctor_info')
def doctor_toc_doctor_info(ctx,doctor_id):
    """
    author: oldman
    7790 医生主页医生的基础信息
    :param doctor_id:医生ID
    :return:
    """
    do = Doctor.objects.get(id=doctor_id)
    info = do.doctor_detail_v2(need_intro=True)
    basic_info = {
        "doctor_id": info["doctor_id"],
        "name": info["name"],
        "badges": info["badges"],
        "title": info["title"],
        "practice_time": info["practice_time"],
        "rate": info["rate"],
        "doctor_type": info["doctor_type"],
        "subscribe_num": info["subscribe_num"],
        "p_licences": do.p_licences,
        "b_licences": do.b_licences,
        "hospital_name": info["hospital_name"],
        "address": info["address"],
        "lat": info["lat"],
        "lng": info["lng"],
        "portrait": info["portrait"],
        "introduction": info["introduction"],
        "service_amount": do.get_doctor_service_num(),
        "hospital_id": info["hospital_id"],
        "good_at": info["good_at"],
        "hospital_type": info["hospital_type"],
    }
    related_info = {
        "accept_private_msg": do.accept_private_msg,
        "accept_call": do.accept_call,
        "phone_ext":do.phone_ext,
        "phone":PhoneService.get_phone_prefix(do.phone_ext),
        "user_id": info["user_id"]
    }
    is_following = False
    user = get_user_from_context(ctx)
    if user:
        social_info = SocialInfo(uid=user.id)
        is_following = social_info.is_following_user(uid=do.user.id)
    basic_info['is_following'] = is_following
    return {"basic_info": basic_info,
            "related_info": related_info}

@bind('api/doctor/diary_tags')
def diary_tags(doctor_id):
    """
    获取医生的案例标签
    :param doctor_id:
    :return:
    """
    do = Doctor.objects.get(id=doctor_id)
    items =  do.get_doctor_item_list()
    return {
        "item_list": items[0],
        "item_list_raw": items[1]
    }


@bind('api/get_officer_by_hospital_id')
def get_officer_by_hospital_id(hospital_id):
    if not hospital_id:
        return {}

    doctor = Doctor.objects.filter(hospital_id=hospital_id, doctor_type=DOCTOR_TYPE.OFFICER).first()
    if not doctor:
        return {}

    return {'officer_id': doctor.id}
