# coding=utf-8
import datetime
import json

from django.conf import settings
from django.db.models import Q
from gm_types.gaia import SERVICE_SCREEN_LABEL, TAG_V3_TYPE

from api.manager.tag_manager import get_bodypart_tags_with_tag_filter
from api.models import (
    Service,
    ServiceItem,
    City,
    Province,
    Tag,
    TAG_TYPE,
    Doctor,
    SERVICE_ORDER_TYPE)
from api.tool.filter_tool import (
    COMMON_AREA_CACHE_KEY,
    COMMON_TAG_CACHE_KEY,
    SERVICE_AREA_CACHE_KEY,
    SERVICE_TAG_CACHE_KEY,
    DOCTOR_AREA_CACHE_KEY,
    SERVICE_AREA_CACHE_KEY_V1,
    SERVICE_AREA_CACHE_KEY_V2,
    DOCTOR_AREA_CACHE_KEY_V1,
    DOCTOR_AREA_CACHE_KEY_V2,
    DOCTOR_AREA_CACHE_KEY_V3,
    COMMON_AREA_CACHE_KEY_V1,
    COMMON_AREA_CACHE_KEY_V2,
    COMMON_AREA_CACHE_KEY_V3,
    FILTER_AREA_CACHE_KEY_V1,
    COMMON_TAG_V3_CACHE_KEY,
    generate_new_tag_filter_by_service, build_special_new_tag_filter, SERVICE_NEW_TAG_CACHE_KEY)
from api.tool.filter_tool import build_special_area_filter
from api.tool.filter_tool import build_special_tag_filter
from api.tool.filter_tool import campaign_to_special
from api.tool.filter_tool import generate_area_filter_by_doctors, generate_doctor_area_filter, \
    generate_doctor_area_filter_v2
from api.tool.filter_tool import generate_area_filter_by_service, generate_service_area_filter, \
    generate_areas_list_v2, generate_areas_list
from api.tool.filter_tool import generate_tag_filter_by_service
from api.tool.filter_tool import get_all_areas, get_all_areas_v1, get_all_areas_v2
from api.tool.filter_tool import generate_service_area_filter_v2
from api.tool.filter_tool import get_all_tags, generate_visual_tags, get_all_new_tags
from api.tool.log_tool import logging_exception
from api.tool.service_extra_filters import ExtraFilterWithName
from api.tool.service_tool import get_city_ids_has_online_service
from launch.models.screen_label import ShortcutScreenLabel
from rpc.cache import (
    page_cache,
    make_cache_key,
    filter_cache,
    service_home_city_cache,
)
from gaia.routers import thread_local
from rpc.context import get_rpc_remote_invoker
from rpc.decorators import bind, cache_page
from rpc.tool.log_tool import info_logger


@bind('api/filter/service_home_city')
@cache_page(120)
def get_service_home_filter():
    key = 'service_home_city_key'
    try:
        city_data = service_home_city_cache.get(key)
        city_data = json.loads(city_data)
        city_ids = city_data['service_home_city_ids']
    except:
        logging_exception()
        city_ids = []

    cities = City.objects.filter(id__in=city_ids)
    cities_dict = {}
    for city_data in cities:
        if not city_data.id:
            continue
        cities_dict.setdefault(city_data.id[0], [])
        cities_dict[city_data.id[0]].append(
            {'id': city_data.id, 'name': city_data.name})

    result = []
    hot_cities = {
        'initial': u'热',
        'title': u'热门城市',
        'inline_block': True,
        'is_auto_located': False,
        'cities': settings.HOT_CITIES,
        'is_hot': True,
    }
    result.append(hot_cities)

    for city_initial in sorted(cities_dict.iterkeys()):
        data = {
            'initial': city_initial.upper(),
            'title': city_initial.upper(),
            'inline_block': False,
            'cities': cities_dict[city_initial],
            'is_auto_located': False,
        }
        result.append(data)
    return result


@bind('api/filter/provinces')
@cache_page(3600)
@thread_local(DB_FOR_READ_OVERRIDE=settings.SLAVE_DB_NAME)
def provinces_filter():
    """ v5.6.0 更新 地区筛选器按照取美购频道的顺序
    """
    province_ids = set(Service.objects.filter(is_online=True).values_list(
        'doctor__hospital__city__province', flat=True))

    provinces = Province.objects.filter(id__in=province_ids)
    result = [province.province_data() for province in provinces]

    return {'provinces': result}


