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

from __future__ import unicode_literals

import json
import math

import datetime
from django.db import transaction
from gm_types.error import ERROR
from api.tool.log_tool import logging_exception


from gm_types.gaia import MEMBERSHIP_LEVEL, USER_RIGHTS_LEVEL, DOCTOR_TYPE, PUNISHMENT_TYPE_FULL

from django.db.models import Q
from gm_dataquery.dict_mixin import to_dict

from api.tool.image_utils import get_full_path
from api.tool.user_tool import get_user_from_context, get_user_extra_by_user_id, filter_user_nick_name

from api.models import Person, User, UserExtra, City, Tag, Service, Conversation, message_signals
from api.models import UserBlackList
from api.models import MarkUser, UserInnerInfo
from hippo.models import DoctorRegister, SlaveMerchant
from hippo.models import DoctorRegisterRecord
from hippo.models import MasterMerchant
from hippo.models import MerchantRelevance, MerchantAccount, MerchantAccountRecord
from hippo.models.finance import FinanceProvince
from api.models.tickets import Punishment
from hippo.tool.chain_hospital_tools import get_merchant_message_doctors
from hippo.utils import get_doctors
from message.views.message import get_conversation_partner_refer
from rpc.context import get_rpc_remote_invoker

from rpc.decorators import bind_context, bind
from rpc.exceptions import RPCNotFoundException
from rpc.tool.error_code import CODES, gen
from rpc.cache import business_select_cache

from hera.models import UserPerm
from gm_types.doctor import DOCTOR_INFO_STATUS, DOCTOR_ACCOUNT_STATUS, DOCTOR_REGISTER_STATUS, DOCTOR_TITLE_TYPE

from hippo.tool.switch_tool import DoctorSwitch
from hippo.tool.user_tool import get_doctor_by_user_id, get_doctor_from_context
from hippo.models import Doctor, DoctorEditRecord, DoctorAccountRecord, Hospital
from rpc.tool.log_tool import info_logger
from statistic.models import Device
from rpc.tool.time_tool import get_timestamp_epoch
from themis.models import Team
from django.conf import settings


@bind('doctor/user/get_info_by_doctor_ids')
def get_info_by_doctor_ids(doctor_ids):
    """根据doctor_ids获取医生信息

    目前只获取user_id
    """
    doctors = Doctor.objects.filter(pk__in=doctor_ids)
    info_list = []
    for doctor in doctors:
        info_list.append({
            'doctor_id': doctor.id,
            'user_id': doctor.user_id,
        })
    result = {
        'doctor_info_list': info_list
    }

    return result


@bind_context("doctor/user/get_info", login_required=True)
def get_doctor_info(ctx):
    """
     根据session获取医生信息及其用户信息
    """
    # info_logger.info("ctx:{}".format(ctx))
    user = get_user_from_context(ctx)
    user_extra = get_user_extra_by_user_id(user.id)

    result = {
        'user': {
            'id': user.id,
            'real_name': user_extra.name or u'',
            'nick_name': filter_user_nick_name(user) or u'',
            'portrait': get_full_path(user_extra.portrait) or get_full_path(u'img%2Fuser_portrait.png'),
            'city': user_extra.city.name if user_extra.city else u'',
            'phone': user.person.phone or '',
            'address': user_extra.address or u'',
            'in_blacklist': UserBlackList.objects.filter(bind_user=user).exists()
        },
        'doctor': {},
        'hospital': {},
        'can_switch': False
    }

    doctor = get_doctor_by_user_id(user.id)

    if not doctor:
        raise RPCNotFoundException
    from hippo.models.chain_hospital import MasterMerchant
    try:
        is_mastermerchant = MasterMerchant.objects.filter(
            mastermerchant_id=doctor.merchant.id, is_operetor_related=True).exists()
    except:
        is_mastermerchant = False

    # 咨询师等级 0 为非咨询师
    rpc = get_rpc_remote_invoker()
    consultant_level = rpc['gm_im/transferconsultant/level'](user_id=user.id).unwrap()

    # 咨询师管理菜单
    consultant_menu = False
    if doctor.merchant:
        if doctor.merchant.id == settings.GENGMEI_MERCHANT and doctor.is_merchant:
            consultant_menu = True
    result.update({
        'doctor': {
            'id': doctor.id,
            'name': doctor.name,
            'portrait': get_full_path(doctor.portrait),
            'title': doctor.title,
            'department': doctor.department,
            'introduction': doctor.introduction,
            'phone': doctor.phone,
            'is_online': doctor.is_online,
            'accept_reserve': doctor.accept_reserve,  # 是否接受预约
            'allow_hospital_agent': doctor.allow_hospital_agent,
            'status': doctor.status,
            'msg_noti_sound': doctor.msg_noti_sound,
            'is_merchant': doctor.is_merchant,
            'merchant_id': str(doctor.merchant.id) if getattr(doctor, 'merchant', None) else None,
            'doctor_type': doctor.doctor_type,
            'is_mastermerchant': is_mastermerchant,
            #是否为旗舰店商户
            'is_store_classification': doctor.is_store_classification,
            #是否为旗舰店从属商户
            'is_store_classification_child':doctor.is_store_classification_child,
            #咨询师等级
            'consultant_level':consultant_level['level'],
            #是否显示咨询师管理菜单
            'consultant_menu':consultant_menu
        },
    })
    if doctor.hospital:
        result.update({
            'hospital': {
                'id': doctor.hospital.id,
                'name': doctor.hospital.name,
                'city_id': doctor.hospital.city_id
            },
        })

    result['can_switch'] = DoctorSwitch(ctx, doctor).can_switch()

    # 根据是否是商务选择方式登录的医生，判断是否对该医生session有访问权限
    allow = True

    business_person_id = business_select_cache.get(ctx.session.session_key)
    # 没有说明不是商务登录的, 是自己登录的
    if business_person_id:
        person = Person.objects.get(id=business_person_id)
        if 'business' in person.user.belong_groups.values_list('name', flat=True):
            # 是商务身份
            if doctor.business_partener not in UserPerm.members(person.user):
                allow = False
        else:
            allow = False
    if not allow:
        # 若是没有权限了，从当前session登出
        ctx.session.do_logout()

    return result


