# coding=utf-8
from __future__ import unicode_literals, absolute_import, print_function

import json
from itertools import chain


from gm_types.doctor import DOCTOR_AREA_TYPE, HOSPITAL_MEDICAL_TYPE, HOSPITAL_LEVEL
from gm_types.user_hierarchy import EventType
from gm_upload.utils.image_utils import Picture
from gm_types.gaia import MERCHANT_LEVEL_NEW

from api.models import DOCTOR_TYPE, PeriodHospital
from api.models import Hospital, Doctor,User,HospitalFavor,Order,Shopcart,Conversation,ConversationUserStatus,Person
from api.tool.common_tool import number_floor
from api.tool.datetime_tool import get_humanize_datetime
from lasker.models import AwardResult
from api.models.types import DIARY_ORDER_TYPE,ORDER_STATUS
from api.tool.user_tool import get_user_from_context, get_hospital_by_id
from api.tool.image_utils import get_full_path, get_w_path
from api.tool.geo_tool import calc_distances_by_lat_lnt,display_distances
from hippo.models import Hospital_Extra, SlaveMerchant, Merchant, MerchantRelevance
from mimas.tasks import send_event_task
from rpc.cache import hospital_tags_cache
from rpc.decorators import bind, list_interface, bind_context, cache_page
from rpc.tool.dict_mixin import to_dict
from rpc.tool.error_code import CODES, gen
from rpc.all import get_rpc_remote_invoker
# TODO: TALOS MIGRATE
from services.custom_phone_service import PhoneService
from social import SocialInfo
from talos.models.diary import Diary
from talos.models.topic import TopicReply
from rpc.tool.log_tool import logging_exception,info_logger
from gm_protocol import GmProtocol
from api.util.cache_util import cache_wrap
from rpc.cache import hospital_search_tags_cache


gm=GmProtocol()

HOSPITAL_TAG_LIMIT = 3


def get_hospital_card_info_by_ids(ids):
    hospitals = Hospital.objects.filter(id__in=ids)
    if hospitals is None:
        return []

    result = []
    for h in hospitals:
        res = {
            'id': h.id,
            'name': h.name,
            'portrait': h.portrait,
            'hospital_type': h.hospital_type,
        }
        images = h.organizationimage_set.all()
        res['images'] = [image.image_url for image in images]
        result.append(res)
    return result


