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

from django.conf import settings
from django.db.models import Q
from rpc.decorators import bind_context
from api.tasks.push_task import (
    allocate_push_task_one,
    allocate_push_task_multi,
    allocate_push_task_multi_for_other_style
)
from api.tasks.push_task import query_push_task, push_tags_task
from api.models import PushTask, City, Tag, Region
from rpc.decorators import list_interface
from message.utils.push_service import eta_2_push_time
from gm_types.gaia import HERA_PUSH_TYPE, PLATFORM_CHOICES
from gm_types.push import PUSH_STAT_CATEGORY, SEGMENT_TYPE, HERA_TASK_TYPE
from rpc.context import get_rpc_remote_invoker
from api.tool.log_tool import logging_exception
from statistic.models import Device
TIME_ZONE = settings.TIME_ZONE

HERA2PUSH_STAT = {
    HERA_PUSH_TYPE.TOPIC: PUSH_STAT_CATEGORY.HERA_TOPIC,
    HERA_PUSH_TYPE.SERVICE: PUSH_STAT_CATEGORY.HERA_SERVICE,
    HERA_PUSH_TYPE.SPECIAL: PUSH_STAT_CATEGORY.HERA_SPECIAL,
    HERA_PUSH_TYPE.DIARY: PUSH_STAT_CATEGORY.HERA_DIARY,
    HERA_PUSH_TYPE.ZONE: PUSH_STAT_CATEGORY.HERA_ZONE,
    HERA_PUSH_TYPE.WEBPAGE: PUSH_STAT_CATEGORY.HERA_WEBPAGE,
    HERA_PUSH_TYPE.ACTIVITY: PUSH_STAT_CATEGORY.HERA_ACTIVITY,
    HERA_PUSH_TYPE.ZHIBO: PUSH_STAT_CATEGORY.HERA_ZHIBO,
    HERA_PUSH_TYPE.TAG: PUSH_STAT_CATEGORY.HERA_TAG,
    HERA_PUSH_TYPE.COLUMN: PUSH_STAT_CATEGORY.HERA_COLUMN,
    HERA_PUSH_TYPE.QUESTION: PUSH_STAT_CATEGORY.HERA_QUESTION,
    HERA_PUSH_TYPE.ANSWER: PUSH_STAT_CATEGORY.HERA_ANSWER,
    HERA_PUSH_TYPE.TRACTATE: PUSH_STAT_CATEGORY.HERA_TRACTATE,
}


@bind_context("api/support/push/one")
def push_message_one(ctx, platform=None, user_id=None, extra=None, alert='', eta=None,
                     sandbox=False, hera_pushtype=None, hera_pushtask_id=None):
    if platform is None:
        return
    """
    把推送任务发送到Celery中
    :param platform: 推送的平台
    :param query: 推送的用户，内容为Q的组合，可以在User.objects.filter()中使用的
    :param extra: 推送的附加消息
    :param alert: 推送消息文本
    :param eta: 定时执行
    :param sandbox: iOS是否使用sandbox
    :return:
    """
    kwargs = {
        'platform': platform,
        'user_id': user_id,
        'extra': extra,
        'alert': alert,
        'eta': eta,
        'labels': {
            'hera_push_task_id': hera_pushtask_id,
            'push_stat_category': HERA2PUSH_STAT[hera_pushtype]
            if hera_pushtype in HERA2PUSH_STAT else None,
            'event_type': 'push',
            'event': 'operator_daily' if hera_pushtype in HERA2PUSH_STAT else '',
        },
    }
    allocate_push_task_one(**kwargs)


@bind_context("api/support/push/province")
def push_message_province(
        ctx, platform=None, province_id=None, extra=None, alert='', eta=None,
        sandbox=False, hera_pushtype=None, hera_pushtask_id=None):
    labels = {
        'hera_push_task_id': hera_pushtask_id,
        'push_stat_category': HERA2PUSH_STAT[hera_pushtype]
        if hera_pushtype in HERA2PUSH_STAT else None,
        'event_type': 'push',
        'event': 'operator_daily' if hera_pushtype in HERA2PUSH_STAT else '',
        'hera_task_type': HERA_TASK_TYPE.MESSAGE,
    }
    query = Q(userextra__city__province__id__in=province_id)
    query_push_task(platform=platform, query=query, extra=extra, alert=alert, labels=labels)