@bind_context("doctor/user/doctor_info", login_required=True)
def doctor_detail_info(ctx):
    """
        获取 医生的详细信息
    """
    doctor = get_doctor_from_context(ctx)
    if not doctor:
        return gen(CODES.DOCTOR_NOT_FOUND)

    return doctor.can_edit_info()


@bind_context("doctor/get_doctor_list", login_required=True)
def get_doctor_list(ctx):
    """
    获取医生所属医院的医生列表，
    如果医生为普通医生则展示自己，
    如果为机构管理者，则展示该机构下的所有医生
    """
    doctor = get_doctor_from_context(ctx)
    if not doctor:
        return gen(CODES.DOCTOR_NOT_FOUND)

    return doctor.get_merchant_doctors()


@bind_context("doctor/user/doctor_edit", login_required=True)
def doctor_edit_info(ctx, doctor_id=None):
    """
        获取 医生可修改信息
    """
    if not doctor_id:
        doctor = get_doctor_from_context(ctx)
    else:
        doctor = Doctor.objects.get(id=doctor_id)
    if not doctor:
        return gen(CODES.DOCTOR_NOT_FOUND)

    data = None
    if doctor.status in [DOCTOR_INFO_STATUS.APPLY_EDIT, DOCTOR_INFO_STATUS.REJECT]:
        record = DoctorEditRecord.objects.filter(doctor_id=doctor.id).last()
        if record:
            data = record.data()

    if data is None:
        # 若没有返回医生可以编辑的信息
        data = {
            'doctor_id': doctor.id,
            'status': DOCTOR_INFO_STATUS.CHECKED,
            'content': doctor.can_edit_info(),
        }
    return data


@bind_context("doctor/user/update_doctor", login_required=True)
def update_doctor_detail(ctx, doctor_info):
    """
     提交 医生修改个人信息
    """
    doctor_user = get_doctor_from_context(ctx)
    if not doctor_user:
        return gen(CODES.DOCTOR_NOT_FOUND)
    # todo 判断当前医生有没有权限处理医生编辑
    doctor_ids = get_doctors(doctor_user.id, only_doctor_id=True, include_master=False)
    if doctor_info.get('id') not in doctor_ids :
        return gen(CODES.NO_PERMISSION)
    doctor = Doctor.objects.get(id=doctor_info.get('id'))
    with transaction.atomic():
        record = DoctorEditRecord.objects.create(
            doctor_id=doctor.id, status=DOCTOR_INFO_STATUS.APPLY_EDIT, content=json.dumps(doctor_info)
        )
        doctor.status = DOCTOR_INFO_STATUS.APPLY_EDIT
        doctor.last_edit_time = datetime.datetime.now()
        doctor.save()
    return {'edit_record_id': record.id}