@bind_context("api/hospital")
def get_hospital_info(ctx, id):
    """
    机构主页
    id: 机构ID
    v 7.6.35 改版
    """
    user = get_user_from_context(ctx)
    rpc = get_rpc_remote_invoker()
    try:
        hospital = Hospital.objects.get(id=id)
        hospital_extra = Hospital_Extra.objects.filter(hospital=hospital).first()
        #  仪器设备及介绍是必填项!!! 要么不写，要么介绍与图片同时存在。
        hospital_instrument = hospital.hospitalinstrument if hasattr(hospital, "hospitalinstrument") else None  # 设备
    except Hospital.DoesNotExist:
        return gen(CODES.HOSPITAL_NOT_FOUND)

    result = hospital.hospital_detail(user)
    result.update(hospital.video_info)  # 增加 视频信息
    result.update({
        "hospital_level": "",  # 机构等级
        "hospital_classify": "",  # 机构类型
        "hospital_medical_type": hospital_extra and hospital_extra.hospital_type or None,
        "device_detail": "",  # 设备介绍
        "device_images": [],  # 设备图片
        "tags": [],  # 医院标签
        "service_ids": [],  # 推荐美购id
        "diary_ids": [],   # 推荐日记本id
        "doctor_ids": list(hospital.hospitalrecommenddoctor_set.values_list("doctor_id", flat=True)),  # 推荐医生
        "qualification_papers": hospital.b_licences and get_full_path(hospital.b_licences[0], '-wwtm') or "",  # 资格证
        "practice_papers": hospital.p_licences and get_full_path(hospital.p_licences[0], '-wwtm') or "",  # 执业证
    })
    # 获取医院类型 和 医院等级
    if hospital_extra and hospital_extra.hospital_type != HOSPITAL_MEDICAL_TYPE.NONE:
        result["hospital_classify"] = HOSPITAL_MEDICAL_TYPE.getDesc(hospital_extra.hospital_type)
    if hospital_extra and hospital_extra.hospital_level != HOSPITAL_LEVEL.NONE:
        result["hospital_level"] = HOSPITAL_LEVEL.getDesc(hospital_extra.hospital_level)

    hospital_images = hospital.organizationimage_set.values_list("image_url", flat=True)
    result['hospital_images'] = list(hospital_images)  # 环境图片
    if hospital_instrument:
        result["device_detail"] = hospital_instrument.intro or ""  # 所有设备描述
        result['device_images'] = json.loads(hospital_instrument.content) or []  # 设备图片
    result["images_counts"] = len(result["hospital_images"]) + len(result["device_images"])  # 图片总数

    hospital_items = {}
    hospital_doctors = hospital.doctor_hospital.filter(is_online=True)
    doctor_ids = []
    for doctor in hospital_doctors:
        doctor_ids.append(doctor.id)
        _, doctor_items = hospital.get_doctor_item_list(doctor_id=doctor.id)
        for item in doctor_items:
            names = item['name'].replace('例', '').rsplit(" ", 1)
            item_dict = {'name': names[0], "cnt": int(names[-1]), "tag_id": item['tag_id']}

            if hospital_items.get(item_dict['name']):
                hospital_items[item_dict['name']]['cnt'] += item_dict['cnt']
            else:
                hospital_items[item_dict['name']] = item_dict

    filters = {
        'hospital_id': id,
    }
    from search.utils.diary import filter_diary
    diary_count = filter_diary(sort_type=DIARY_ORDER_TYPE.DOCTOR_CUSTOMIZE_SORT, filters=filters, expose_total=True)
    # diary_count = rpc["doris/search/query_filter_diary"](sort_type=DIARY_ORDER_TYPE.DOCTOR_CUSTOMIZE_SORT,
    #                                                      filters=filters, expose_total=True).unwrap()
    result['diary_count'] = diary_count.get('total')

    hospital_items = sorted(hospital_items.values(), key=lambda x: x['cnt'], reverse=True)
    item_list_raw = [{'name': u'{} {}例'.format(v['name'], v['cnt']), 'tag_id': v['tag_id']} for v in
                     hospital_items]
    item_list = [u'{}'.format(v['name']) for v in hospital_items]

    result['item_list_raw'] = item_list_raw
    result['items'] = item_list
    result['service_tags_distribution'] = hospital.get_service_tags_distribution()

    #  机构管理者的地域类型决定医院的境内境外。境内 则分公立、民营；境外则为海外
    if hospital.officer and hospital.officer.area_type == DOCTOR_AREA_TYPE.ABROAD:
        result["hospital_type"] = "2"  # 如果是境外，直接返回 2 以代表海外

    if hospital.officer:
        result['operate_tag'] = hospital.officer.operate_tag()[:HOSPITAL_TAG_LIMIT]    # 获取运营标签
    else:
        result['operate_tag'] = []

    if hospital_extra:
        result['notice'] = hospital_extra.notice

    return result


