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

import itertools
from collections import defaultdict
import json
from copy import deepcopy, copy

from django.conf import settings

from api.models import TransactionNearbyCity
from api.models import City, Country, Service, logging_exception, Province
from api.tool.geo_tool import get_city_by_options, get_city_name_by_options
from api.tool.geo_tool import get_location_tag_id_by_city_id
from api.tool.geo_tool import get_geo_related_tags
from api.tool.geo_tool import get_city_by_id, set_city_for_user
from api.tool.user_tool import get_user_extra_by_user_id, get_user_from_context
from api.tool.service_tool import get_city_ids_has_online_service
from api.tool.city_tool import native_and_oversea_area, NATIVE_OVERSEA_KEY, get_ares_cache, NATIVE_OVERSEA_KEY_v2, is_oversea, get_city_name_by_ids

from search.utils.service import filter_service

from rpc.decorators import bind_context, bind

from rpc.cache import citycache


@bind('api/city/city_info')
def city_info(lat, lng):
    # 临时隐藏错误的城市id设置
    # todo 在输入时进行校验，并检查有问题的数据
    # 6.3.0 Deprecated
    cities = City.objects.exclude(id=u'东阳').exclude(id=' yiwu')
    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 = []
    for city_initial in sorted(cities_dict.iterkeys()):
        data = {
            'is_auto_located': False,
            'initial': city_initial.upper(),
            'title': city_initial.upper(),
            'inline_block': False,
            'cities': cities_dict[city_initial]
        }
        result.append(data)

    """
        添加热门城市http://wiki.gengmei.cc/pages/viewpage.action?pageId=1050321
        热门城市：北京、上海、深圳、广州、重庆、成都、南京、天津、武汉、杭州、长沙、西安
    """
    hot_cities = {
        'initial': u'热',
        'title': u'热门',
        'inline_block': True,
        'is_auto_located': False,
        'cities': settings.HOT_CITIES,
        'is_hot': True,
    }
    result.insert(0, hot_cities)

    # 添加定位城市
    position_data = {
        'initial': u'#',
        'title': u'定位城市',
        'inline_block': True,
        'cities': [],
        'located_successfully': False,
        'is_auto_located': True,
    }

    position_city = get_city_by_options(lat=lat, lng=lng)
    if position_city:
        position_data.update({
            'cities': [{'id': position_city.id, 'name': position_city.name}],
            'located_successfully': True,
        })
    result.insert(0, position_data)

    return result


@bind('api/city/info_v2')
def city_info_v2(lat, lng, has_service=False):
    """
        用户选择城市 since 6.3.0

        has_service: 是否有美购，默认false
    """
    service_city_ids = []
    if has_service:
        service_city_ids = get_city_ids_has_online_service()

    result = {
        'auto_located': None,
        'countries': [],
    }
    # 定位城市
    position_city = get_city_by_options(lat=lat, lng=lng)
    country_id = None
    if position_city:
        country_id = position_city.province.country.id
        result['auto_located'] = {
            'id': position_city.id,
            'name': position_city.name,
        }
    countries = Country.objects.all()
    for country in countries:
        # 无定位展示China
        is_located = country_id is None and country.id == settings.COUNTRY_CHINA_ID
        is_located = is_located or country.id == country_id

        country_data = {
            'id': country.id,
            'name': country.name,
            'is_located': is_located,
            'groups': [],
        }
        if country.id == settings.COUNTRY_CHINA_ID:
            # 热门城市
            hot_cities = {
                'initial': u'热',
                'title': u'热门城市',
                'inline_block': True,
                'cities': settings.HOT_CITIES,
                'is_hot': True,
            }
            country_data['groups'].append(hot_cities)
        # 查找该国家的城市
        cities = City.objects.filter(province__country=country)
        cities_dict = {}
        for city_data in cities:
            if not city_data.id or city_data.id == '东阳' or city_data.id == ' yiwu':
                continue

            if has_service and city_data.id not in service_city_ids:
                continue

            if has_service and city_data.id in ['xinsu', 'segu']:
                continue

            cities_dict.setdefault(city_data.id[0], [])
            cities_dict[city_data.id[0]].append(
                {'id': city_data.id, 'name': city_data.name})

        if has_service and country.id == 'Japan':
            flag = False
            for city in cities_dict.get('D', []):
                if city.id == 'dongjing':
                    flag = True
                    break

            if not flag:
                cities_dict.setdefault('D', []).append(
                    {'id': 'dongjing', 'name': '东京'}
                )

        for city_initial in sorted(cities_dict.iterkeys()):
            cities_data = {
                'initial': city_initial.upper(),
                'title': city_initial.upper(),
                'inline_block': False,
                'cities': cities_dict[city_initial],
                'is_hot': False,
            }
            country_data['groups'].append(cities_data)

        if country_data['groups']:
            result['countries'].append(country_data)

    return result