@bind_context("doctor/user/update_info", login_required=True)
def update_doctor_info(ctx, doctor_info):
    # TODO Deprecated since 2017-02-16
    """
     医生修改个人信息
    """
    user = get_user_from_context(ctx)
    doctor = Doctor.objects.filter(user=user)
    if doctor.count() != 1:
        return gen(CODES.DOCTOR_NOT_FOUND)
    doctor.update(**doctor_info)
    return None


@bind_context('doctor/user/extra_info', login_required=True)
def extra_info(ctx):
    """
        获取医生额外的信息（主要区分app client端需要的信息）
    """
    doctor = get_doctor_from_context(ctx)
    if not doctor:
        return gen(CODES.DOCTOR_NOT_FOUND)

    data = {
        'goog_at': doctor.good_at,
        'doctor_type': doctor.doctor_type,
    }
    business = UserInnerInfo.objects.filter(user_id=doctor.business_partener_id).first()
    if business:
        data['business_partener'] = {
            'id': business.user_id,
            'name': business.name,
            'phone': business.phone,
        }
    return data


@bind_context('doctor/user/mark', login_required=True)
def mark_user(ctx, target_uid, uid=None):
    """
        备注用户信息
    """
    if uid:
        user = User.objects.get(pk=uid)
    else:
        user = get_user_from_context(ctx)
    conversation = Conversation.objects.filter(uid_hash=Conversation.gen_uid_hash([target_uid, user.id])).first()
    if not conversation:
        gen(ERROR.MESSAGE_INVALID_CONVERSATION)
    cus = conversation.user_status_set.filter(user_id=user.id).first()
    data = {}
    data['comment'] = cus.comment
    return data


@bind_context('doctor/user/update_mark', login_required=True)
def submit_mark_user(ctx, target_uid, comment, uid=None):
    """
        提交 用户备注信息
    """
    if uid:
        user = User.objects.get(pk=uid)
    else:
        user = get_user_from_context(ctx)
    # mark, _ = MarkUser.objects.get_or_create(user=user, target_user_id=target_uid)
    # mark.comment = comment
    # mark.save(update_fields=['comment'])
    conversation = Conversation.objects.filter(uid_hash=Conversation.gen_uid_hash([target_uid, user.id])).first()
    if not conversation:
        gen(ERROR.MESSAGE_INVALID_CONVERSATION)
    cus = conversation.user_status_set.filter(user_id=user.id).first()
    cus.comment = comment
    cus.save(update_fields=['comment'])
    message_signals.post_touch_conversation(user, conversation)


@bind_context('doctor/user/account_info', login_required=True)
def account_info(ctx):
    doctor = get_doctor_from_context(ctx)
    if not doctor:
        return gen(CODES.DOCTOR_NOT_FOUND)
    data = doctor.doctor_account()
    return data


@bind_context('doctor/user/account_edit', login_required=True)
def account_edit(ctx):
    doctor = get_doctor_from_context(ctx)
    if not doctor:
        return gen(CODES.DOCTOR_NOT_FOUND)
    data = None
    merchant = MerchantRelevance.objects.get(doctor_id=doctor.id).merchant
    account = merchant.account
    if account and account.status in [DOCTOR_ACCOUNT_STATUS.SUBMITED, DOCTOR_ACCOUNT_STATUS.REJECT]:
        record = MerchantAccountRecord.objects.filter(account_id=account.id).last()
        if record:
            data = record.data()

    if data is None:
        # 若没有返回医生可以编辑的信息
        data = doctor.doctor_account()
    return data


@bind_context('doctor/user/submit_account', login_required=True)
def submit_account(ctx, info):
    doctor = get_doctor_from_context(ctx)
    if not doctor:
        return gen(CODES.DOCTOR_NOT_FOUND)

    if doctor.id != info.get('doctor_id'):
        return gen(CODES.NO_PERMISSION)

    with transaction.atomic():
        account = doctor.merchant.account
        record = MerchantAccountRecord.objects.create(
            account_id=account.id, status=DOCTOR_ACCOUNT_STATUS.SUBMITED, content=json.dumps(info)
        )
        account.status = DOCTOR_ACCOUNT_STATUS.SUBMITED
        account.save()
    return {'account_record_id': record.id}