@bind_context("api/get_toc_hospital_basic_info")
def get_toc_hospital_basic_info(ctx, hospital_id, with_fields=None):
    """toc 获取医院基本信息

    :param ctx:
    :param hospital_id: 医院ID
    :param List[str] with_fields: 需要的字段
    :return:
    """
    try:
        hospital = Hospital.objects.get(id=hospital_id)
    except Hospital.DoesNotExist:
        return gen(CODES.HOSPITAL_NOT_FOUND)

    officer = hospital.officer

    if officer and officer.portrait:
        portrait = get_full_path(officer.portrait)
    elif hospital.portrait:
        portrait = get_full_path(hospital.portrait)
    else:
        portrait = get_w_path(u'img%2Fyiyuan.png')

    result = {}

    if officer:
        is_flagship = int(officer.is_store_classification)
    else:
        is_flagship = 0

    branch_store_num = SlaveMerchant.objects.filter(mastermerchant__mastermerchant__doctor=officer).count()
    flagship_layout_img = "https://heras.igengmei.com/2019/09/20/3399be3225"

    if 'meta' in with_fields:
        result['meta'] = {
            'id': hospital.id,
            'name': hospital.name,
            'portrait': portrait,
            'is_flagship': is_flagship,
            'branch_store_num': branch_store_num if is_flagship else None,
            'flagship_layout_img': flagship_layout_img if is_flagship else None,
        }

    if 'content' in with_fields:
        accept_private_msg = False
        accept_call = False
        phone_ext = ''
        good_at = []
        star = 0.0
        if officer:
            if officer.accept_private_msg is True:
                accept_private_msg = True
            if officer.accept_call is True:
                accept_call = True
            phone_ext = officer.phone_ext
            star = officer.rate
            if officer.good_at:
                good_at = officer.good_at.split(',')

        result['content'] = {
            'hospital_type': hospital.hospital_type,
            "qualification": hospital.qualification,
            "introduction": hospital.description,
            "address": hospital.location,
            "longitude": hospital.baidu_loc_lng,
            "latitude": hospital.baidu_loc_lat,
            'accept_private_msg': accept_private_msg,
            'accept_call': accept_call,
            'phone_ext': phone_ext,
            'city_name': hospital.city.name if hospital.city else '',
            'star': hospital.rate,
            'effect_rating': hospital.effect_rating,
            "attitude_rating": hospital.attitude_rating,
            "env_rating": hospital.env_rating,
            'show_rating': '1' if hospital.rate >= 1 else '0',
            'phone': PhoneService.get_phone_prefix(phone_ext),
            'good_at': good_at,
            'created_time': str(hospital.created_time),
            'area_type': officer.area_type if officer else '',
        }

    if 'related' in with_fields:
        service_amount = officer.get_hospital_service_num() if officer else 0
        badges, is_special_appearance = hospital.get_hospital_award_result()
        if officer:
            operate_tags = officer.operate_tag()
            try:
                hospital_scale = hospital.hospital_extra.get_scale_desc()
            except Exception:
                hospital_scale = ""
                logging_exception()
        else:
            operate_tags = []
            hospital_scale = ''

        # 如果医院名医大赏里面没有 特殊皮肤，则针对 对应商户等级判断是否展示特殊UI
        if not is_special_appearance:
            # merchant_level 为 MERCHANT_LEVEL_NEW.V5及以上时候 医院详情特殊UI
            merchant_level = MERCHANT_LEVEL_NEW.V1
            if officer:
                merchant_level = Merchant().get_doctor_merchant_level(officer.id)
            if merchant_level >= MERCHANT_LEVEL_NEW.V5:
                is_special_appearance = 1

        result['related'] = {
            'service_amount': service_amount,  # 不一定准确
            'sell_amount': 0,
            'show_v': '1' if service_amount > 0 else '0',
            'operate_tags': operate_tags,
            'badges': badges,
            'is_special_appearance': is_special_appearance,
            'display_tags': hospital.format_display_tags(hospital_scale, badges, operate_tags)
        }

    if 'relation' in with_fields:
        if officer and officer.user and officer.user.id:
            user_id = officer.user.id
        else:
            user_id = ''

        result['relation'] = {
            'user_id': user_id,
            'doctor_id': officer.id if officer else '',
        }

    if 'social' in with_fields:
        is_following = False
        user = get_user_from_context(ctx)
        if user and officer:
            from social import SocialInfo
            social_info = SocialInfo(uid=user.id)
            is_following = social_info.is_following_user(uid=officer.user.id)
        result['social'] = {
            'is_following': is_following,
        }

    return result


@bind("api/get_toc_hospital_extra_info")
@cache_page(60)
def get_toc_hospital_extra_info(hospital_id):
    try:
        hospital = Hospital.objects.get(id=hospital_id)
    except Hospital.DoesNotExist:
        return gen(CODES.HOSPITAL_NOT_FOUND)
    from hippo.businessmethod.hospital import get_hospital_info
    # support_installment = PeriodHospital.check_hospital_in_list(hospital)
    hospital_extra_info = get_hospital_info(hospital)
    # hospital_extra_info['rest_assured'].update({'support_installment': support_installment})
    return hospital_extra_info


@bind_context('api/hospital/list')
@list_interface(offset_name='start_num', limit_name='count', element_model=Hospital,
                element_func_list=[Hospital.hospital_detail])
def hospital_list(ctx, start_num=0, count=10):
    user = get_user_from_context(ctx)
    hospitals = Hospital.objects.exclude(id='wanmeizhensuo')
    return [h.hospital_detail(user) for h in hospitals[start_num:start_num + count]]


@bind('api/hospital/iterator')
@list_interface(limit_name='count')
def hospital_interator(start_num=0, count=10, is_online=True):
    '''
    被api/doctor_officer/iterator替换，待删除
    '''
    hospitals = Hospital.objects.exclude(id='wanmeizhensuo').filter(service__is_online=is_online)
    return [h.hospital_detail() for h in hospitals[start_num:start_num + count]]


@bind_context("api/hospital/add_follow", login_required=True)
def hospital_add_follow(ctx, hospital_id):
    """
    专家添加关注
    :param hospital_id: 需要关注的机构ID
    :return:
    """
    try:
        hospital = Hospital.objects.get(id=hospital_id)
        doctor = hospital.doctor_hospital.get(doctor_type=DOCTOR_TYPE.OFFICER)
        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=hospital_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 Hospital.DoesNotExist:
        return gen(CODES.USER_NOT_FOUND)


