# coding=utf8

import json
import itertools
from collections import deque, OrderedDict
import logging
from gm_types.gaia import DOCTOR_TYPE

from api.models.doctor import Doctor
from api.models.hospital import Hospital
from api.models.types import DOCTOR_ORDER_TYPE
from api.tool.geo_tool import get_location_tag_id_by_city_id
from api.tool.user_tool import get_user_city_tagid
from rpc.cache import doctor_search_tags_cache, hospital_search_tags_cache
from rpc.decorators import bind_context
from rpc.decorators import list_interface
from rpc.tool.log_tool import search_logger
from search.utils.common import get_query_matched_tags
from search.utils.doctor import search_doctor, filter_doctor
from category.models import CategoryPolymer
from search.utils.es import HIGHLIGHT_TAG
import logging


def get_doctor_hospital_info(d):
    # hospital info
    if not d:
        return

    try:
        h = d.hospital
        if not h:
            return

        res = {
            'id': d.hospital.id,
            'name': d.hospital.name,
            'hospital_type': d.hospital.hospital_type,
        }
    except Hospital.DoesNotExist:
        return

    # hospital position info
    if d.hospital.city and d.hospital.city.province:
        res['city_name'] = d.hospital.city.name
        res['city_province_name'] = d.hospital.city.province.name

    return res