@bind('doctor/user/get_doctors')
def get_doctor_by_user_ids(doctor_ids=None, user_ids=None):
    if doctor_ids:
        q = Q(pk__in=doctor_ids)
    elif user_ids:
        q = Q(user_id__in=user_ids)
    else:
        return {
            'doctors': [],
        }
    doctors = Doctor.objects.filter(q)
    doctor_dicts = []
    for doctor in doctors:
        doctor_dict = to_dict(doctor)
        punishments = Punishment.get_punishment_by_doctor_id(doctor.id).get('qa', None)
        org_sinks = []
        if punishments and punishments.get('type', None) in ['limit', ]:
            org_sink = {}
            org_sink['org_sink_start_time'] = get_timestamp_epoch(punishments['start_time'])
            org_sink['org_sink_end_time'] = get_timestamp_epoch(punishments['end_time'])
            org_sinks.append(org_sink)

        doctor_dict['org_sink'] = org_sinks
        doctor_dicts.append(doctor_dict)
    return {
        'doctors': doctor_dicts,
    }


@bind('doctor/update_last_answered_time')
def last_answered_time_by_doctor_id(doctor_id):
    doctor = Doctor.objects.get(id=doctor_id)
    doctor.last_answered_time = datetime.datetime.now()
    doctor.save()


@bind_context('doctor/merchant/get_doctors', login_required=True)
def get_merchant_doctors(ctx):
    """
    获取商户下面管理的全部医生
    :param ctx:
    :return:
    """
    doctor = get_doctor_from_context(ctx)
    data = get_merchant_message_doctors(doctor.id)
    res = {}
    for item in data:
        item.pop('doctor')
        res[str(item['user_id'])] = item
    return res


@bind_context('doctor/conversation/user_info')
def conversation_user_info(ctx, conversation_id, doctor_user_id, user_id):
    # rpc_invoker = get_rpc_remote_invoker()
    # doctor = Doctor.objects.get(user_id=doctor_user_id)
    # res_data = get_conversation_partner_refer(conversation_id=conversation_id,
    #                                           doctor_id=doctor.id
    #                                           )
    # partner_refer = res_data['partner_refer']  # from which page
    fmt = '%Y-%m-%d %H:%M:%S'
    user = User.objects.get(id=user_id)
    userextra = UserExtra.objects.get(user_id=user_id)
    # user_level = userextra.membership_level
    city_id = userextra.current_city_id
    # service = Device.objects.filter(user=user).order_by('-last_activity').first()
    # city_name = '暂无'
    # user_level_str = '暂无'
    # user_from = '暂无'
    #
    # if partner_refer == 'message_home':
    #     user_from = '私信'
    #
    # if partner_refer == 'expert_detail':
    #     user_from = '医生详情页'
    #
    # if partner_refer == 'organization_detail':
    #     user_from = '医院详情页'
    #
    # if partner_refer == 'welfare_detail':
    #     user_from = '美购详情页'
    #     try:
    #         service = Service.objects.get(id=int(res_data['partner_business_id']))
    #         user_from = user_from + ': ' + service.name
    #     except:
    #         pass
    #
    try:
        city_name = City.objects.get(id=city_id).name
    except:
        city_name = u'未知'
    try:
        age = int(math.ceil(float((datetime.datetime.now().date() - userextra.birthday).days) / 365))
        if age < 1:
            age = 0
    except:
        age = 0
    #
    # try:
    #     user_level_str = u'{0} + {1}'.format(USER_RIGHTS_LEVEL.getDesc(userextra.user_rights_level),
    #                                          MEMBERSHIP_LEVEL.getDesc(user_level))
    # except:
    #     pass
    # try:
    #     interest = Device.get_interest(user)
    # except:
    #     interest = u'暂无'
    return {
        'user_id': user_id,
        'city_name': city_name,
        # 'user_level_str': user_level_str,
        'user_level_str': '',
        # 'interest': interest,
        'interest': '',
        # 'user_from': user_from
        'user_from': '',
        'age': age,
        'nickname': user.last_name,
        'portrait': get_full_path(user.userextra.portrait) or get_full_path(u'img%2fuser_portrait.png'),
        'birthday': userextra.birthday.strftime(fmt) if userextra.birthday and userextra.birthday.year >= 1900 else '',
        'date_joined': user.date_joined.strftime(fmt) if user.date_joined else '',
        'last_login': user.last_login.strftime(fmt) if user.last_login else ''
    }


@bind_context('doctor/getdoctorinfo_byid')
def get_doctor_info_by_doctor_id(ctx, doctor_id):
    try:
        doctor = Doctor.objects.get(id=doctor_id)
    except Doctor.DoesNotExist:
        raise RPCNotFoundException

    return {
        'name': doctor.name,
        'hospital_name': doctor.hospital.name if doctor.hospital else '',
        'user_id': doctor.user.id
    }