@bind_context("api/hospital/del_follow", login_required=True)
def hospital_del_follow(ctx, hospital_id):
    """
    机构取消关注
    :param hospital_id: 需要取消关注的机构ID
    :return:
    """
    try:
        hospital = Hospital.objects.get(id=hospital_id)
        doctor = hospital.doctor_hospital.get(doctor_type=DOCTOR_TYPE.OFFICER)
        user = get_user_from_context(ctx)
        social_info = SocialInfo(uid=user.id)
        social_info.unfollow(uid=doctor.user.id)
    except Hospital.DoesNotExist:
        return gen(CODES.USER_NOT_FOUND)
    return None


@bind_context('api/hospital/add_favor', login_required=True)
def add_hospital_favor(ctx, hospital_id):
    user = get_user_from_context(ctx)
    hospital = get_hospital_by_id(hospital_id)
    if user and hospital:
        _favor, _created = HospitalFavor.objects.get_or_create(user=user, hospital=hospital)


@bind_context('api/hospital/delete_favor', login_required=True)
def delete_hospital_favor(ctx, hospital_id):
    user = get_user_from_context(ctx)
    hospital = get_hospital_by_id(hospital_id)
    if user and hospital:
        HospitalFavor.objects.filter(user=user, hospital=hospital).delete()


@bind('api/hospital/basic_info')
def basic_info(hospital_ids):

    if len(hospital_ids) > 100:
        hospital_ids = hospital_ids[:100]   # 限制数量,防止被爬库

    result = Hospital.objects.filter(id__in=hospital_ids).only('id', 'name', 'portrait', 'hospital_type', 'rate')

    extra_info = Hospital_Extra.objects.filter(hospital_id__in=hospital_ids).values("hospital_id", "hospital_level")
    extra_pre_dic = {extra["hospital_id"]: extra for extra in extra_info}

    officers = Doctor.objects.filter(hospital_id__in=hospital_ids, doctor_type=DOCTOR_TYPE.OFFICER)
    hospital_officers_map = {doctor.hospital_id: doctor for doctor in officers}

    officer_doctor_ids = [officer.id for officer in officers]
    merchants = Merchant.objects.filter(is_online=True, doctor_id__in=officer_doctor_ids)
    merchant_dic = {merchant.doctor_id: merchant for merchant in merchants}

    data = []
    for res in result:
        extra = extra_pre_dic.get(res.id, {})

        officer = hospital_officers_map.get(res.id)
        if officer and officer.portrait:
            portrait = get_full_path(officer.portrait)
        elif res.portrait:
            portrait = get_full_path(res.portrait)
        else:
            portrait = get_w_path(u'img%2Fyiyuan.png')

        merchant_level = MERCHANT_LEVEL_NEW.V1
        if officer:
            merchant = merchant_dic.get(officer.id)
            if merchant:
                merchant_level = merchant.merchant_level

        hospital = {
            'hospital_name': res.name,
            'hospital_id': res.id,
            'doctor_id': officer.id if officer else None,
            'hospital_portrait': portrait,
            'hospital_type': res.hospital_type,
            'star': res.rate,
            'address': res.location,
            'hospital_level': extra.get("hospital_level", HOSPITAL_LEVEL.NONE),
            'merchant_level': merchant_level,
        }
        data.append(hospital)

    return data


@bind('api/hospital/doctor')
def get_doctor(hospital_id, doctor_type):
    hospital = get_hospital_by_id(hospital_id)
    if not hospital:
        return None
    doctors = Doctor.objects.filter(hospital=hospital).filter(doctor_type=doctor_type)
    if doctors and len(doctors) >= 1:
        doctor_data = []
        for i in range(len(doctors)):
            doctor_data.append(doctors[i].to_dict())
        return doctor_data
    else:
        return None


@bind('api/hospital/doctor/v1')
@list_interface(offset_name='start_num', limit_name='count')
def get_doctors_list(hospital_id, doctor_ids=None, start_num=0, count=3, exclude_ids=None):
    """
    v 7.6.35 新加 获取医院下的医生团队，考虑管理者，医生团队在线情况
    :param hospital_id: 医院id
    :param doctor_ids: 医生id list
    :param start_num: 起始数
    :param count: 获取个数
    :param exclude_ids: 需要排除掉的医生
    :return: {} dict
    """
    result = {
        "doctor_count": 0,
        "doctor_list": [],
    }
    exclude_ids = exclude_ids or []
    try:
        hospital = Hospital.objects.get(id=hospital_id)

        if not hospital.officer:  # 机构管理者不存在
            return result
        #  医生后台选择的都是在线的医生
        doctors = Doctor.objects.prefetch_related('services').filter(hospital_id=hospital.id, is_online=True, doctor_type=DOCTOR_TYPE.DOCTOR)
        if not doctors:  # 没有医生
            return result

        result['doctor_count'] = doctors.count()
        # 通过医生id获取要展示的医生信息(需要按照 id 顺序排序)，没有的按照默认排序
        if doctor_ids:
            doctors = doctors.filter(id__in=doctor_ids)  # 根据医生id 获取医生后台推荐的医生
        elif exclude_ids:
            doctors = doctors.exclude(id__in=exclude_ids)

        for doctor in doctors[start_num: start_num + count]:
            item_list, item_list_raw = doctor.get_doctor_item_list()
            data = {}
            data['item_list_raw'] = item_list_raw
            data['is_online'] = True
            data["user"] = {
                "title": doctor.doctor_title_display or "执业医师",
                "star": doctor.rate,
                "subscribe_num": sum([service.sell_amount_display for service in doctor.services.all()]),
                "id": doctor.id,
                "name": doctor.name,
                "portrait": Picture(get_full_path(doctor.portrait)).web,
            }
            result['doctor_list'].append(data)

        return result

    except Hospital.DoesNotExist:
        return result