@bind_context("search/doctor/esquery")
@list_interface(offset_name='offset', limit_name='size', element_model=Doctor)
def search_es_doctor(
        ctx, query='', user_city_tag_id=None, offset=0, size=5,
        sort_type=DOCTOR_ORDER_TYPE.DEFAULT, filters=None,
        current_city_id=None, is_ad=False
):
    """
    :param query:
    :param offset:
    :param size:
    :return:
        total 匹配结果数量
        id
        portrait    医生头像
        name        医生姓名
        title       医生职称
       hospital //所属机构
        相关福利数量
     """
    search_logger.info("重运营位抓取医生id----")

    # 如果是广告位的话
    doctor_ids = []

    # 如果是广告位的话
    if is_ad:
        search_logger.info("查询category polymer---")
        try:
            search_logger.info("query:{0},city_id:{1}".format(query, current_city_id))

            cp = CategoryPolymer.objects.get(name=query)
            search_logger.info(cp)
            search_logger.info(cp.id)

            cps = CategoryPolymer.get_recommend(cp.id, current_city_id)
            search_logger.info(cps)

            items = cps.get("doctor")
            for item in items:
                if item.get("content_type") == "doctor":
                    doctor_ids.append(item.get('content_id').encode("utf-8"))
        except Exception as e:
            search_logger.info(e)

        search_logger.info("运营位拿到的doctor ids")
        search_logger.info(doctor_ids)

    filters = filters or {}
    sort_params = {}

    # 只返回医生
    # http://wiki.gengmei.cc/pages/viewpage.action?pageId=4137843
    # filters['doctor_type'] = DOCTOR_TYPE.DOCTOR
    # 注销掉 是否返回医生或者机构 从filters中传入
    if not user_city_tag_id:
        user = ctx.session.user
        user_city_tag_id = get_user_city_tagid(user.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

    results = []
    # 首先进行精确匹配搜索
    es_data = filter_doctor(
        filters=dict(filters, name_raw=query),
        offset=offset,
        size=size,
        sort_type=sort_type,
        sort_params=sort_params
    )
    if es_data['total_count'] > 0:
        total = es_data['total_count']
        hits = es_data['hits']
        for hit in hits:
            hit['highlight'] = {  # a bit tricky
                'name': ['<%s>%s</%s>' % (HIGHLIGHT_TAG, query, HIGHLIGHT_TAG)],
            }
    else:
        # 如果没有结果进行模糊搜索
        es_data = search_doctor(
            query=query,
            offset=offset,
            size=size,
            sort_type=sort_type,
            filters=filters,
            sort_params=sort_params,
            is_hospital_search=True
        )
        hits = es_data["hits"]["hits"]
        total = es_data['hits']['total']

    try:
        hit_doctor_ids = [hit['_id'].encode("utf-8") for hit in hits]

        # 去重
        hit_doctor_ids_remove_duplicate = [item for item in hit_doctor_ids if item not in doctor_ids]

        # 获取doctor_id
        doctor_ids.extend(hit_doctor_ids_remove_duplicate)

        search_logger.info("拿到的doctor ids")
        search_logger.info(doctor_ids)
    except Exception as e:
        search_logger.log(e)

    for doctor_id in doctor_ids:
        try:
            doctor = Doctor.objects.get(pk=doctor_id)
        except Doctor.DoesNotExist:
            search_logger.info(u"Doctor {} not found".format(doctor_id))
            continue

        if not all([doctor.business_partener_id, doctor.b_licences or doctor.p_licences]):
            continue

        source = doctor.doctor_detail_v2(query=query)
        source['hospital'] = get_doctor_hospital_info(doctor)
        item_list, _ = doctor.get_doctor_item_list()
        source['items'] = item_list
        if doctor_search_tags_cache.get(doctor.id):
            source['items'] = json.loads(doctor_search_tags_cache.get(doctor.id))
        # 如果命中的话,加高亮
        if doctor_id in hit_doctor_ids:
            for hit in hits:
                if hit['_id'] == doctor_id:
                    highlight = hit.get('highlight', {})
        else:
            highlight = {}

        if hasattr(doctor, 'hospital'):
            source['hospital_id'] = doctor.hospital.id
        else:
            source['hospital_id'] = None

        results.append({
            'source': source,
            'highlight': highlight,
        })

    ctx.logger.app(search_esquery=dict(type='doctor', query=query, offset=offset, recall_count=len(hits)))
    return {
        'matched_tag_ids': [tag.id for tag in get_query_matched_tags(query)],
        'hits': results,
        'total': total
    }


@bind_context("search/officer/esquery")
@list_interface(offset_name='offset', limit_name='size', element_model=Doctor)
def search_es_officer(
        ctx, query='', user_city_tag_id=None, offset=0, size=5,
        sort_type=DOCTOR_ORDER_TYPE.DEFAULT, filters=None,
        current_city_id=None, services_size=None
):
    """
    :param query:
    :param offset:
    :param size:
    :return:
        total 匹配结果数量
        id
        portrait    医生头像
        name        医生姓名
        title       医生职称
       hospital //所属机构
        相关福利数量
     """
    filters = filters or {}
    sort_params = {}

    # 只返回机构管理者
    # http://wiki.gengmei.cc/pages/viewpage.action?pageId=4137843
    filters['doctor_type'] = DOCTOR_TYPE.OFFICER

    if not user_city_tag_id:
        user = ctx.session.user
        user_city_tag_id = get_user_city_tagid(user.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

    results = []
    # 首先进行精确匹配搜索
    es_data = filter_doctor(
        filters=dict(filters, name_raw=query),
        offset=offset,
        size=size,
        sort_type=sort_type,
        sort_params=sort_params
    )
    if es_data['total_count'] > 0:
        total = es_data['total_count']
        hits = es_data['hits']
        for hit in hits:
            hit['highlight'] = {  # a bit tricky
                'name': ['<%s>%s</%s>' % (HIGHLIGHT_TAG, query, HIGHLIGHT_TAG)],
            }
    # 如果没有结果进行模糊搜索
    else:
        es_data = search_doctor(
            query=query,
            offset=offset,
            size=size,
            sort_type=sort_type,
            filters=filters,
            sort_params=sort_params
        )
        total = es_data['hits']['total']
        hits = es_data["hits"]["hits"]

    doctor_id_to_highlight = {hit['_id']: hit.get('highlight', {}) for hit in hits}

    doctors = Doctor.objects.prefetch_related(
        'business_partener', 'hospital__city__province', 'hospital__hospital_extra', 'hospital__doctor_hospital', 'tags'
    ).filter(id__in=doctor_id_to_highlight.keys()).all()
    doctor_id_to_doctor_info = {}
    for doctor in doctors:
        if not all([doctor.business_partener_id, doctor.b_licences or doctor.p_licences]):
            continue

        source = doctor.doctor_detail_v2(query=query, services_size=services_size)
        source['hospital'] = get_doctor_hospital_info(doctor)
        source['address'] = doctor.hospital and doctor.hospital.location or ''
        item_list, _ = doctor.get_doctor_item_list()
        source['items'] = item_list

        highlight = doctor_id_to_highlight[doctor.id]

        if hasattr(doctor, 'hospital') and doctor.hospital:
            source['hospital_id'] = doctor.hospital.id
            if hospital_search_tags_cache.get(doctor.hospital.id):
                source['items'] = json.loads(hospital_search_tags_cache.get(doctor.hospital.id))
        else:
            source['hospital_id'] = None

        doctor_id_to_doctor_info[doctor.id] = {
            'source': source,
            'highlight': highlight,
            'services_highlight': source.get('highlight', {})
        }
    for hit in hits:
        doctor_id = hit['_id']
        doctor_info = doctor_id_to_doctor_info.get(doctor_id)
        if not doctor_info:
            continue
        results.append(doctor_info)

    ctx.logger.app(search_esquery=dict(type='officer', query=query, offset=offset, recall_count=len(hits)))

    return {
        'matched_tag_ids': [tag.id for tag in get_query_matched_tags(query)],
        'hits': results,
        'total': total
    }


@bind_context("search/hospital/esquery")
@list_interface(offset_name='offset', limit_name='size', element_model=Doctor)
def search_es_officer(
        ctx, query='', user_city_tag_id=None, offset=0, size=5,
        sort_type=DOCTOR_ORDER_TYPE.DEFAULT, filters=None,
        current_city_id=None, services_size=None, is_ad=False
):
    """
    :param query:
    :param offset:
    :param size:
    :return:
        total 匹配结果数量
        id
        portrait    医生头像
        name        医生姓名
        title       医生职称
       hospital //所属机构
        相关福利数量
     """

    # 如果是广告位的话
    ad_doctors = []
    if is_ad:
        search_logger.info("查询category polymer---")
        try:
            search_logger.info("query:{0},city_id:{1}".format(query, current_city_id))

            cp = CategoryPolymer.objects.get(name=query)
            search_logger.info(cp)
            search_logger.info(cp.id)

            cps = CategoryPolymer.get_recommend(cp.id, current_city_id)
            search_logger.info(cps)

            items = cps.get("hospital")

            for item in items:
                doctor = Doctor.objects.prefetch_related('business_partener', 'hospital__city__province',
                                                         'hospital__hospital_extra', 'hospital__doctor_hospital',
                                                         'tags').filter(hospital_id=item.get("content_id"),
                                                                        doctor_type=DOCTOR_TYPE.OFFICER).first()
                ad_doctors.append(doctor)
        except Exception as e:
            search_logger.info(e)

        search_logger.info("运营位拿到的相关doctor---")
        search_logger.info(ad_doctors)

    filters = filters or {}
    sort_params = {}

    # 只返回机构管理者
    # http://wiki.gengmei.cc/pages/viewpage.action?pageId=4137843
    filters['doctor_type'] = DOCTOR_TYPE.OFFICER

    if not user_city_tag_id:
        user = ctx.session.user
        user_city_tag_id = get_user_city_tagid(user.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

    results = []
    # 首先进行精确匹配搜索
    es_data = filter_doctor(
        filters=dict(filters, name_raw=query),
        offset=offset,
        size=size,
        sort_type=sort_type,
        sort_params=sort_params
    )
    if es_data['total_count'] > 0:
        total = es_data['total_count']
        hits = es_data['hits']
        for hit in hits:
            hit['highlight'] = {  # a bit tricky
                'name': ['<%s>%s</%s>' % (HIGHLIGHT_TAG, query, HIGHLIGHT_TAG)],
            }
    # 如果没有结果进行模糊搜索
    else:
        es_data = search_doctor(
            query=query,
            offset=offset,
            size=size,
            sort_type=sort_type,
            filters=filters,
            sort_params=sort_params,
            is_hospital_search=True
        )
        total = es_data['hits']['total']
        hits = es_data["hits"]["hits"]

    doctor_id_to_highlight = {hit['_id']: hit.get('highlight', {}) for hit in hits}
    search_doctor_ids = [hit["_id"] for hit in hits]

    doctors = Doctor.objects.prefetch_related(
        'business_partener', 'hospital__city__province', 'hospital__hospital_extra', 'hospital__doctor_hospital', 'tags'
    ).filter(id__in=search_doctor_ids).all()

    doctors = sorted(doctors, key=lambda item: search_doctor_ids.index(item.id))

    search_logger.info("广告中医生---")
    search_logger.info(ad_doctors)

    search_logger.info("查询到的医生----")
    search_logger.info(doctors)

    # 去重
    doctors = [item for item in doctors if item not in ad_doctors]

    search_logger.info("去重后的医生")
    search_logger.info(doctors)

    # 在广告医生数据后面加上搜索医生数据
    ad_doctors.extend(list(doctors))

    search_logger.info("合并后的医生---")
    search_logger.info(ad_doctors)

    doctor_id_to_doctor_info = {}
    for doctor in ad_doctors:
        if not all([doctor.business_partener_id, doctor.b_licences or doctor.p_licences]):
            continue

        source = doctor.doctor_detail_v2(query=query, services_size=services_size)
        source['hospital'] = get_doctor_hospital_info(doctor)
        source['address'] = doctor.hospital and doctor.hospital.location or ''
        item_list, _ = doctor.get_doctor_item_list()
        source['items'] = item_list

        highlight = {}
        try:
            highlight = doctor_id_to_highlight[doctor.id]
        except Exception as e:
            search_logger.info(e)

        if hasattr(doctor, 'hospital') and doctor.hospital:
            source['hospital_id'] = doctor.hospital.id
            if hospital_search_tags_cache.get(doctor.hospital.id):
                source['items'] = json.loads(hospital_search_tags_cache.get(doctor.hospital.id))
        else:
            source['hospital_id'] = None

        doctor_id_to_doctor_info[doctor.id] = {
            'source': source,
            'highlight': highlight,
            'services_highlight': source.get('highlight', {})
        }
    # 医生信息
    for doctor in ad_doctors:
        doctor_info = doctor_id_to_doctor_info.get(doctor.id)
        if not doctor_info:
            continue
        results.append(doctor_info)

    ctx.logger.app(search_esquery=dict(type='officer', query=query, offset=offset, recall_count=len(hits)))
    return {
        'matched_tag_ids': [tag.id for tag in get_query_matched_tags(query)],
        'hits': results,
        'total': total
    }