@bind_context('doctor/getdoctorinfo_byuid')
def get_doctor_info_by_uid(ctx, user_id=None, person_id=None):
    try:
        if user_id:
            doctor = Doctor.objects.get(user_id=user_id)
        else:
            person = Person.objects.get(pk=person_id)
            doctor = Doctor.objects.get(user_id=person.user_id)
    except Exception:
        raise RPCNotFoundException

    return {'name': doctor.name,
            'hospital_name': doctor.hospital.name if doctor.hospital else '',
            'h_doctor_name': u'{}-{}'.format(doctor.hospital.name, doctor.name)
                if doctor.doctor_type == DOCTOR_TYPE.DOCTOR else doctor.name,
            'portrait': doctor.portrait,
            'doctor_id': doctor.id
            }


@bind("doctor/getdoctorinfo_by_doctor_ids")
def get_doctor_info_by_uid(doctor_ids=None):

    if not doctor_ids:
        return {}

    doctors = Doctor.objects.filter(pk__in=doctor_ids).select_related("hospital")

    result = {}
    for doctor in doctors:
        result[doctor.id] = {
            'name': doctor.name,
            'hospital_id': doctor.hospital.id if doctor.hospital else '',
            'hospital_name': doctor.hospital.name if doctor.hospital else '',
            'portrait': doctor.portrait,
            'doctor_id': doctor.id
        }

    return result


@bind_context('doctor/is_merchant')
def doctor_is_another_merchant(ctx, doctor_user_id, target_user_id):
    """
    判断target_user_id 是否是doctor_user_id的商户成员
    :param ctx:
    :param doctor_user_id:
    :param target_user_id:
    :return:
    """
    # doctor_office = Doctor.objects.get(user_id=doctor_user_id)
    # if doctor_office.doctor_type == DOCTOR_TYPE.DOCTOR:
    #     return {'is_merchant': False}
    # doctor = Doctor.objects.filter(hospital_id=doctor_office.hospital.id,
    #                                is_merchant=False,
    #                                user_id=target_user_id
    #                                )
    # if doctor.exists():
    #     return {'is_merchant': True}
    # else:
    #     return {'is_merchant': False}
    # doctor_merchant = MerchantRelevance.objects.filter(
    #     merchant__doctor__user_id=doctor_user_id,
    #     doctor__user_id=target_user_id,
    #     merchant__is_online=True
    # )
    doctor = Doctor.objects.get(user_id=doctor_user_id)
    target_doctor = Doctor.objects.get(user_id=target_user_id)
    doctor_ids = [item['doctor_id'] for item in get_merchant_message_doctors(doctor.id)]
    if target_doctor.id in doctor_ids:
        return {'is_merchant': True}
    else:
        return {'is_merchant': False}


@bind_context('doctor/finance/cities')
def doctor_finance_cities(ctx):
    provinces = FinanceProvince.objects.all()
    results = []
    for province in provinces:
        results.append({
            'id': province.id,
            'name': province.name,
            'cities': [{
                           'id': item['city_id'],
                           'name': item['city_name']
                       } for item in province.cities]
        })
    return results


@bind_context('doctor/get_merchant_doctor_id')
def get_merchant_doctor_id(ctx, doctor_id):
    """
    根据医生ID获取他的商户的医生ID
    1，如果这个医生自己标记为了一个商户，则返回该医生的ID
    2，如果这个医生没有被标记为商户，并且受医院管理，并且该医生所在的医院的机构管理者被标记为了商户，则返回机构管理者的ID
    3.其他的返回None
    """
    # doctor = Doctor.objects.get(id=doctor_id)
    # if doctor.is_merchant:
    #     return {
    #         'merchant_doctor_id': doctor.id
    #     }
    # doctor_hospital = Doctor.objects.filter(hospital_id=doctor.hospital.id, doctor_type=DOCTOR_TYPE.OFFICER)
    # if doctor.allow_hospital_agent and doctor_hospital.exists():
    #     return {
    #         'merchant_doctor_id': doctor_hospital.first().id
    #     }
    # else:
    #     return None
    merchants = MerchantRelevance.objects.filter(doctor_id=doctor_id, merchant__is_online=True)
    if merchants.exists():
        return {
            'merchant_doctor_id': merchants.first().merchant.doctor.id
        }
    else:
        return None