@bind('api/city/index_city')
def index_city(lat=None, lng=None):
    _key = 'ctry_city'
    locate_city = get_city_by_options(lat=lat, lng=lng)
    locate_country_id = settings.COUNTRY_CHINA_ID
    result = citycache.get(_key)
    if result:
        result = json.loads(result)
        if locate_city:
            locate_country_id = locate_city.province.country_id
            result['auto_located'] = {
                'id': locate_city.id,
                'name': locate_city.name
            }
        for country in result['countries']:
            if country['id'] == locate_country_id:
                country['is_located'] = True
                break

        return result

    result = {
        'auto_located': None,
        'countries': [],
    }
    cache_data = {
        'auto_located': None,
        'countries': []
    }
    if locate_city:
        locate_country_id = locate_city.province.country_id
        result['auto_located'] = {
            'id': locate_city.id,
            'name': locate_city.name
        }

    for ctry in Country.objects.all():
        country = {
            'id': ctry.id,
            'name': ctry.name,
            'is_located': locate_country_id == ctry.id,
            'groups': []
        }

        if ctry.id == settings.COUNTRY_CHINA_ID:
            group = {
                'initial': u'热',
                'title': u'热门城市',
                'inline_block': True,
                'cities': settings.HOT_CITIES,
                'is_hot': True
            }
            country['groups'].append(group)

        char_to_cities = defaultdict(list)
        have = False
        for city_obj in City.objects.filter(province__country_id=ctry.id):
            # add filter specified cities
            if city_obj.id in {'东阳', ' yiwu', 'xinsu', 'segu'}:
                continue

            if ctry.id == 'Japan' and city_obj.id == 'dongjing':
                have = True

            char_to_cities[city_obj.id[0]].append({
                'id': city_obj.id,
                'name': city_obj.name
            })

        if ctry.id == 'Japan' and not have:
            char_to_cities['d'].append({
                'id': 'dongjing',
                'name': '东京'
            })

        for char in sorted(char_to_cities.iterkeys()):
            group = {
                'initial': char.upper(),
                'title': char.upper(),
                'inline_block': False,
                'cities': char_to_cities[char],
                'is_hot': False
            }

            country['groups'].append(group)

        if country['groups']:
            result['countries'].append(country)
            tmp = deepcopy(country)
            tmp['is_located'] = False
            cache_data['countries'].append(tmp)

    citycache.set(_key, json.dumps(cache_data), 5 * 60)

    return result


@bind('api/cities')
def get_cities(lat, lng, exclude_gat=False):
    """
    http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=5478804
    产品统一了APP内关于城市展示的逻辑, add at 7.6.65

    changed:
    城市展示优化 7.6.90
    http://wiki.wanmeizhensuo.com/pages/viewpage.action?pageId=5479231
    """

    data = get_ares_cache(exclude_gat=exclude_gat)

    data['auto_located'] = {
        'id': -1,
        'name': '定位失败'
    }

    native_hot_cities = {
        'initial': '热',
        'title': '热门城市',
        'is_hot': True,
        'cities': [{'id': city['id'], 'name': city['name']} for city in settings.NATIVE_HOT_CITIES]
    }

    data['countries'][0]['groups'].insert(0, native_hot_cities)
    foreign_hot_cities = copy(native_hot_cities)
    if exclude_gat:
        foreign_hot_cities['cities'] = [{'id': city['id'], 'name':city['name']} for city in settings.FOREIGN_HOT_CITIES]
    else:
        foreign_hot_cities['cities'] = [{'id': city['id'], 'name': city['name']} for city in settings.ORIGIN_FOREIGN_HOT_CITIES]
    data['countries'][1]['groups'].insert(0, foreign_hot_cities)

    located_city = get_city_by_options(lat=lat, lng=lng)
    if located_city:
        data['auto_located'] = {
            'id': located_city.id,
            'name': located_city.name
        }

    if not located_city or located_city.province.country_id == settings.COUNTRY_CHINA_ID:
        data['countries'][0]['is_located'] = True
        data['auto_located']['type'] = 1
    else:
        data['countries'][1]['is_located'] = True
        data['auto_located']['type'] = 2

    return data


@bind('api/city/is_oversea')
def is_oversea_city(city_ids, exclude_gat=False):

    return is_oversea(city_ids, exclude_gat)

@bind_context('api/city/user_city', login_required=True)
def user_city(ctx):
    user = get_user_from_context(ctx)
    if not user:
        return []

    user_extra = get_user_extra_by_user_id(user.id)
    city_model = user_extra.city
    if city_model is not None:
        city = city_model.to_dict()
        return city
    else:
        return None


@bind_context('api/city/update_user_city', login_required=True)
def update_user_city(ctx, city_id):
    user = get_user_from_context(ctx)
    user_extra = get_user_extra_by_user_id(user.id)
    result = set_city_for_user(user_extra, city_id=city_id)
    if result:
        return {'error': 0, 'message': u'城市信息设置成功'}
    else:
        return {'error': 1, 'message': u'用户信息不存在'}


