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

import datetime
import time
from django.db.models import Q
from gm_types.error import ERROR
from gm_types.gaia import PLATFORM_CHANNEL
from django.conf import settings
from gm_types.push import PUSH_USER_TYPE2, SEND_STATUS, HERA_PUSH_PLATFORM

from api.models import PushTask, CODES, PushTask2, PushUser, PushReadLog
from api.tool.common_tool import check_platform
from api.tool.notification_tool import _notification_red_point
from rpc.decorators import bind_context, bind
from rpc.decorators import list_interface
from api.tool import notification_tool
from api.tool.user_tool import get_user_from_context
from rpc.tool.error_code import gen
from rpc.tool.log_tool import info_logger


def check_read_status(task_info, user_id, now_date):
    """
    获取push已读未读状态
    :param task_info:
    :param user_id:
    :param now_date:
    :return:
    """
    task_ids = [item['id'] for item in task_info]
    all_type_push_ids = list(PushUser.objects.using(settings.SLAVE_DB_NAME).filter(
        pushtask_id__in=task_ids, user=0, is_all=1).values_list('pushtask_id', flat=True)
    )
    # 7140之前 老的全量push id
    history_all_type_push_ids = list(PushUser.objects.using(settings.SLAVE_DB_NAME).filter(
        pushtask_id__in=task_ids, user=0, is_all=1, is_read=True).values_list('pushtask_id', flat=True)
    )
    # 7140之后 新的已读的全量push id
    is_read_all_type_push_ids = list(PushReadLog.objects.filter(
        push_task_id__in=task_ids, user_id=user_id).values_list('push_task_id', flat=True)
    )
    # 非全量已读ids
    has_read_ids = list(PushUser.objects.using(settings.SLAVE_DB_NAME).filter(
        pushtask_id__in=task_ids, user=user_id, is_read=True, is_all=False,
    ).values_list('pushtask_id', flat=True))
    read_info = {}
    for t in task_info:
        if t['id'] in all_type_push_ids:  # 全量push
            push_time_limit = t['pushtime'] + datetime.timedelta(days=30)
            if push_time_limit < now_date:  # 超过三十天的全量push 默认为已读
                read_info.update({t['id']: True})
            elif t['id'] in history_all_type_push_ids:  # 如果是老数据，默认已读
                read_info.update({t['id']: True})
            else:
                read_info.update({t['id']: t['id'] in is_read_all_type_push_ids})
        else:
            read_info.update({t['id']: t['id'] in has_read_ids})
    return read_info


@bind("api/notification/create")
def api_notification_create(uid, title, content='', url=''):
    return notification_tool.send_notification(uid=uid, title=title, content=content, url=url)


@bind_context('api/notification/list', login_required=True)
@list_interface(offset_name='start_num', limit_name='count')
def get_notification(ctx, start_num=0, count=10):
    user = get_user_from_context(ctx)
    data = []
    for notif in user.notification.order_by('-create_time')[start_num:start_num + count]:
        data.append(notif.get_notification_detail())
    return data


@bind_context('api/notification/not_viewed', login_required=True)
def notification_statistic(ctx, start_num=0, count=10, choose_id='0', community_id='0', platform=None):
    """
        未读消息数目
    """
    user = get_user_from_context(ctx)
    total = user.notification.filter(is_viewed=False).count()
    num = _notification_red_point(ctx, choose_id, community_id, platform)
    if (num['choose'] or num['community']) and total == 0:
        total = 1
    return {
        'total': total,
    }


@bind_context('api/notification/choose', login_required=True)
def notification_choose(ctx, platform, start_num=0, count=10):
    """
        精选通知
    """
    user = get_user_from_context(ctx)
    if not user:
        gen(CODES.MESSAGE_UNKNOWN_USER)

    tasks = PushTask.get_user_choose_query(user, platform, start_num, count)
    data = [task.to_dict() for task in tasks]
    return data