@bind('api/hospital/doctor/v2')
@cache_page(2 * 60)
@list_interface(offset_name='start_num', limit_name='count')
def get_doctors_list_v2(hospital_id, start_num=0, count=3, with_fields=None, only_count=False):
    """
    v 7.6.35 新加 获取医院下的医生团队，考虑管理者，医生团队在线情况
    :param hospital_id: 医院id
    :param start_num: 起始数
    :param count: 获取个数
    :return: {} dict
    """
    if with_fields is None:
        with_fields = []
    result = {
        "doctor_count": 0,
        "doctor_list": [],
    }
    result['doctor_count'] = Doctor.objects.filter(
        hospital_id=hospital_id, is_online=True, doctor_type=DOCTOR_TYPE.DOCTOR
    ).count()
    if result['doctor_count'] == 0:
        return result

    if only_count:
        return result
    try:
        hospital = Hospital.objects.only('id', 'name').get(id=hospital_id)
    except Hospital.DoesNotExist:
        return result

    if not hospital.officer:  # 机构管理者不存在
        return result

    # 通过医生id获取要展示的医生信息(需要按照 id 顺序排序)，没有的按照默认排序
    recommend_doctor_ids = list(hospital.hospitalrecommenddoctor_set.order_by('id').values_list("doctor_id", flat=True))
    if recommend_doctor_ids:
        recommend_doctor_ids.reverse()
        order_fields = ','.join(map(lambda id: "\"{}\"".format(str(id)), recommend_doctor_ids))
    else:
        order_fields = 'null'

    doctor_prefetch_related_list = ['services']
    if 'content' in with_fields:
        doctor_prefetch_related_list.append('doctor_extra')

    #  医生后台选择的都是在线的医生
    doctors = Doctor.objects.prefetch_related(*doctor_prefetch_related_list).\
        filter(hospital_id=hospital.id, is_online=True, doctor_type=DOCTOR_TYPE.DOCTOR).\
        extra(select={'ordering': 'FIELD(`id`, %s)' % order_fields}, order_by=('-ordering', 'id')).\
        all()[start_num: start_num + count]

    for doctor in doctors:
        data = {}
        if 'meta' in with_fields:

            data['meta'] = {
                'id': doctor.id,
                'name': doctor.name,
                "title": doctor.doctor_title_display or "执业医师",
                'portrait': get_full_path(doctor.portrait),
            }
        if 'content' in with_fields:
            good_at = []
            try:
                if doctor.good_at:
                    good_at = doctor.good_at.split(',')
            except BaseException:
                logging_exception()
            data['content'] = {
                'star': doctor.rate,
                'good_at': good_at,
                "working_year": doctor.doctor_extra.working_year if hasattr(doctor, 'doctor_extra') else 0,
            }

        if 'related' in with_fields:
            _, item_list_raw = doctor.get_doctor_item_list()
            data['related'] = {
                'cases': item_list_raw,
                "sell_amount": sum([service.sell_amount_display
                                    for service in doctor.services.all()]),
            }
        result['doctor_list'].append(data)

    return result


@bind('api/hospital/by_ids')
def hospital_by_ids(ids):
    model = Hospital
    m = model.objects.filter(id__in=ids).select_related('city__province__country')
    res = []
    for hospital in m:
        if hasattr(hospital, 'to_dict'):
            data = hospital.to_dict()
        else:
            data = to_dict(hospital)
        # with area fields
        data['city_tag_id'] = hospital.city.tag_id
        data['province_tag_id'] = hospital.city.province.tag_id
        data['country_tag_id'] = hospital.city.province.country.tag_id

        if hasattr(hospital, "hospital_extra"):
            data["hospital_level"] = hospital.hospital_extra.hospital_level
        else:
            data['hospital_level'] = HOSPITAL_LEVEL.NONE

        res.append(data)

    return res