@bind_context('doctor/chief/info')
def doctor_chief_info(ctx, doctor_id):
    """
    获取医生所属医院的机构管理者信息
    :param ctx:
    :param doctor_id:
    :return:
    """
    doctor = Doctor.objects.get(id=doctor_id)
    try:
        chief = Doctor.objects.get(hospital_id=doctor.hospital_id, is_online=True, doctor_type=DOCTOR_TYPE.OFFICER)
    except Doctor.DoesNotExist:
        return []
    return [{'id': chief.id, 'name': chief.name}]


@bind_context('doctor/get_all_doctor_ids')
def doctor_get_all_doctor_ids(ctx):
    """
    获取全部的doctorids
    :param ctx:
    :return:
    """
    doctors = Doctor.objects.all()
    result = [item.id for item in doctors]
    return result


@bind_context('doctor/get_all_doctors')
def get_all_doctors(ctx, doctor_ids):
    """
    获取全部医生的数据
    :param ctx:
    :return:
    """
    results = {}
    doctors = Doctor.objects.filter(id__in=doctor_ids)

    for doctor in doctors:

        try:
            merchantrelevances = MerchantRelevance.objects.filter(merchant__is_online=True,
                                                                  doctor=doctor)
            try:
                hospital = doctor.hospital
            except:
                hospital = None
            try:
                merchant = merchantrelevances.first().merchant
            except:
                merchant = None

            try:
                team = Team.objects.get(id=doctor.business_group).name
            except:
                team = u''
            try:
                city_name = doctor.hospital.city.name
            except:
                city_name = u''
            results[doctor.id] = {'name': doctor.name,
                                  'hospital_id': hospital.id if hospital else u'',
                                  'hospital_name': hospital.name if hospital else u'',
                                  'city_name': city_name,
                                  'merchant_id': merchant.id if merchant else u'',
                                  'merchant_doctor_id': merchant.doctor.id if merchant else u'',
                                  'business': doctor.business_partener.username if doctor.business_partener else u'',
                                  'business_group': team
                                  }
        except Exception as e:
            print e.message
            continue

    return results


@bind('doctor/merchant/get_all_doctors')
def merchant_all_doctors(doctor_id, can_officer=False):
    try:
        merchant = MerchantRelevance.objects.get(doctor_id=doctor_id).merchant
    except:
        return [doctor_id]
    doctor = Doctor.objects.get(id=doctor_id)
    if doctor.is_merchant:
        if can_officer:
            doctor_ids = [d.doctor_id for d in merchant.merchant_doctors.all().filter(
                doctor__is_online=True
            )]
        else:
            doctor_ids = [d.doctor_id for d in merchant.merchant_doctors.all().filter(
                doctor__is_online=True, doctor__doctor_type=DOCTOR_TYPE.DOCTOR
            )]
    else:
        doctor_ids = [doctor.id]
    return doctor_ids


@bind('doctor/getdoctorinfo_bycityid')
def get_doctorinfo_by_city_id(city_id):
    """
    根据城市ID获取医生数据
    :param city_id:
    :return:
    """
    doctors = Doctor.objects.filter(hospital__city_id=city_id)
    return [{
                'doctor_id': doctor.id
            } for doctor in doctors]


@bind('doctor/get_doctor/by_merchant')
def get_doctor_by_merchant(merchant_id, offset=0, limit=10):
    doctors = MerchantRelevance.objects.filter(merchant_id=merchant_id,
                                               doctor__doctor_type=DOCTOR_TYPE.DOCTOR)
    count = doctors.count()
    ds = doctors[offset: limit]

    return {
        'count': count,
        'doctors': [ {
            'portrait': d.doctor.portrait,
            'name': d.doctor.name,
            'phone': d.doctor.user.person.phone if d.doctor.user.person else d.user.phone,
            'is_online': d.doctor.is_online,
            'id': d.doctor.id,
            'title': DOCTOR_TITLE_TYPE.getDesc(d.doctor.title),
            'is_show': int(d.doctor.is_show)
                     }for d in ds]
    }


@bind('doctor/get_register_doctor/by_merchant')
def get_register_doctor_by_merchant(merchant_id, offset=0, limit=10):
    doctors = DoctorRegister.objects.filter(merchant_id=merchant_id,status__in=[DOCTOR_REGISTER_STATUS.DATA_SUBMITTED, DOCTOR_REGISTER_STATUS.DATA_REJECT])
    count = doctors.count()
    ds = doctors[offset: limit]
    res = []
    for item in ds:
        reason = ''
        if item.status == DOCTOR_REGISTER_STATUS.DATA_REJECT:
            try:
                reason = DoctorRegisterRecord.objects.filter(doctor_register=item, status=DOCTOR_REGISTER_STATUS.DATA_REJECT).last().reject_reason
            except:
                reason = ''
        res.append({
            'id': item.id,
            'portrait': item.portrait,
            'name': item.name,
            'phone': item.person.phone if item.person else item.register_phone,
            'is_online': False,
            'reason': reason,
            'status': item.status,
            'title': DOCTOR_TITLE_TYPE.getDesc(item.title)
        })
    return {
        'count': count,
        'doctors': res
    }


