# coding: utf-8

import datetime
import itertools
from django.db import connection
from django.conf import settings

from gm_types.gaia import PLATFORM_CHOICES

from rpc.decorators import bind_context, bind
from api.models import DeviceBinding
from api.tool.user_tool import get_user_from_context

from statistic.models import Device
from django.contrib.auth.models import User
from api.models.area import City
from api.tool.datetime_tool import get_timestamp_epoch


@bind_context('api/device_binding/update')
def update_device_binding(ctx, device_id):

    """

    :param ctx:
    :param device_id:
    :return:
    """
    user = get_user_from_context(ctx)
    if not (user and device_id):
        return False

    city = user.userextra.city
    province = city.province if city else None
    DeviceBinding.objects.update_or_create(user=user, defaults={
        'device': device_id, 'city': city, 'province': province
    })


@bind('api/device/is_doctor_device')
def is_doctor_device(device_id):
    """

    :param device_id:
    :return:
    """
    if not device_id:
        return False
    try:
        device = Device.objects.get(device_id=device_id)
    except (Device.DoesNotExist, Device.MultipleObjectsReturned):
        return False

    return device.user.filter(doctor__isnull=False).exists()


@bind('api/device/user_app_version')
def get_device_app_version_by_user_id(user_id):
    """通过用户ID获取最近使用的客户端app版本号

    :param: user_id: 用户ID
    :return: version string 版本号
    """
    # TODO: add 5 min cache
    try:
        device = Device.objects.only('version', 'last_activity').filter(
            user__id=user_id, platform__in=[PLATFORM_CHOICES.ANDROID, PLATFORM_CHOICES.IPHONE]
        ).order_by('-last_activity').first()
    except:
        return "0.0.0"
    return device.version if device and device.version else '0.0.0'


@bind('api/device/get_device_city')
def get_city_of_devices(device_id_list):
    result = {}
    date_time_default = datetime.datetime(year=2000, month=1, day=1)
    device_split_list = [device_id_list[i:i+50] for i in range(0, len(device_id_list), 50)]
    #
    for _device_list in device_split_list:
        res = User.objects.filter(devices__device_id__in=_device_list).values_list(
            'devices__device_id',
            'userextra__current_city_id',
            'userextra__update_time'
        )
        for (device_id, current_city_id, update_time) in res:
            if not (device_id and current_city_id and update_time):
                continue
            if update_time > result.get(device_id, {}).get('update_time', date_time_default):
                result[device_id] = {
                    "current_city_id": current_city_id,
                    "update_time": update_time
                }
    #
    all_city_ids = list(set([i['current_city_id'] for i in result.values()]))
    city_info = City.objects.filter(
        id__in=all_city_ids,
        is_online=True
    ).in_bulk(all_city_ids)
    #
    for _device_id in result.keys():
        city_item = city_info.get(result[_device_id]['current_city_id'])
        if not city_item:
            result[_device_id] = u'中国'
        else:
            result[_device_id] = city_item.name
    #
    return result


@bind('api/device/get_by_user_ids')
def get_devices_by_user_ids(user_ids):
    if not user_ids:
        return []
    res = Device.objects.filter(user__in=user_ids).values_list('device_id', flat=True)
    return [r for r in res]


@bind("api/device/get_info_by_device_id")
def get_info_by_device_id(platform, device_id):
    """
    通过device_id获取设备信息
    :param platform:
    :param device_id:
    :return:
    """
    result = {}

    device = Device.objects.filter(platform=platform, device_id=device_id).first()
    if not device:
        return result

    return {
        "id": device.id,
        "device_id": device.device_id,
        "create_timestamp": get_timestamp_epoch(device.created_time),
    }


@bind('api/device/reset_device_created_time_as')
def reset_device_created_time_as(platform, device_id, date=None):
    # NOTE: DO NOT MODIFY THIS METHOD, DO NOT USE `date` parameter
    dvs = Device.objects.filter(device_id=device_id, platform=platform)
    if not dvs:
        return {'success': False}

    for dv in dvs:
        dv.created_time = datetime.datetime.now()
        dv.save()

    return {'success': True}


@bind("api/device/get_user_id_by_device_ids")
def get_user_id_by_device_ids(device_ids):
    """
    通过 设备ID 获取对应的 用户ID
    :param device_ids:
    :return:
    """
    result = {}

    if not device_ids:
        return result

    device_infos = list(Device.objects.filter(
        device_id__in=device_ids
    ).values_list("id", "device_id"))

    _ids = list(map(lambda item: str(item[0]), device_infos))

    query_sql = "select device_id, user_id from statistic_device_user where device_id in ({ids_str}) order by device_id asc"
    query_sql = query_sql.format(ids_str=",".join(_ids))
    cursor = connection.cursor()
    cursor.execute(query_sql)

    result_tuple = cursor.fetchall()
    did_user_ids_map = {}
    for device_id, items in itertools.groupby(result_tuple, key=lambda item: item[0]):
        did_user_ids_map[device_id] = [int(item[1]) for item in items]

    for pk, device_id in device_infos:
        _user_ids = did_user_ids_map.get(pk, [])
        if not _user_ids:
            continue

        result[device_id] = _user_ids

    return result
