# -*- coding: utf8 -*-

from __future__ import unicode_literals, absolute_import, print_function

import datetime

from django.db import transaction
from gm_types.gaia import DIARY_OPERATION, CONST_STRINGS
from gm_types.user_hierarchy import EventType
from gm_types.error import ERROR as CODES
from gm_rpcd.all import bind

from utils.rpc import gen, rpc_client, logging_exception, get_current_user
from utils.stat_log import SocialStatLogForUserAction

from talos.libs.diaryrank_utils import DiaryRankTool
from talos.models.diary import Diary
from talos.models.diary import DiaryVote
from talos.services import UserService, get_user_from_context
from talos.tasks.vote import fake_vote, normal_vote, get_async_args_v2
from talos.manager.diary import diary_list_manager
from user_hierarchy.portal import process_task


@bind('diary/vote')
def diary_vote(diary_id, growth_task=True):
    """
    日记本点赞
    :param diary_id:
    :param growth_task: 是否需要做任务
    :return:
    """
    user = get_current_user()
    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    try:
        diary = Diary.objects.get(pk=diary_id)
    except Diary.DoesNotExist:
        return gen(CODES.DIARY_NOT_FOUND)

    try:
        DiaryVote.objects.get(user_id=user.id, diary_id=diary.id)
        return gen(CODES.DIARY_HAS_VOTED)

    except DiaryVote.DoesNotExist:
        dv = DiaryVote()
        dv.user_id = user.id
        dv.diary = diary
        dv.save()

        growth_value, point_value, submit_count = 0, 0, 0
        if growth_task:
            if user.id != diary.user_id:
                d = DiaryRankTool(diary_id)
                now = datetime.datetime.now()
                d.add_heat(DIARY_OPERATION.OTHER_VOTE, now)

                # add point,growth
                event_data = process_task(user_id=user.id, event_type=EventType.VOTE_MULTI_TIMES, related_item=dv.id)
                growth_value, point_value = event_data['growth_value'], event_data['point_value']
                submit_count = event_data['submit_count']

        # 对作者增加点赞数
        diary_author = UserService.get_user_by_user_id(user_id=diary.user_id)
        diary_author.incr_vote_count()

        # 实时增加点赞并且增加浏览量
        normal_vote(user, diary, is_diary=True)

        # 真实用户点赞后[60s, 1h], 点赞并增加浏览量
        countdowns, incr_range = get_async_args_v2(CONST_STRINGS.DIARY_VOTE)
        for cd in countdowns:
            fake_vote.apply_async(
                args=(1, diary.id),
                kwargs={'is_topic': False, 'incr_range': incr_range, 'force_push': True},
                countdown=cd
            )

        # 用户行为埋点，点赞相关
        SocialStatLogForUserAction.stat_log_for_like(
            content_type=SocialStatLogForUserAction.CONTENT_TYPE.diary,
            user_id=user.id,
            content_id=diary_id
        )

        re_data = {
            'tag_ids': [tag['id'] for tag in diary.tags_new_era],
            'growth_value': growth_value,
            'point_value': point_value,
            'submit_count': submit_count,
        }
        return re_data


@bind('diary/cancel_vote')
@transaction.atomic
def diary_cancel_vote(diary_id):
    """
    NOTE:
        日记本取消点赞
    """
    user = get_current_user()
    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    try:
        diary = Diary.objects.get(pk=diary_id)
    except Diary.DoesNotExist:
        return gen(CODES.DIARY_NOT_FOUND)

    try:
        dv = DiaryVote.objects.get(user_id=user.id, diary_id=diary.id)
    except DiaryVote.DoesNotExist:
        return gen(CODES.DIARY_NOT_FOUND)

    dv.delete()
    diary.like_num -= 1
    diary.save()

    diary_author = UserService.get_user_by_user_id(user_id=diary.user_id)
    diary_author.decr_vote_count()

    return {'deleted': True}


@bind('diary/has_voted')
def diary_has_voted(diary_id, user_id):
    """用户是否为该日记本点过赞"""
    query = DiaryVote.objects.filter(diary_id=diary_id, user_id=user_id)
    has_voted = query.exists()
    return {'has_voted': bool(has_voted)}


@bind('diary/user/voted')
def diary_user_voted(user_id, diary_ids):

    if not diary_ids or not user_id:
        return []

    diary_ids = list(DiaryVote.objects.filter(user_id=user_id, diary_id__in=diary_ids).values_list('diary_id', flat=True))
    return diary_ids


@bind('diary/vote_num')
def diary_vote_num(diary_ids):

    if not diary_ids:
        return {}

    diary_objs = diary_list_manager._get_diaries_by_ids(diary_ids, is_online=True)

    return {
        str(diary.id): diary.vote_num
        for diary in diary_objs
    }