@bind('api/city/current_city')
def change_city(lat, lng):
    position_city = get_city_by_options(lat=lat, lng=lng)
    result = {}
    if not position_city:
        return result

    filters = {'city_tag_id': position_city.tag.id}
    service_ids = filter_service(filters=filters, offset=0, size=1)
    if not service_ids or not service_ids['service_ids']:
        return result

    result = {
        'id': position_city.id,
        'name': position_city.name,
        'city_tag_id': position_city.tag.id,
    }
    return result


@bind('api/city/get_city_by_name')
def get_city_by_name(city_name):
    result = {
        'id': '',
        'name': ''
    }
    city = get_city_by_options(city_name=city_name)
    if city:
        result['id'] = city.id
        result['name'] = city.name
    return result


@bind('api/city/get_tag_id_by_name')
def get_tag_id_by_name(name):
    result = {}
    city_qs = City.objects.filter(name=name)[:1]
    country_qs = Country.objects.filter(name=name)[:1]
    for o in itertools.chain(city_qs, country_qs):
        result['id'] = o.id
        result['tag_id'] = o.tag_id
        break

    return result

@bind('api/city/province')
def get_are_province(id):
    result = {}
    try:
        city = City.objects.get(id=id)
        if hasattr(city, 'province'):
            result['province'] = city.province.id
    except City.DoesNotExist:
        pass
    return result


@bind('api/city/city_and_country_tag_id')
def location_tag_id_by_city_id(city_id):
    """return country tag id and city tag id."""
    return get_location_tag_id_by_city_id(city_id)


@bind('api/city/city_and_province_tag_id')
def province_and_city_id(city_id):
    return get_geo_related_tags(city_id)


@bind('api/city/locate')
def get_city_located(lat, lng):
    position_city = get_city_by_options(lat=lat, lng=lng)
    if position_city:
        result = {'city_id': position_city.id, 'city_name': position_city.name}
    else:
        result = {}
    return result


@bind("api/city/locate_v1")
def get_city_located(lat, lng):
    position_city = get_city_name_by_options(lat=lat, lng=lng, downgrad=True)
    if position_city:
        result = {"city_id": position_city.id, "city_name": position_city.name}
    else:
        result = {}
    return result


@bind("api/city/current_city/v1")
def get_current_city_info(city_id=None, lat=None, lng=None):
    """
    通过城市 id 或是 经纬度 获取当前城市的信息
    :param city_id:
    :param lat:
    :param lng:
    :return:
    """
    result = {}
    current_city = get_city_by_options(city_id=city_id, lat=lat, lng=lng)

    if current_city:
        result = {
            'id': current_city.id,
            'name': current_city.name,
            'city_tag_id': current_city.tag.id,
            'province_name': current_city.province.name,
            'region_name': current_city.province.region.name,
            'province_id': current_city.province.id,
            'region_id': current_city.province.region.id,
        }

    return result


@bind("api/city/city_by_tag_id")
def get_city_info_by_tag_id(tag_id):
    """
    通过 标签id 获取城市 信息
    :param tag_id:
    :return:
    """
    result = {}
    if not tag_id:
        return result

    city = City.objects.filter(tag_id=tag_id, is_online=True).last()
    if city:
        result = {
            "city_id": city.id,
            "city_name": city.name,
        }
    return result


@bind("api/city/city_by_ids")
def get_city_info_by_ids(city_ids):

    cities_info = get_city_name_by_ids(city_ids=city_ids)

    return cities_info


@bind("api/city/base_cities")
def get_base_cities_for_call_center():
    city = City.objects.filter(is_online=True).all()
    result = list()
    if city:
        result = list({'id': item.id, 'name': item.name} for item in city)

    return result



@bind("api/city/base_cities_dict")
def get_base_cities_dict():
    city = City.objects.filter(is_online=True).all()
    result = {}
    for item in city:
        result[item.id] = item.name
    return result


@bind("api/city/nearby_city_ids")
def get_nearby_city_ids(city_id):
    """ 查询 临近城市. """

    neary_city_ids = TransactionNearbyCity.objects.filter(
        city_id=city_id
    ).values_list("nearby_city_id", flat=True)

    return {
        "nearby_city_ids": list(neary_city_ids)
    }


@bind('api/city/city_id_to_all_related_tag_id')
def get_city_id_to_all_related_tag_id(city_ids):
    """ 批量获取city_ids对应的country_tag_ids, province_tag_ids, city_tag_ids
    Returns:
        示例:
        {
            'beijing': [<country_tag_id>, <province_tag_id>, <city_tag_id>]
        }
    """
    city_id_to_city_and_province_tag_id = {
        city_id: list(get_geo_related_tags(city_id))
            for city_id in city_ids
    }
    return city_id_to_city_and_province_tag_id