@bind('api/filter/country')
def country_filter():
    """
    changelog:
    v5.9.1 创建 在之前地区筛选器(provinces_filter)基础上增加国家级别
    v6.0.0 修改 提到公共函数中调用 通用的地区筛选器 cache时间固定
    """
    areas = filter_cache.get(COMMON_AREA_CACHE_KEY)
    if areas:
        return json.loads(areas)

    areas = get_all_areas()
    return areas


@bind('api/filter/country/v1')
def country_filter_v1(exclude_gat=False):
    areas = filter_cache.get(COMMON_AREA_CACHE_KEY_V1)
    if areas:
        return json.loads(areas)

    areas = get_all_areas_v1(exclude_gat=exclude_gat)
    return areas


@bind('api/filter/country/v2')
def country_filter_v2(exclude_gat=True, lat='0', lng='0'):
    areas = filter_cache.get(COMMON_AREA_CACHE_KEY_V2)
    if areas:
        return json.loads(areas)

    return get_all_areas_v2(exclude_gat=exclude_gat)


@bind('api/filter/country/v3')
def country_filter_v2(exclude_gat=True):
    areas = filter_cache.get(COMMON_AREA_CACHE_KEY_V3)
    if areas:
        return json.loads(areas)

    areas = get_all_areas_v2(exclude_gat=exclude_gat)
    return areas


@bind('api/filter/countries')
def countries_filter(exclude_gat=True):
    """获取地区列表，过滤掉没有美购的地区。"""

    areas = filter_cache.get(FILTER_AREA_CACHE_KEY_V1)
    if areas:
        return json.loads(areas)

    cities = get_city_ids_has_online_service()
    areas = get_all_areas_v2(cities=cities, exclude_gat=exclude_gat)
    return areas


@bind('api/filter/service_areas')
def get_areas_by_services():
    """
    通过在线美购过滤掉没有美购的地区生成筛选器选项
    changelog:
    v6.0.0 创建
    """
    cache_area = filter_cache.get(SERVICE_AREA_CACHE_KEY)
    if cache_area:
        return json.loads(cache_area)

    cities = get_city_ids_has_online_service()
    areas = generate_areas_list(cities)
    return areas


@bind('api/filter/service_areas/v1')
def get_service_areas():
    areas = filter_cache.get(SERVICE_AREA_CACHE_KEY_V1)
    if areas:
        return json.loads(areas)

    services = Service.objects.filter(is_online=True)
    areas = generate_service_area_filter(services)
    return areas


@bind('api/filter/service_areas/v2')
def get_service_areas_v2(lat='0', lng='0'):
    areas = filter_cache.get(SERVICE_AREA_CACHE_KEY_V2)
    if areas:
        return json.loads(areas)

    cities = get_city_ids_has_online_service()
    return generate_areas_list_v2(cities)


@bind('api/filter/doctor_areas')
def get_areas_by_doctors():
    """
    通过在线医生过滤掉没有医生的地区生成筛选器选项
    changelog:
    v6.0.0 创建
    """
    cache_area = filter_cache.get(DOCTOR_AREA_CACHE_KEY)
    if cache_area:
        return json.loads(cache_area)

    doctors = Doctor.objects.filter(is_online=True)
    areas = generate_area_filter_by_doctors(doctors)
    return areas


@bind('api/filter/doctor_areas/v1')
def get_doctor_areas():
    areas = filter_cache.get(DOCTOR_AREA_CACHE_KEY_V1)
    if areas:
        return json.loads(areas)

    doctors = Doctor.objects.filter(is_online=True)
    areas = generate_doctor_area_filter(doctors)
    return areas


@bind('api/filter/doctor_areas/v2')
def get_doctor_areas_v2(lat='0', lng='0'):
    """获取有医生的城市列表。"""

    areas = filter_cache.get(DOCTOR_AREA_CACHE_KEY_V2)
    if areas:
        return json.loads(areas)

    doctors = Doctor.objects.filter(is_online=True)
    return generate_doctor_area_filter_v2(doctors)


@bind('api/filter/doctor_areas/v3')
def get_doctor_areas_v3():
    """获取有医生的城市列表。"""

    areas = filter_cache.get(DOCTOR_AREA_CACHE_KEY_V3)
    if areas:
        return json.loads(areas)

    doctors = Doctor.objects.filter(is_online=True)
    areas = generate_doctor_area_filter_v2(doctors)
    return areas