@bind('doctor/get_info/by_ids')
def get_doctor_infos_by_ids(doctor_ids):
    """
    根据医生ID获取医生的信息详情
    :param doctor_ids:
    :return:
    """
    doctors = Doctor.objects.filter(id__in=doctor_ids)
    res = [d.get_doctor_base_info() for d in doctors]
    return res

@bind('doctor/get_info/by_id')
def get_doctor_infos_by_id(doctor_id):
    """
    根据医生ID获取医生的信息详情
    :param doctor_id:
    :return:
    """
    try:
        do = Doctor.objects.get(id=doctor_id)
        return do.get_doctor_base_info()
    except:
        logging_exception()
        return None


@bind('doctor/get_info/by_pids')
def get_doctor_by_personids(person_ids):
    persons = Person.objects.filter(id__in=person_ids)
    data = []
    for p in persons:
        sub = {}
        try:
            d = Doctor.objects.get(user_id=p.user_id)
        except:
            continue
        sub[p.id.hex] = {
            'id': d.id,
            'name': d.name,
            'portraid': d.portrait if d.portrait else 'https://heras.igengmei.com/slide/2016/11/30/07b076e423',
            'user_id': d.user_id
        }
        data.append(sub)
    return data


@bind_context('doctor/account/submechanisms', login_required=True)
def doctor_submechanisms(ctx, doctor_id=None, include_master=False, is_store_classification_child=False):
    """
    返回机构管理者下属所有医生，包括自己
    """

    def _gen_doctor_info(d):
        try:
            phone = d.user.person.phone
        except:
            phone = ''
        return {
            'id': d.id,
            'name': d.name,
            'user_id': d.user_id,
            'phone': phone
        }
    if doctor_id:
        doctor = Doctor.objects.get(id=doctor_id)
    else:
        doctor = get_doctor_from_context(ctx)
    if not doctor:
        return gen(CODES.DOCTOR_NOT_FOUND)
    if is_store_classification_child:
        """
        查询所关联的主旗舰店
        """
        merchant = doctor.merchant
        slave_marchant = SlaveMerchant.objects.get(slavemerchant_id=merchant.id)
        master_merchant = slave_marchant.mastermerchant
        doctor = master_merchant.mastermerchant.doctor
    if doctor.merchant and MasterMerchant.objects.filter(
            mastermerchant_id=doctor.merchant.id, is_operetor_related=True).exists():
        doctors = get_doctors(doctor_id=doctor.id, only_doctor_id=False, include_master=include_master)
    else:
        doctors = get_doctors(doctor.id)
    data = [_gen_doctor_info(d['doctor']) for d in doctors]
    return {
        'doctors': data,
    }

@bind_context('doctor/update_status', login_required=True)
def doctor_update_status(ctx, doctor_id, is_show):

    if doctor_id:
        doctor = Doctor.objects.get(id=doctor_id)
    else:
        doctor = get_doctor_from_context(ctx)

    if not doctor:
        return gen(CODES.DOCTOR_NOT_FOUND)

    doctor.is_show = is_show
    doctor.save()

    return None


@bind('cpc/promote_account/by_ids')
def get_cpc_promote_account(service_ids):
    """
    根据福利id,过滤出其中在线的id
    :param service_ids:
    :return:
    """
    effective_service_ids = Service.objects.filter(id__in=service_ids).filter(is_online=True).values('id')
    res = [id['id'] for id in effective_service_ids]
    return res


# @bind_context('doctor/batch/personal_pictures', login_required=True)
@bind_context('doctor/batch/personal_pictures')
def batch_personal_pictures(ctx, doctor_ids):
    """
    批量获取医生形象照
    """
    res = {}
    doctors = Doctor.objects.filter(id__in=doctor_ids)
    for doctor in doctors:
        personal_pictures = doctor.personal_pictures
        print(personal_pictures)
        if not personal_pictures:
            personal_picture = doctor.portrait
        else:
            personal_picture = personal_pictures[0]
        res[doctor.id] = personal_picture
    return res