@bind_context('api/notification/community', login_required=True)
def notification_community(ctx, platform, start_num=0, count=10):
    """
    社区精选
    """
    user = get_user_from_context(ctx)
    if not user:
        gen(CODES.MESSAGE_UNKNOWN_USER)

    tasks = PushTask.get_user_community_query(user, platform, start_num, count)
    data = [task.to_dict() for task in tasks]
    return data


@bind_context('api/notification/red_point', login_required=True)
def notification_red_point(ctx, choose_id, community_id, platform):
    """
    推送小红点
    """
    return _notification_red_point(ctx, choose_id, community_id, platform)


@bind_context('api/notification/index_push')
def notification_index(ctx, platform, start_num=0, count=10):
    """
    added 7.1.5
    获取推送相关信息
    modify 711
    """
    user = get_user_from_context(ctx)

    if not user:
        return []

    push_platform = check_platform(platform)

    data = []
    tasks = list(PushUser.objects.using(settings.SLAVE_DB_NAME).filter(Q(user=user.id) | Q(is_all=True)).order_by("-id")
                 .values_list("pushtask_id", flat=True))
    now_time = datetime.datetime.now()

    task_infos = PushTask2.objects.filter(id__in=tasks, pushtime__lte=now_time, platform__in=[0, push_platform])\
                 .order_by("-pushtime")[start_num:start_num+count]\
                 .values("id", "heading", "image", "subheading", "pushvalue", "pushtype", "pushtime", "url")
    is_read_dic = check_read_status(task_infos, user.id, now_time)

    for item in task_infos:
        data.append({
            "id": item.get("id"),
            "push_type": item.get("pushtype"),
            "heading": item.get("heading"),
            "subheading": item.get("subheading"),
            "pushvalue": item.get("pushvalue") or item.get("url"),
            "image": item.get("image"),
            "create_time": item.get("pushtime").strftime('%Y-%m-%d  %H:%M:%S'),
            'time_stamp': int(time.mktime(item.get("pushtime").timetuple())),
            'is_read': is_read_dic.get(item['id'], True),
        })

    #处理老数据
    # city_id = None
    # userextra = user.userextra if user else None
    # if userextra and userextra.current_city_id:
    #     city_id = userextra.current_city_id
    # tasks = PushTask.get_index_push_query(platform, start_num=0, count=start_num+count, city_id=city_id)
    # old_data = [task.to_dict2() for task in tasks]
    # for item in old_data:
    #     data.append({
    #         "id": item.get("id"),
    #         "push_type": None,
    #         "heading": "",
    #         "subheading": item.get("title"),
    #         "pushvalue": item.get("url"),
    #         "image": "",
    #         "create_time": item.get("create_time"),
    #         "imgheader": item.get("imgheader"),
    #         "top_title": item.get("top_title"),
    #         'time_stamp': item.get("time_stamp"),
    #     })
    #
    # data = sorted(data, key=lambda item: item.get('time_stamp'), reverse=True)

    return data


@bind_context('api/notification/index_aggregation')
def notification_index_aggregation(ctx):
    """
    added 7.1.5
    获取关于我相关信息

    fix:2018-07-31
    没有未读但是有已读，返回最新的一条已读；未读已读全都没有，返回空
    """
    user = get_user_from_context(ctx)
    if not user:
        return {}

    latest_noti = user.notification.order_by('-create_time').first()
    if not latest_noti:
        return {}

    unread_count = user.notification.filter(is_viewed=False).count()

    _data = latest_noti.get_notification_detail()
    _data.update({
        'imgheader': settings.ABOUT_ME_IMG_HEADER_V2,
        'unread_count': unread_count,
        'top_title': u'关于我',
    })

    return _data


@bind_context('api/notification/not_viewed_v2', login_required=True)
def notification_statistic_v2(ctx):
    """
    用户未读消息
    """
    user = get_user_from_context(ctx)
    total = user.notification.filter(is_viewed=False).count()
    return {'total': total}


@bind_context('api/notification/readall', login_required=True)
def notification_read(ctx):
    """
    用户未读消息置位已读
    :param ctx:
    :return:
    """
    user = get_user_from_context(ctx)
    user.notification.filter(is_viewed=False).update(is_viewed=True)

    return gen(ERROR.SUCCESS)


