# -*- coding: UTF-8 -*-
import json

import pinyin
from django.db import IntegrityError
from django.db.models import Q
from django.db import transaction
from django.conf import settings

from hippo.models import HospitalInstrument, HospitalVideo, \
    HospitalRecommendService, HospitalRecommendDoctor, Hospital_Extra, HospitalSpecialService, HospitalRestAssured
from rpc.decorators import bind_context
from rpc.exceptions import (RPCPermissionDeniedException, RPCIntegrityError, RPCNotFoundException)
from rpc.exceptions import GaiaRPCFaultException
from rpc.tool.dict_mixin import to_dict
from rpc.tool.log_tool import info_logger
from api.models.hospital import Hospital
from api.models.doctor import Doctor, DoctorLicence
from api.tool.user_tool import get_user_from_context
from api.tasks.hospital_task import hospital2redis
from ..utils import remote_choices, get_choices
from ..datatables import HospitalDT
from ..queries.hospital import HospitalDQ
from api.models import HospitalInfo, HospitalLicenes
from gm_types.ascle.types import HOSPITAL_INFO_REVIEW
uri_pre = 'hera/hospital'


@bind_context(uri_pre + '/choices')
def hospital_choices(ctx, q='', page=1, num=30, initial=None):
    src_map = {'id': 'id', 'text': 'name'}
    if initial is None:
        q = Q(name__contains=q) | Q(id__contains=q)
    else:
        if isinstance(initial, (list, tuple)):
            q = Q(id__in=initial)
        else:
            q = Q(id=initial)
    hospitals = Hospital.objects.filter(q)
    return get_choices(hospitals, page, num, src_map)


@bind_context(uri_pre + '/query')
def hospital_query(ctx, options):
    dqobj = HospitalDQ()
    return dqobj.process(**options)


@bind_context(uri_pre + '/list')
def hospital_datatable(ctx, req_data):
    dtobj = HospitalDT(Hospital)
    return dtobj.process(req_data, ['id', 'name', 'location'])


@bind_context(uri_pre + '/get')
def hospital_get(ctx, hospital_id, options=None):
    try:
        hospital = Hospital.objects.get(id=hospital_id)
    except:
        raise RPCNotFoundException
    if options is None:
        options = {
            'fields': None,
            'excludes': None,
            'expands': None,
        }
    hospital_data = to_dict(hospital, **options)
    hospital_data[
        'baidu_map'] = u'http://api.map.baidu.com/staticimage?center=%.3f,' \
                       u'%.3f&markers=%.3f,%.3f&width=500&height=480&zoom=16' % (
        hospital.baidu_loc_lng, hospital.baidu_loc_lat, hospital.baidu_loc_lng, hospital.baidu_loc_lat)
    hospital_data['p_licences'] = hospital.p_licences
    hospital_data['b_licences'] = hospital.b_licences
    hospital_data['instrument_intro'] = ''
    hospital_data['instrument_info'] = []
    hospital_data['video_url'] = ''
    hospital_data['video_pic'] = ''
    hospital_data['recomment_services'] = ''
    hospital_data['recomment_doctors'] = ''
    hospital_data['bed_count'] = None
    hospital_data['department_count'] = None
    instrument = HospitalInstrument.objects.filter(hospital=hospital).first()
    if instrument:
        hospital_data['instrument_intro'] = instrument.intro
        hospital_data['instrument_info'] = json.loads(instrument.content or '[]')
    video = HospitalVideo.objects.filter(hospital=hospital).first()
    if video:
        hospital_data.update(video.get_video_info())

    hospital_extra = Hospital_Extra.objects.filter(hospital=hospital).first()
    if hospital_extra:
        hospital_data['notice'] = hospital_extra.notice
        hospital_data['honor_introduction'] = hospital_extra.honor_introduction
        hospital_data['bed_count'] = hospital_extra.bed_count
        hospital_data['department_count'] = hospital_extra.department_count
        hospital_data['honor_pics'] = hospital.officer.honor_pics if hospital.officer else []
    hospital_special_service = HospitalSpecialService.objects.filter(hospital_id=hospital_id).first()
    if hospital_special_service:
        hospital_data['wifi'] = hospital_special_service.wifi
        hospital_data['paid_parking'] = hospital_special_service.paid_parking
        hospital_data['independent_treatment_room'] = hospital_special_service.independent_treatment_room
        hospital_data['dressing_room'] = hospital_special_service.dressing_room
        hospital_data['free_parking_space'] = hospital_special_service.free_parking_space
        hospital_data['smoking_room'] = hospital_special_service.smoking_room
        hospital_data['free_drink'] = hospital_special_service.free_drink
        hospital_data['free_snack'] = hospital_special_service.free_snack
        hospital_data['swip'] = hospital_special_service.swip
    hospital_rest_assured = HospitalRestAssured.objects.filter(hospital_id=hospital_id).first()
    if hospital_rest_assured:
        hospital_data['escort'] = hospital_rest_assured.escort
        hospital_data['one_to_one_consulation'] = hospital_rest_assured.one_to_one_consulation
        hospital_data['regular_return_visit'] = hospital_rest_assured.regular_return_visit

    r_services = HospitalRecommendService.recomend_services_info(hospital_id)
    r_doctors = HospitalRecommendDoctor.recomend_doctors_info(hospital_id)
    hospital_data['recommend_services'] = ','.join([x['name'] for x in r_services])
    hospital_data['recommend_doctors'] = ','.join([x['name'] for x in r_doctors])

    return hospital_data