@bind('api/hospital/by_doctor_id')
def hospital_by_doctor_id(doctor_id):
    model = Doctor
    try:
        m = model.objects.get(id=doctor_id)
        if m.hospital_id is None:
            return gen(CODES.HOSPITAL_NOT_FOUND)
        else:
            h = m.hospital
            if hasattr(h, 'to_dict'):
                data = h.to_dict()
            else:
                data = to_dict(h)
            if hasattr(h, "hospital_extra"):
                data["hospital_level"] = h.hospital_extra.hospital_level
            else:
                data["hospital_level"] = HOSPITAL_LEVEL.NONE
            return data
    except model.DoesNotExist:
        return gen(CODES.DOCTOR_NOT_FOUND)


@bind('api/hospital/list_doctor')
@list_interface(offset_name='start_num', limit_name='count', element_model=Hospital,
                element_func_list=[Hospital.hospital_detail])
def list_doctor_by_hospital_id(start_num=0, count=100):
    """
    List doctor by hospital id.
    此接口只用作构建cache(doctor_hospital_rel)
    :return:
    """
    hospitals = Hospital.objects.exclude(id='wanmeizhensuo')
    data = []
    for hospital in hospitals[start_num: start_num + count]:
        docs = []
        for doctor in hospital.doctor_hospital.filter(is_online=True, doctor_type=DOCTOR_TYPE.DOCTOR):
            docs.append({
                'doctor_id': doctor.id, 'doctor_name': doctor.name
            })
        data.append({'hospital_id': hospital.id, 'doctors': docs})
    return data


@bind('api/hospital/info_by_hospital_id')
@cache_page(30 * 60)
def get_info_by_hospital_id(hospital_id):
    """复用doctor model 下doctor_detail_v2方法获取机构详情"""
    try:
        officer = Hospital.objects.get(id=hospital_id).officer
        if not officer:
            return {}

        result = officer.doctor_detail_v2()
        return result

    except Hospital.DoesNotExist:
        return {}

@bind('api/hospital/info_by_ids')
@cache_page(30 * 60)
def get_info_by_hospital_id(hospital_ids, business_partener_ids):
    """根据医院ids获取医院名称, 根据商务ids获取商务名称"""
    from django.contrib.auth.models import User
    try:
        hospital_data = list(Hospital.objects.filter(id__in=hospital_ids).values('id', 'name'))
        business_partener_data = list(User.objects.filter(id__in=business_partener_ids).values('id', 'username'))
        return hospital_data, business_partener_data
    except Hospital.DoesNotExist:
        return [], []


@bind('api/hospital/list_by_ids')
@cache_page(30 * 60)
def list_hospital_by_ids(hospital_ids):
    """
    获取结构详情batch接口
    :param hospital_ids:
    :return:
    """
    queryset = Hospital.objects.filter(pk__in=hospital_ids)
    data = {pk: {} for pk in hospital_ids}
    for hospital in queryset:
        data[hospital.id] = hospital.officer.doctor_detail_v2() if hospital.officer else {}
    return data