@bind_context('api/push_msg/unread_count')
def get_push_msg_unread_count(ctx, platform=None):
    """
    获取push通知的未读消息数
    :param ctx:
    :param platform:
    :return:
    """
    user = get_user_from_context(ctx)
    if not user:
        return {'count': 0}
    push_platform = check_platform(platform)
    # 1、先获取全量push的未读总数
    time_limit = datetime.datetime.now() - datetime.timedelta(days=30)
    push_ids = list(PushUser.objects.using(settings.SLAVE_DB_NAME).filter(user=0, is_all=True, is_read=False).values_list('pushtask_id', flat=True))
    # 获取一个月内的全量推送，一个月之前的默认为已读
    all_type_push_ids = list(PushTask2.objects.using(settings.SLAVE_DB_NAME).filter(
        id__in=push_ids, online=True, platform__in=[HERA_PUSH_PLATFORM.ALL, push_platform],
        pushtime__lte=datetime.datetime.now(), pushtime__gte=time_limit,
    ).values_list('id', flat=True))

    user_read_ids = list(PushReadLog.objects.using(settings.SLAVE_DB_NAME).filter(
        user_id=user.id, push_task_id__in=all_type_push_ids,
    ).values_list('push_task_id', flat=True))
    all_type_unread_count = len(set(all_type_push_ids) - set(user_read_ids))

    # 2、获取非全量push的未读数(全量推送user_id=0)
    push_ids = PushUser.objects.using(settings.SLAVE_DB_NAME).filter(
        user=user.id, is_read=False,
    ).count()
    info_logger.info('push未读数:全量：全量ids:{}, 全量已读ids:{},非全量未读个数:{}'.format(
        set(all_type_push_ids), set(user_read_ids), push_ids
    ))

    return {
        'count': push_ids + all_type_unread_count
    }


@bind_context('api/push_msg/readall')
def push_msg_readall(ctx):
    """
    push消息一键已读
    :param ctx:
    :return:
    """
    user = get_user_from_context(ctx)
    if not user:
        return

    # 1、非全量push已读
    PushUser.objects.filter(user=user.id, is_read=False).update(is_read=True)

    # 2、全量push已读
    time_limit = datetime.datetime.now() - datetime.timedelta(days=30)
    # 全量推送ids
    push_ids = list(PushUser.objects.using(settings.SLAVE_DB_NAME).filter(user=0, is_all=True).values_list('pushtask_id', flat=True))
    # 取一个月内的全量推送
    all_type_push_ids = list(PushTask2.objects.using(settings.SLAVE_DB_NAME).filter(
        id__in=push_ids, online=True,
        pushtime__lte=datetime.datetime.now(), pushtime__gte=time_limit,
    ).values_list('id', flat=True))

    # 已读的全量推送
    has_read_ids = list(PushReadLog.objects.filter(
        push_task_id__in=all_type_push_ids, user_id=user.id
    ).values_list('push_task_id', flat=True))

    need_create = set(all_type_push_ids) - set(has_read_ids)

    push_log_list = []
    for _id in need_create:
        push_log_list.append(
            PushReadLog(
                push_task_id=_id,
                user_id=user.id,
            )
        )

    PushReadLog.objects.bulk_create(push_log_list)


@bind_context('api/push/read_one')
def one_push_read(ctx, push_id):
    """
    指定私信 已读
    :param push_id:
    :param ctx:
    :return:
    """
    user = get_user_from_context(ctx)
    if not all([push_id, user]):
        return gen(CODES.PARAMS_INCOMPLETE)
    try:
        push_task = PushTask2.objects.get(id=push_id)
    except PushTask2.DoesNotExist:
        return gen(CODES.UPDATE_FAIL)

    # 判断是否为全量push
    push_user_queryset = PushUser.objects.filter(pushtask_id=push_task.id, user=user.id)

    if push_user_queryset.exists():  # 非全量
        push_user_queryset.update(is_read=True)
    else:
        PushReadLog.objects.get_or_create(
            user_id=user.id,
            push_task_id=push_task.id,
        )