@bind('api/filter/service_tags')
def get_tags_by_services(ordering=False):
    """
    通过在线美购过滤掉没有美购的二级tag生成筛选器选项
    changelog:
    v6.0.0 创建
    """
    cache_tag = filter_cache.get(SERVICE_TAG_CACHE_KEY)
    cache_new_tag = filter_cache.get(SERVICE_NEW_TAG_CACHE_KEY)

    cache_tag = json.loads(cache_tag) if cache_tag else None
    cache_new_tag = json.loads(cache_new_tag) if cache_new_tag else None
    if cache_tag and cache_new_tag:
        return {'tags': cache_tag, 'new_tags': cache_new_tag}

    services = Service.objects.filter(is_online=True)
    tags = generate_tag_filter_by_service(services, ordering=ordering)
    new_tags = generate_new_tag_filter_by_service(services, ordering=ordering)
    filter_cache.setex(SERVICE_TAG_CACHE_KEY, 60 * 60 * 24, json.dumps(tags))
    filter_cache.setex(SERVICE_NEW_TAG_CACHE_KEY, 60 * 60 * 2, json.dumps(new_tags))
    return {'tags': tags, 'new_tags': new_tags}


@bind('api/filter/special_activity_tags')
def special_activity_tags(special_id=None, is_campaign=False):
    if is_campaign:
        special_id = campaign_to_special(special_id)
    cache_key = make_cache_key(build_special_tag_filter, special_id=special_id)
    tags = page_cache.get(cache_key)
    tags = json.loads(tags) if tags else None
    if tags:
        return tags
    else:
        return build_special_tag_filter(special_id=special_id)


@bind('api/filter/special_activity_new_tags')
def special_activity_new_tags(special_id=None, is_campaign=False):
    if is_campaign:
        special_id = campaign_to_special(special_id)
    cache_key = make_cache_key(build_special_new_tag_filter, special_id=special_id)
    tags = page_cache.get(cache_key)
    tags = json.loads(tags) if tags else None
    if tags:
        return tags
    else:
        return build_special_new_tag_filter(special_id=special_id)

@bind('api/filter/special_activity_areas')
def special_activity_areas(special_id=None, is_campaign=False):
    if is_campaign:
        special_id = campaign_to_special(special_id)
    cache_key = make_cache_key(build_special_area_filter, special_id=special_id) + '-v1'
    areas = page_cache.get(cache_key)
    if areas:
        return json.loads(areas)
    else:
        return build_special_area_filter(special_id=special_id, exclude_gat=True)


@bind('api/filter/tags')
def get_tags(with_hot=True, with_level_3=False):
    """
    changelog:
    v6.0.0 修改 提到公共函数中调用
    """
    cache_key = COMMON_TAG_CACHE_KEY.format(with_hot, with_level_3)
    tags = filter_cache.get(cache_key)
    if tags:
        return json.loads(tags)

    return get_all_tags(with_hot=with_hot, with_level_3=with_level_3)


@bind('api/filter/tags_v3')
def get_tags(with_hot=True, with_level_3=False):
    """
    changelog:
    v6.0.0 修改 提到公共函数中调用
    """
    cache_key = COMMON_TAG_V3_CACHE_KEY.format(with_hot, with_level_3)
    tags = filter_cache.get(cache_key)
    if tags:
        return json.loads(tags)

    return get_all_new_tags(with_hot=with_hot, with_level_3=with_level_3,
                            child_types=[TAG_V3_TYPE.FIRST_CLASSIFY, TAG_V3_TYPE.SECOND_CLASSIFY])


@bind('api/filter/tags_for_doctor_organization')
def get_tags_for_doctor_organization(tag_ids=None):
    '''
    :param doctor_id_for_diary:
    :param organization_id_for_diary:
    :return:
    '''
    permitted_tag_id_list = frozenset(
        Tag.objects.filter(
            id__in=tag_ids
        ).values_list('id', flat=True)
    )
    tags = get_bodypart_tags_with_tag_filter(
        permitted_tag_id_list=permitted_tag_id_list)

    return {'tags': tags}


@bind('api/filter/sections')
def get_sections():
    sections_list = Tag.objects.filter(is_online=True,
                                       tag_type=TAG_TYPE.BODY_PART)
    sections_list = sections_list.order_by('ordering')
    sections = [section.get_tag_info() for section in sections_list]
    return {'sections': sections}