@bind_context('api/hospital/topic',login_required=True)
def list_hospital_topic(ctx,lat,lng,query,search=False):
    '''
        发帖关联医院
    '''
    info_logger.info("取相关机构----")
    user =get_user_from_context(ctx)
    #user=User.objects.get(id=20891740)

    hospitals=[]
    if not search:
        #用户支付过的订单
        orders=Order.objects.filter(user=user,status__in=[ORDER_STATUS.PAID,ORDER_STATUS.USED,ORDER_STATUS.SETTLED]).order_by("-status","id")


        for item in orders:
            info_logger.info(item.id)
            hospitals.append(item.service.doctor.hospital)
        info_logger.info("用户支付过的订单---")
        info_logger.info(orders)
        info_logger.info("订单关联的医院---")
        info_logger.info(hospitals)

        #用户咨询美购所在医院
        user_id_list=list()
        conversation_status_list=ConversationUserStatus.objects.filter(user_id=user.id).order_by("-id")[:100]
        for item in conversation_status_list:
            user_id_list.extend(item.conversation.user_ids())

        info_logger.info("用户长度---")
        info_logger.info(len(user_id_list))

        #查找到会话关联的用户id
        user_id_list=set(user_id_list)
        user_id_list.remove(user.id)

        user_id_list=list(user_id_list)

        info_logger.info("用户咨询过的医生ids")
        info_logger.info(user_id_list)

        try:
            doctors=Doctor.objects.filter(user_id__in=user_id_list)
            for doctor in doctors:
                if doctor.hospital:
                    hospitals.append(doctor.hospital)
        except Exception as e:
            info_logger.info(e)
            pass
        info_logger.info("拿到的医院列表--")
        info_logger.info(hospitals)

        #取最近10条购物车
        person=Person.objects.get(user=user)
        shopcarts=Shopcart.objects.filter(person=person,service_item__is_delete=False).order_by('-update_time')[0:10]

        info_logger.info("拿到的购物车---")
        info_logger.info(len(shopcarts))

        #获取购物车关联的美购信息
        for item in shopcarts:
            hospitals.append(item.service.doctor.hospital)

        info_logger.info("最后拿到的医院列表---")
        info_logger.info(hospitals)

    if search or len(hospitals)<=40:
        #从搜索提示接口返回医院列表

        rpc_client = get_rpc_remote_invoker()

        #拿不到地理位置时默认定位为北京
        if query=="wordwide" or lat==0 and lng==0:
            query='北京'

        info_logger.info("发起rpc请求----")
        info_logger.info("搜索条件为:")
        info_logger.info("query:{0},lat:{1},lng:{2}".format(query,lat,lng))

        try:
            response = rpc_client['search_tips/search/auto_complete_query'](q=query, lat=lat, lng=lng).unwrap()

            data=response.get('data', [])
            info_logger.info("搜索到的医院列表")
            info_logger.info(data)

            names=[item.get('ori_name').strip() for item in data]
            info_logger.info(names)
            search_hospitals=Hospital.objects.filter(name__in=names)

            info_logger.info(len(search_hospitals))

            hospitals.extend(search_hospitals)
        except Exception as e:
            info_logger.info(e)

    info_logger.info("此时的医院数为---")
    info_logger.info(len(hospitals))

    results=[]
    _hospitals=list(set(hospitals))
    _hospitals.sort(key=hospitals.index)
    hospitals=_hospitals[0:20]

    for hospital in hospitals:
        hospital_lat=hospital.baidu_loc_lat if hospital.baidu_loc_lat else hospital.google_loc_lat
        hospital_lng=hospital.baidu_loc_lng if hospital.baidu_loc_lng else hospital.google_loc_lng

        distance=999999999
        if hospital_lat and hospital_lng:
            distance=calc_distances_by_lat_lnt(lat,lng,hospital_lat,hospital_lng)

        #机构管理者
        officer = hospital.officer

        if officer and officer.portrait:
            portrait = get_full_path(officer.portrait)
        elif hospital.portrait:
            portrait = get_full_path(hospital.portrait)
        else:
            portrait = get_full_path(u'img%2Fyiyuan.png')

        data={
            "portrait":portrait,
            "id":hospital.id,
            "gm_url":gm.hospital_welfare_home(hospital.id,hospital.name),
            "name":hospital.name,
            "highlight_name":"" if not query else hospital.name.replace(query,"<ems>{0}</ems>".format(query)),
            "distance":display_distances(distance)
        }
        results.append(data)

    return results

@bind_context('api/hospital/location',login_required=False)
def get_locations(ctx):
    '''
        拿去全部医院的坐标
    '''
    locations=Hospital.objects.values("id","baidu_loc_lat","baidu_loc_lng","google_loc_lat","google_loc_lng").all()

    return list(locations)


@bind("api/hospital/iterator_for_inner")
def hospital_iterator_for_inner(start_num=0, count=10):
    '''仅供内部调用!!!'''
    result = {
        "hospital_ids": [],
    }

    hospitals = Hospital.objects.all().only("id")[start_num: start_num + count]
    result["hospital_ids"] = list(hospitals.values_list("id", flat=True))

    return result


@bind('api/hospital/diary_tags')
def get_hospital_diary_tags(hospital_id, tag_v3=False):
    """
    获取机构相关的案例标签
    :param hospital_id:
    :param tag_v3:
    :return:
    """

    result = {
        "item_list": [],
        "item_list_raw": [],
    }

    if not hospital_id:
        return result

    hospital_doctors = Doctor.objects.filter(hospital_id=hospital_id, is_online=True)
    all_doctor_items = [doctor.get_doctor_item_list(tag_v3=tag_v3)[1] for doctor in hospital_doctors]

    hospital_items_dic = {}
    for item in chain(*all_doctor_items):
        name, nums = item['name'].replace('例', '').rsplit(" ", 1)

        if name not in hospital_items_dic:
            hospital_items_dic[name] = {
                'name': name,
                "cnt": int(nums),
                "tag_id": item['tag_id'],
            }
        else:
            hospital_items_dic[name]['cnt'] += int(nums)

    hospital_items = sorted(hospital_items_dic.values(), key=lambda x: x['cnt'], reverse=True)

    result['items'] = [u'{}'.format(v['name']) for v in hospital_items]
    result['item_list_raw'] = [{
        'name': u'{} {}例'.format(v['name'], v['cnt']),
        'tag_id': v['tag_id']
    } for v in hospital_items]

    return result