@bind_context(uri_pre + '/edit')
def hospital_edit(ctx, hospital_id=None, hospital_info=None):
    user = get_user_from_context(ctx)
    if hospital_info is None:
        return None
    hospital_info.pop('baidu_map', None)
    hospital_info['city_id'] = hospital_info.pop('city', None) or None

    if hospital_id is None:
        try:
            old_obj = None
            hospital = Hospital.objects.create(**hospital_info)
        except IntegrityError:
            raise RPCIntegrityError
    else:
        try:
            old_obj = Hospital.objects.get(id=hospital_id)
            hospital = Hospital.objects.get(id=hospital_id)
        except:
            info_logger.info(__import__('traceback').format_exc())
            raise RPCNotFoundException
        for k, v in hospital_info.iteritems():
            setattr(hospital, k, v)

    if old_obj is not None:
        # 同时更新所有的Doctor
        if (old_obj.baidu_loc_lng == hospital.baidu_loc_lng) and (old_obj.baidu_loc_lat == hospital.baidu_loc_lat):
            # 如果百度坐标不变，则直接Save
            Doctor.objects.filter(hospital=hospital).update(google_loc_lng=hospital.google_loc_lng,
                                                            google_loc_lat=hospital.google_loc_lat)
            hospital.save()
            return hospital.id

    # TODO: 更新Google坐标 or 直接去掉

    hospital.save()
    # 保存医院名分词结果到redis
    hospital2redis(hospital.id, user)

    Doctor.objects.filter(hospital=hospital).update(
        google_loc_lng=hospital.google_loc_lng,
        google_loc_lat=hospital.google_loc_lat,
    )
    return hospital.id


@transaction.atomic
@bind_context(uri_pre + '/info/review')
def hospital_info_reject(ctx, id, is_pass, reason):
    info = HospitalInfo.objects.get(id=id)
    if info.status != HOSPITAL_INFO_REVIEW.SUBMIT:
        raise GaiaRPCFaultException(error=1, message='审核信息状态不正确', data=None)
    if not is_pass:
        info.status = HOSPITAL_INFO_REVIEW.REJECT
        info.reason = reason
    else:
        info.status = HOSPITAL_INFO_REVIEW.PASS
        hospital_info = {
            'chief_ph_count': info.major_doc,
            'associate_chief_ph_count': info.vice_doc,
            'ph_in_charge_count': info.main_doc,
            'resident_ph_count': info.in_doc,
            'ph_count': info.other_doc,
            'area_count': info.hospital_area,
            'city_count': info.city_num,
            'chain_count': info.hospital_num,
            'operation_room_count': info.operation_num,
            'injection_room_count': info.injection_num,
            'laser_room_count': info.laser_num,
            'level': info.hospital_level,
        }
        Hospital.objects.filter(id=info.hospital_id).update(**hospital_info)

        HospitalLicenes.objects.filter(hospital_id=info.hospital_id).delete()
        for obj in info.hospitalinfolicenes_set.all():
            HospitalLicenes.objects.create(
                hospital_id=info.hospital_id,
                image_url=obj.image_url,
                type=obj.type,
            )
    info.save()
