# 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 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,
        }

    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