@bind("api/simple_hospital/list")
def get_simple_hospital_list(start_num=0, count=10):

    data = []
    hospitals = Hospital.objects.exclude(id='wanmeizhensuo')

    for hospital in hospitals[start_num:start_num+count]:
        data.append({
            "id": hospital.id,
            "name": hospital.name,
        })

    return data


@bind('api/hospital/feed_info')
def gets_hospital_feed_infos(ids):
    if not ids:
        return {}
    if len(ids) > 100:
        return {}
    return _gets_hospital_feed_infos(ids)


hospital_cache_wrap = cache_wrap(hospital_search_tags_cache, pre_fix='hospital_feed_info', expire=7200, time_range=600)


@hospital_cache_wrap.batch
def _gets_hospital_feed_infos(ids):

    model = Hospital
    objs = model.objects.filter(id__in=ids)

    res = {}
    for obj in objs:
        info = {
            'accept_private_msg': obj.accept_private_msg,
            'is_recommend': obj.is_recommend,
            'rate': obj.rate,
            'hospital_name': obj.name,  # hospital name
            'hospital_id': obj.id,
            'hospital_type': obj.hospital_type,
            'share_amount': obj.share_diary_num,
            'extend_tips': "",
            'show_rating': '1' if obj.rate >= 1 else '0',
            'city_id': obj.city_id,
            'lng': obj.baidu_loc_lng if obj.baidu_loc_lng else obj.google_loc_lng,
            'lat': obj.baidu_loc_lat if obj.baidu_loc_lat else obj.google_loc_lat,
        }

        info['portrait'] = obj.officer.portrait
        info['did'] = info['doctor_id'] = obj.officer.id if obj.officer else ''
        lincence = obj.officer.get_doctor_lincence(obj.officer.title, obj.officer.get_hospital_service_num())
        info['title'] = lincence['title']
        info['name'] = obj.officer.name if obj.officer else ''
        service_amount = obj.officer.get_hospital_service_num() if obj.officer else 0
        info['show_v'] = '1' if service_amount > 0 else '0'
        info['subscribe_num'] = obj.officer.sell_amount_display() if obj.officer else 0
        info['accept_call'] = obj.officer.accept_call if obj.officer else False
        info['items'] = obj.officer.operate_tag() if obj.officer else []
        info['service_num'] = service_amount
        badges, is_special_appearance = obj.get_hospital_award_result()
        info['is_special_appearance'] = is_special_appearance
        info['badges'] = badges
        operate_tags = obj.officer.operate_tag() if obj.officer else []
        try:
            hospital_scale = obj.hospital_extra.get_scale_desc()
        except:
            hospital_scale = ''
        info['display_tags'] = obj.format_display_tags(hospital_scale, badges, operate_tags)
        info['is_hospital'] = True
        info['cases'] = obj.officer.cases()
        res[obj.id] = info
    return res


@bind("api/get_hospital_id")
def get_hospital_id(hospital_map_id):
    obj = None
    from hippo.models.hospital import HospitalMap
    obj = HospitalMap.objects.filter(id=hospital_map_id).first()
    if obj:
        return {'hospital_id': obj.hospital_id}
    return {'hospital_id': hospital_map_id}

@bind("api/get_hospital_list")
def get_hospital_list():
    hospitals = Hospital.objects.all()
    hospital_list = []
    for hospital in hospitals:
        hospital_list.append({"hospital_id": hospital.id, "hospital_name": hospital.name})
    return hospital_list


@bind("api/get_hospital_ids_by_name")
def get_hospital_id_by_name(name):
    """
    通过hostpital name获取ids
    """
    try:
        rows = Hospital.objects.filter(name__contains=name).values('id')
        hospital_ids = [ row['id'] for row in rows ]
    except:
        hospital_ids = []
    return hospital_ids


@bind("api/get_hospital_name_by_id")
def get_hospital_name_by_id(ids):
    """
        通过hospital id列表获取name
        return { <id>: <name> }
    """
    ids = list(set(ids))
    try:
        rows = Hospital.objects.filter(id__in=ids).values('id', 'name')
        hospital_obj = {}
        for row in rows:
            hospital_obj[row['id']] = row['name']
    except:
        hospital_obj = {}
    return hospital_obj