@bind_context("api/support/push/all")
def push_message_all(
        ctx, platform=None, extra=None, alert='', eta=None, sandbox=False,
        hera_pushtype=None, hera_pushtask_id=None):
    labels = {
        'hera_push_task_id': hera_pushtask_id,
        'push_stat_category': HERA2PUSH_STAT[hera_pushtype]
        if hera_pushtype in HERA2PUSH_STAT else None,
        'event_type': 'push',
        'event': 'operator_daily' if hera_pushtype in HERA2PUSH_STAT else '',
        'hera_task_type': HERA_TASK_TYPE.MESSAGE,
    }
    rpc_invoker = get_rpc_remote_invoker()
    try:
        rpc_invoker['push2/push/user/notification/all'](
            platform=platform,
            alert=alert,
            extra=extra,
            push_time=eta_2_push_time(eta),
            labels=labels,
        ).unwrap()
    except Exception as e:
        logging_exception()


@bind_context("api/support/push_multi_style/all")
def push_message_all(
        ctx, platform=None, extra=None, alert='', eta=None, sandbox=False,
        hera_pushtype=None, hera_pushtask_id=None, others=None):
    labels = {
        'hera_push_task_id': hera_pushtask_id,
        'push_stat_category': HERA2PUSH_STAT[hera_pushtype]
        if hera_pushtype in HERA2PUSH_STAT else None,
        'event_type': 'push',
        'event': 'operator_daily' if hera_pushtype in HERA2PUSH_STAT else '',
        'hera_task_type': HERA_TASK_TYPE.MESSAGE,
    }
    rpc_invoker = get_rpc_remote_invoker()
    try:
        rpc_invoker['push2/push/user/notification_multi_style/all'](
            platform=platform,
            alert=alert,
            extra=extra,
            push_time=eta_2_push_time(eta),
            labels=labels,
            others=others,
        ).unwrap()
    except Exception as e:
        logging_exception()


@bind_context("api/support/push/precision")
def push_message_precision(
        ctx, platform=None, extra=None, alert='', eta=None, sandbox=False,
        hera_pushtype=None, hera_pushtask_id=None):
    """
    向用户版精准推送, 各筛选条件之间取交集
    :param tag_ids: 推送的tag_ids
    :param city_ids: 推送的city_ids
    :param segments: 推送的用户分群 list of gm_types.push.SEGMENT_TYPE
    :param platform: 设备类型列表(android, ios), i.e. PLATFORM_CHOICES,
        只会向该列表中的设备推送
                         None表示向所有设备类型推送
    :param alert: 消息文本
    :param extra: 附加信息dict
    :param silent: 是否静默推送
    :param push_time: 定时推送时间, epoch表示
    :param urgency: 推送紧急程度, 目前请使用默认值
    :param labels: 统计标签, 用于统计日志追踪hera任务id等
    :return: 对于立即推送, 返回None.
        对于定时推送, 将返回{"task_id":TASK_ID}, 其中TASK_ID为一个字符串
        可用于撤销推送任务.
    """
    labels = {
        'hera_push_task_id': hera_pushtask_id,
        'push_stat_category': HERA2PUSH_STAT[hera_pushtype]
        if hera_pushtype in HERA2PUSH_STAT else None,
        'event_type': 'push',
        'event': 'operator_daily' if hera_pushtype in HERA2PUSH_STAT else '',
        'hera_task_type': HERA_TASK_TYPE.MESSAGE,
    }
    pushtask = PushTask.objects.get(pk=hera_pushtask_id)
    tag_ids = [item.id for item in pushtask.push_tags.all()]
    city_ids = [item.id for item in pushtask.city.all()]
    for region in pushtask.region.all():
        region_cities = [item.id for item in region.cities()]
        city_ids.extend(region_cities)
    city_ids = list(set(city_ids))
    segments = []
    if pushtask.push_user_type:
        segments.append(pushtask.push_user_type)
    else:
        segments = None
    rpc_invoker = get_rpc_remote_invoker()
    try:
        rpc_invoker['push2/push/user/notification/precision'](
            tag_ids=tag_ids,
            city_ids=city_ids,
            segments=segments,
            platform=platform,
            alert=alert,
            extra=extra,
            push_time=eta_2_push_time(eta),
            labels=labels,
        ).unwrap()
    except Exception as e:
        logging_exception()