# @bind_context('doctor/get_doctor_has_picture', login_required=True)
@bind_context('doctor/get_doctor_has_picture')
def get_doctor_has_picture(ctx, doctor_id):
    """
    批量获取医生形象照
    """
    res = {}
    doctor = Doctor.objects.get(id=doctor_id)
    personal_pictures = doctor.personal_pictures
    has_image = True
    if not personal_pictures:
        has_image = False
    return has_image


@bind_context('doctor/rename')
def rename(ctx, doctor_id, name):
    doctor_user = get_doctor_from_context(ctx)
    if not doctor_user:
        return gen(CODES.DOCTOR_NOT_FOUND)
    # 判断当前医生有没有权限处理医生编辑
    doctor_ids = get_doctors(doctor_user.id, only_doctor_id=True, include_master=False)
    if doctor_id not in doctor_ids:
        return gen(CODES.NO_PERMISSION)
    doctor = Doctor.objects.filter(id=doctor_id).first()
    if doctor.name != name:
        doctor.name = name
        doctor.save()

    return doctor.id


@bind('doctor/get_doctor_info_by')
def get_doctor_info_by(login_phone=None, user_id=None):
    if login_phone:
        try:
            person = Person.objects.get(phone=login_phone)
            user_id = person.user.id

            doctor = Doctor.objects.get(user__id=user_id)
            data = {
                'id':doctor.id,
                'name':doctor.name,
                'user_id':user_id,
                'merchant_id':doctor.merchant.id if getattr(doctor, 'merchant', None) else None,
                'is_merchant':doctor.is_merchant,
                'doctor_type':doctor.doctor_type
            }
            return data
        except Person.DoesNotExist, Doctor.DoesNotExist:
            gen(ERROR.DOCTOR_NOT_FOUND)

    if user_id:
        try:
            doctor = Doctor.objects.get(user_id=user_id)
            data = {
                'id': doctor.id,
                'name': doctor.name,
                'user_id': user_id,
                'merchant_id': str(doctor.merchant.id) if getattr(doctor, 'merchant', None) else None,
                'is_merchant': doctor.is_merchant,
                'doctor_type': doctor.doctor_type
            }
            return data
        except Doctor.DoesNotExist:
            gen(ERROR.DOCTOR_NOT_FOUND)


@bind('doctor/search')
def doctor_search(doctor_name=None, city_id=None, count=10, start_num=0):
    if count<0 or count>50:
        count = 50

    q = Q()
    if city_id:
        q&=Q(hospital__city_id=city_id)
    if doctor_name:
        q&=Q(name__contains=doctor_name)
    query = Doctor.objects.filter(q)
    total = query.count()
    doctor_list = []
    for item in query[start_num:start_num+count]:
        try:
            doctor_dict = {
                'doctor_id':item.id,
                'doctor_name':item.name,
                'h_doctor_name':u'{}-{}'.format(item.hospital.name, item.name) if item.doctor_type == DOCTOR_TYPE.DOCTOR and item.hospital_id else item.name,
                'user_id':item.user_id,
                'portrait': item.portrait if item.portrait else 'https://heras.igengmei.com/slide/2016/11/30/07b076e423',
            }
        except Hospital.DoesNotExist:
            doctor_dict = {
                'doctor_id': item.id,
                'doctor_name': item.name,
                'h_doctor_name': item.name,
                'user_id': item.user_id,
                'portrait': item.portrait if item.portrait else 'https://heras.igengmei.com/slide/2016/11/30/07b076e423',
            }
        doctor_list.append(doctor_dict)

    return {'total':total, 'doctor_list':doctor_list}


@bind("doctor/get_name_by_id")
def get_name_by_id(ids):
    """
        根据doctor_id获取对应的doctor_name
        return: { <docter_id>: <doctor_name> }
    """
    ids = list(set(ids))
    try:
        rows = Doctor.objects.filter(id__in=ids).values('id', 'name')
        doctor_obj = {}
        for row in rows:
            doctor_obj[row['id']] = row['name']
    except Exception as e:
        doctor_obj = {}
    return doctor_obj


@bind('doctor/get_detail/by_ids')
def get_doctor_infos_by_ids(doctor_ids):
    """
    根据医生ID获取医生的信息详情
    :param doctor_ids:
    :return:
    """
    doctors = Doctor.objects.select_related('hospital__name', 'hospital__id').filter(id__in=doctor_ids)
    res = [d.get_doctor_detail() for d in doctors]
    return res