@bind('api/filter/extra')
def extra_filter(version='0.0.0'):
    result = [
        {
            'key': efn.key,
            'name': efn.name,
        }
        for efn in ExtraFilterWithName.get_all(version)
    ]

    return {'extra_filter': result}


@bind('api/filter/screen_label')
def screen_label():

    now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    query = Q(is_delete=False)
    query &= Q(start_time__lt=now)
    query &= Q(end_time__gt=now)

    title_enums= list(ShortcutScreenLabel.objects.filter(query).order_by('position', '-create_time').values_list('title', flat=True))
    title_list = []
    for title_enum in title_enums:
        title_list.append({
            'id': title_enum,
            'name': SERVICE_SCREEN_LABEL.getDesc(title_enum),
        })
    return {'screen_label': title_list}


@bind('api/filter/related_recommend')
def related_recommend(q=None, device_id=None):

    rpc_client = get_rpc_remote_invoker()
    rs = rpc_client['doris/search/service_search_related_recommend'](device_id=device_id, query=q).unwrap()
    info_logger.info({
        'url': 'doris/search/service_search_related_recommend',
        'device_id': device_id,
        'query': q,
        'res': rs,
    })
    if not rs:
        return {}
    # rs = {
    #     "search_related_recommend": ["水光针", "菲洛嘉水光针", "有针水光"],
    #     "is_second_tagv3": True
    # }
    if rs.get('is_second_tagv3', False):
        title = '细分项目'
    else:
        title = '相关推荐'

    return {'recommend_tags': rs.get('search_related_recommend', ''), 'title': title, 'is_second_tagv3': rs.get('is_second_tagv3', False)}


@bind('api/filter/visual_services_tags')
def visual_services_tags(service_ids=None):
    """
    根据service_id列表获取对应的标签
    :param service_ids:
    :return:
    """
    if not service_ids:
        tags = get_all_tags(with_hot=False)['tags']
    else:
        services = Service.objects.filter(id__in=service_ids)
        if not services:
            tags = get_all_tags(with_hot=False)['tags']
        else:
            tags = generate_tag_filter_by_service(services)

    return tags


@bind('api/filter/visual_service_items_tags')
def visual_service_items_tags(service_item_ids=None):
    """
    根据service_item_id列表获取对应的标签
    :param service_item_ids:
    :return:
    """
    if not service_item_ids:
        tags = get_all_tags(with_hot=False)['tags']
    else:
        service_ids = ServiceItem.objects.filter(id__in=service_item_ids).values_list('service_id', flat=True)
        service_ids = list(set(service_ids))
        services = Service.objects.filter(id__in=service_ids)
        if not services:
            tags = get_all_tags(with_hot=False)['tags']
        else:
            tags = generate_tag_filter_by_service(services)

    return tags


@bind('api/filter/visual_tags_tags')
def visual_tags_tags(tag_ids=None):
    """
    可视化根据tag_ids列表获取对应的标签树形结构
    :param tag_ids: 标签id列表
    :return:
    """
    if not tag_ids:
        tags = get_all_tags(with_hot=False)['tags']
    else:
        tags = generate_visual_tags(tag_ids)

    return tags


@bind('api/filter/visual_services_areas')
def visual_services_areas(service_ids=None):
    """
    根据service_id列表获取对应的城市
    :param service_ids:
    :return:
    """
    if not service_ids:
        areas = get_all_areas_v2(exclude_gat=True)
    else:
        services = Service.objects.filter(id__in=service_ids)
        if not services:
            areas = get_all_areas_v2(exclude_gat=True)
        else:
            areas = generate_service_area_filter_v2(services)

    return areas


@bind('api/filter/visual_service_items_areas')
def visual_service_items_areas(service_item_ids=None):
    """
    根据service_item_id列表获取对应的城市
    :param service_item_ids:
    :return:
    """
    if not service_item_ids:
        areas = get_all_areas_v2(exclude_gat=True)
    else:
        service_ids = ServiceItem.objects.filter(id__in=service_item_ids).values_list('service_id', flat=True)
        service_ids = list(set(service_ids))
        services = Service.objects.filter(id__in=service_ids)
        if not services:
            areas = get_all_areas_v2(exclude_gat=True)
        else:
            areas = generate_service_area_filter_v2(services)

    return areas