@bind_context("api/support/push/users")
def push_message_users(ctx, platform=None, user_ids=None, extra=None, alert='', eta=None, hera_pushtype=None,
                             sandbox=False, hera_pushtask_id=None):
    if platform is None:
        return
    """
    :param platform: 推送的平台
    :param extra: 推送的附加消息
    :param alert: 推送消息文本
    :param eta: 定时执行
    :return:
    """
    kwargs = {
        'platform': platform,
        'user_id': user_ids,
        'extra': extra,
        'alert': alert,
        'eta': eta,
        'labels': {
            'hera_push_task_id': hera_pushtask_id,
            'push_stat_category': HERA2PUSH_STAT[hera_pushtype]
            if hera_pushtype in HERA2PUSH_STAT else None,
            'event_type': 'push',
            'event': 'operator_daily' if hera_pushtype in HERA2PUSH_STAT else '',
        },
    }
    allocate_push_task_multi(**kwargs)


@bind_context("api/support/push_multi_style/users")
def push_by_multi_users(ctx, platform=None, extra={}, alert='', eta=None, hera_pushtype=None, hera_pushtask_id=None,
                  sandbox=False, user_ids=[], other_style={}):
    """
    :param ctx:
    :param platform: 用户平台
    :param alert: 消息文本
    :param extra: 附加信息dict
    :param eta:
    :param hera_pushtype:
    :param hera_pushtask_id:
    :param users_id: 用户的id
    :param params: 一些额外补充的参数
    :return:
    """
    kwargs = {
        'platform': platform,
        'user_ids': user_ids,
        'extra': extra,
        'alert': alert,
        'eta': eta,
        'labels': {
            'hera_push_task_id': hera_pushtask_id,
            'push_stat_category': HERA2PUSH_STAT[hera_pushtype] if hera_pushtype in HERA2PUSH_STAT else None,
            'event_type': 'push',
            'event': 'operator_daily' if hera_pushtype in HERA2PUSH_STAT else '',
        },
        'other_style': other_style,
    }
    allocate_push_task_multi_for_other_style(**kwargs)


@bind_context("api/support/jpush/bind")
def jpush_bind(ctx, registration_id, device_id, user_id=None, city_id=None):
    city_tag_id = None
    if city_id and city_id.lower() != 'nationwide':
        try:
            city_tag_id = City.objects.get(pk=city_id).tag.id
        except City.DoesNotExist:
            pass

    # user binding
    # if user_id is not None:
    #     user = User.objects.get(id=user_id)
    #     object = JpushBindUser(registration_id=registration_id, user=user)
    #     object.store()
    # else:
    #     JpushAnonymousBindUser.save_by_city(
    #         registration_id=registration_id,
    #         city=city)

    rpc_invoker = get_rpc_remote_invoker()
    rpc_invoker['push2/bind/user/reg'](
        registration_id=registration_id,
        device_id=device_id,
        user_id=user_id,
        city_id=city_id
    ).unwrap()
    #
    # # jpush tag binding
    # rpc_invoker['push2/bind/user/tag'](
    #     registration_id=registration_id,
    #     tag_ids=[city_tag_id],
    # ).unwrap()


@bind_context('support/push_history/get')
@list_interface(offset_name='start_num', limit_name='count',
                element_model=PushTask, element_func_list=[PushTask.push_history_data])
def support_push_history_get(ctx, start_num=0, count=10):
    results = []
    push_tasks = PushTask.objects.filter(is_activity_push=True)
    push_tasks = push_tasks.filter(approver_id__isnull=False).order_by('-eta')
    for push_task in push_tasks[start_num: start_num + count]:
        results.append(push_task.push_history_data)
    return results


@bind_context('api/support/push/tags')
def push_tags(ctx, platform=None, extra=None, alert='', eta=None, hera_pushtype=None,
                             sandbox=False, hera_pushtask_id=None):
    if platform is None:
        return
    """
    :param platform: 推送的平台
    :param extra: 推送的附加消息
    :param alert: 推送消息文本
    :param eta: 定时执行
    :return:
    """
    push_tags_task.delay(platform=platform, extra=extra, alert=alert, eta=eta, hera_pushtype=hera_pushtype, sandbox=sandbox, hera_pushtask_id=hera_pushtask_id)


@bind_context('api/tractate_audit/push')
def hera_tractate_audit_push(
        ctx, platform=None, user_id=None, extra=None, alert='', labels=None, eta=None, push_type=None):
    """
    hera 后台帖子审核推送
    :param ctx:
    :param platform:
    :param user_id:
    :param extra:
    :param alert:
    :param labels:
    :param eta:
    :param push_type:
    :return:
    """
    rpc_invoker = get_rpc_remote_invoker()
    try:
        rpc_invoker['push2/push/user/automated_push/uids'](
            user_ids=[user_id],
            platform=platform,
            alert=alert,
            extra=extra,
            push_time=eta_2_push_time(eta),
            push_type=push_type
        ).unwrap()

    except Exception as e:
        logging_exception()
