#! /usr/bin/env python
# -*- coding: utf-8 -*-
# __author__ = "chenwei"
# Date: 2019/1/11

import json
import random
from rpc.decorators import bind_context
from rpc.tool.error_code import gen, CODES
from rpc.context import Session
from gm_types.gaia import NEW_SPRING_ACTIVITY_IMA_LEVEL

from api.tool.wechat_push import get_wechat_access_token
from api.models import UserExtraWechatInfo, User
from api.tool.log_tool import logging_exception, info_logger
from api.tool.user_tool import get_user_from_context
from .models import ActivityConfig, ActivityUserImage
from .utils import lock_user_newspring, unlock_user_newspring
from api.tool.wechat_push import wechat_template_push
from django.conf import settings


LEVEL_LIST = [
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_ONE,
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_TWO,
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_THREE,
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_FOUR,
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_FIVE,
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_SIX,
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_SEVEN,
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_EIGHT,
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_NINE,
]

POSTER = {
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_ONE: [
        'https://pic.igengmei.com/2019/02/02/c3a8f8583d-wxw',
        'https://pic.igengmei.com/2019/02/02/a8192a5004-wxw'
    ],
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_TWO: [
        'https://pic.igengmei.com/2019/02/02/7fbed6358f-wxw',
        'https://pic.igengmei.com/2019/02/02/223ed91ef0-wxw'

    ],
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_THREE: [
        'https://pic.igengmei.com/2019/02/02/40b2e68e52-wxw',
        'https://pic.igengmei.com/2019/02/02/7922af80ad-wxw'

    ],
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_FOUR: [
        'https://pic.igengmei.com/2019/02/02/8ec0c35a13-wxw',
        'https://pic.igengmei.com/2019/02/02/353c51c481-wxw'

    ],
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_FIVE: [
        'https://pic.igengmei.com/2019/02/02/588835af9c-wxw',
        'https://pic.igengmei.com/2019/02/02/ac1b79ecdd-wxw'
    ],
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_SIX: [
        'https://pic.igengmei.com/2019/02/02/a14d950d3e-wxw',
        'https://pic.igengmei.com/2019/02/02/4f060885e2-wxw'
    ],
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_SEVEN: [
        'https://pic.igengmei.com/2019/02/02/98d7a4c0e4-wxw',
        'https://pic.igengmei.com/2019/02/02/a35c78a222-wxw'
    ],
    NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_EIGHT: [
        'https://pic.igengmei.com/2019/02/02/7ff0ddf796-wxw',
        'https://pic.igengmei.com/2019/02/02/c2c4aac8c8-wxw'
    ]
}


def get_defeated_nums(acu, from_upgrade=False):
    """
    count how many people are defeated
    :param from_upgrade:
    :return:
    """
    if not acu:
        return 0

    if from_upgrade:
        # 升级通知进来, 获取上一等级打败多少人
        click_nums = ActivityConfig.objects.get(level=acu.level - 1).threshold
    else:
        click_nums = acu.real_click_nums

    real_kick_nums = acu.real_click_nums

    return real_kick_nums + acu.fake_exceed_nums


def get_user_image(queryset, is_vest=False, level=None, excude=None):
    """
    get user image
    :param queryset:
    :param is_vest:
    :param level:
    :return:
    """
    data, aui_id = [], None

    # if level and not is_vest:
    #     # 取当前等级真实用户图片
    #     activity_image_ids = list(queryset.filter(is_vest=is_vest, level=level).values_list('id', flat=True))
    # elif not level and not is_vest:
    #     # 取其它等级真实用户图片
    #     activity_image_ids = list(queryset.filter(is_vest=is_vest).values_list('id', flat=True))
    # else:
    #     # 取马甲图片
    #     activity_image_ids = list(queryset.filter(is_vest=is_vest).values_list('id', flat=True))
    if level:
        # 随机选取当前等级图片
        activity_image_ids = list(queryset.filter(level=level).values_list('id', flat=True))
    else:
        activity_image_ids = list(queryset.filter(is_vest=is_vest).values_list('id', flat=True))

    if excude:
        aui = ActivityUserImage.objects.filter(
            user_id=excude, is_online=True, is_deleted=False
        ).first()
        aui_id = aui.id if aui else None

    # if less than two
    if len(activity_image_ids) < 10:
        target_ids = activity_image_ids
    else:
        target_ids = random.sample(activity_image_ids, 10)

    for activity_image_id in target_ids:
        if aui_id == activity_image_id:
            continue
        aui = ActivityUserImage.objects.get(id=activity_image_id)
        data.append({
            "image_url": aui.image_url + '-half' if aui.image_url and aui.is_vest else aui.image_url + '-halfwx',
            "acu_id": aui.id
        })
    return data


def get_user_random_image(queryset, level=None, excude=None):
    """
    if new, random choice two image, user pic prior vest pic
    if old, prior choice the level is the same as the user, if curruent pic is not enough, random choice other
    level pic
    :return:
    """
    _extra = []

    if queryset.exists() and level:
        # old user, get image which level is the same as current user level
        data = get_user_image(queryset, level=level, excude=excude)

    else:
        # new user, get image from storage randomly
        data = get_user_image(queryset, excude=excude)

    # if less than ten
    if len(data) < 10:
        _extra = get_user_image(queryset, is_vest=True, excude=excude)

    data.extend(random.sample(_extra, 10 - len(data)))
    data = random.sample(data, 10)
    return data


def get_rank_list_data(aui_ids):
    """
    获取排行榜数据
    :param aui_ids:
    :return:
    """
    result = []
    if not aui_ids:
        return []

    for aui_id in aui_ids:
        activity_user = ActivityUserImage.objects.get(
            id=aui_id,
            is_online=True,
            is_deleted=False,
        )

        try:
            nickname = UserExtraWechatInfo.objects.get(user_id=activity_user.user_id).wechat_nickname
        except UserExtraWechatInfo.DoesNotExist:
            nickname = User.objects.get(id=activity_user.user_id).last_name

        level = activity_user.level
        image_url = activity_user.image_url
        activity_user_id = activity_user.id
        level_desc = ActivityConfig.objects.get(level=level).tag
        kick_nums = get_defeated_nums(activity_user)
        result.append({
            "acu_id": activity_user_id,
            'nickName': nickname,
            'avatar': image_url + '-half' if image_url and activity_user.is_vest else image_url + '-halfwx',
            'user_id': activity_user.user_id,
            'kick_nums': kick_nums,
            'image_url': image_url + '-half' if image_url and activity_user.is_vest else image_url + '-halfwx',
            'level_desc': level_desc
        })

    return sorted(result, key=lambda result: result["kick_nums"], reverse=True)


def get_new_or_old_user_info_by_level(level=None):
    """
    通过level来获取相应等级数据
    :param level:
    :return:
    """
    base = ActivityUserImage.objects.filter(
        is_online=True,
        is_deleted=False,
    )
    if level:
        base = base.filter(level=level)

    cur_real_ids = list(base.filter(is_vest=False).order_by('click_nums').values_list('id', flat=True))
    d_value = 20 - base.filter(is_vest=False).count()
    if d_value > 0:
        # 不足20个, 使用马甲替换
        vest_ids = random.sample(list(base.filter(is_vest=True).values_list('id', flat=True)), d_value)
        cur_real_ids.extend(vest_ids)

    if len(cur_real_ids) > 20:
        cur_real_ids = cur_real_ids[0:20]

    result = get_rank_list_data(cur_real_ids)

    return result


def _send_message(open_id, form_id, tag_desc):
    """
    发送模版消息
    :param open_id:
    :param form_id:
    :param kick_nums:
    :param tag_desc:
    :return:
    """
    if not all([open_id, form_id, tag_desc]):
        return -1
    data = {
        "keyword1": {
            "value": "更美新春颜值pk大赛"
        },
        "keyword2": {
            "value": "恭喜你，你的颜值等级晋级为{tag_desc}".format(tag_desc=tag_desc.encode('utf8'))
        },
        "keyword3": {
            "value": "已为你生成了颜值海报，保存分享炫耀一下吧。"
        },
    }
    code = wechat_template_push(open_id=open_id, template_type='vote', form_id=form_id, data=data)
    return code


def send_message(acu):
    code = -2
    try:
        level = acu.level
        if level != NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_ONE:
            level -= 1
        tag_desc = ActivityConfig.objects.get(level=level).tag
        uw = UserExtraWechatInfo.objects.get(user_id=acu.user_id)
        code = _send_message(open_id=uw.openid, form_id=acu.form_id, tag_desc=tag_desc)
    except Exception:
        logging_exception()
    return code


def get_target_data(aui_id):
    if not aui_id:
        return {}

    activity_user = ActivityUserImage.objects.get(
        id=aui_id,
        is_online=True,
        is_deleted=False,
    )

    try:
        nickname = UserExtraWechatInfo.objects.get(user_id=activity_user.user_id).wechat_nickname
    except UserExtraWechatInfo.DoesNotExist:
        nickname = User.objects.get(id=activity_user.user_id).last_name

    level = activity_user.level
    image_url = activity_user.image_url
    activity_user_id = activity_user.id
    level_desc = ActivityConfig.objects.get(level=level).tag
    kick_nums = get_defeated_nums(activity_user)
    ret_data = {
        "acu_id": activity_user_id,
        'nickName': nickname,
        'avatar': image_url + '-half' if image_url and activity_user.is_vest else image_url + '-halfwx',
        'user_id': activity_user.user_id,
        'kick_nums': kick_nums,
        'image_url': image_url + '-half' if image_url and activity_user.is_vest else image_url + '-halfwx',
        'level_desc': level_desc
    }
    return ret_data


@bind_context('api/new_spring/get_random_image')
def get_random_images_for_wechat_small(ctx, share_user_id=None, from_share=False):
    """
    get random image
    :param ctx:
    :param share_user_id:
    :param from_share:
    :return:
    """

    user = get_user_from_context(ctx)
    level, share_user_data = None, {}
    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    # hack 获取历史用户的openid
    UserExtraWechatInfo.objects.get_or_create(
        user_id=user.id,
        defaults={
            "openid": ctx.session.get_wechat_openid(wechat_appid=settings.WECHAT_SMALL_APPID),
            "wechat_nickname": User.objects.get(id=user.id).last_name  # 历史用户使用更美last_name 代替用户昵称
        }
    )

    base_filter = ActivityUserImage.objects.filter(is_online=True, is_deleted=False)
    has_play = base_filter.filter(user_id=user.id, is_vest=False)

    if has_play.exists():
        level = has_play.first().level

    data = get_user_random_image(base_filter, level=level, excude=share_user_id)

    if user.id == share_user_id:
        # 分享给自己, 不会产生自己的图片
        return {'random_images': data}

    if from_share and share_user_id:
        aui = ActivityUserImage.objects.filter(
            user_id=share_user_id, is_online=True, is_deleted=False
        ).first()
        if aui:
            share_user_data = {
                "image_url": aui.image_url + '-halfwx' if aui.image_url else '',
                "acu_id": aui.id
            }

            data.pop()
            data.insert(0, share_user_data)

    return {'random_images': data}


@bind_context('api/new_spring/get_rank_list')
def get_rank_list_for_wechat_small(ctx):
    """
    get rank data
    :param ctx:
    :return:
    """
    user = get_user_from_context(ctx)
    _ids_data = []
    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    aui = ActivityUserImage.objects.filter(
        user_id=user.id,
        is_online=True,
        is_deleted=False,
        is_vest=False
    ).first()

    # 如果存在aui，表示老用户； 否则为新用户
    level = aui.level if aui else None
    result = get_new_or_old_user_info_by_level(level=level)
    _id = aui.id if aui else None

    apppend_data = get_target_data(_id)
    append_id = apppend_data['acu_id'] if apppend_data else ''

    for _data in result:
        _ids_data.append(_data['acu_id'])

    if append_id and append_id not in _ids_data:
        result = result[0:19]
        if apppend_data:
            result.append(apppend_data)

    result = sorted(result, key=lambda x: x["kick_nums"], reverse=True)

    return {"rank_list": result}


@bind_context('api/new_spring/thumb_up')
def thumb_up(ctx, acu_id):
    """
    thumb up for user image
    :param ctx:
    :param acu_id:
    :return:
    """
    user = get_user_from_context(ctx)
    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    lock_user_newspring(acu_id)
    try:
        acu = ActivityUserImage.objects.get(id=acu_id)
        cur_level_threshold = ActivityConfig.objects.get(level=acu.level).threshold
        # if vest, don't add click nums
        if acu.is_vest:
            return
        if not acu.is_click:
            acu.is_click = True

        cur_click_nums = acu.click_nums
        if cur_click_nums + 1 >= cur_level_threshold:
            # 发送消息通知
            code = send_message(acu)
            if code == 0:
                acu.is_push = True
            if acu.level == NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_ONE:
                acu.click_nums += 1
            else:
                acu.level -= 1
                acu.click_nums = 0
        else:
            acu.click_nums += 1
        acu.real_click_nums += 1
        acu.save()

    except ActivityUserImage.DoesNotExist:
        unlock_user_newspring(acu_id)
        logging_exception()

    unlock_user_newspring(acu_id)


@bind_context('api/new_spring/get_user_info')
def get_user_info_for_wechat_small(ctx, from_upgrade):

    """
    get user base info
    :param ctx:
    :return:
    """
    user = get_user_from_context(ctx)
    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    if ActivityUserImage.objects.filter(user_id=user.id, is_deleted=False, is_vest=False, is_online=False).exists():
        # 用户图片下线
        return {
            'is_online': 1,
            'next_level_desc': '',
            'current_level_click_nums': 0,
            'total_threshold': 0,
            'image_url': '',
            'user_id': user.id
        }

    acu = ActivityUserImage.objects.filter(
        user_id=user.id,
        is_online=True,
        is_deleted=False,
        is_vest=False
    ).first()

    try:
        nickname = UserExtraWechatInfo.objects.get(user_id=user.id).wechat_nickname
    except UserExtraWechatInfo.DoesNotExist:
        nickname = User.objects.get(id=user.id).last_name

    if not acu:
        return {
            'has_play': bool(acu),
            'nickName': nickname,
            'avatarUrl': '',
            'user_id': user.id
        }

    image_url = acu.image_url
    if from_upgrade:
        kick_nums = get_defeated_nums(acu, from_upgrade=from_upgrade)
    else:
        kick_nums = get_defeated_nums(acu)
    is_share = True if acu.is_share else False
    current_level_click_nums = acu.click_nums
    poster = random.choice(POSTER.get(acu.level))
    current_level_desc = NEW_SPRING_ACTIVITY_IMA_LEVEL.getDesc(acu.level)
    current_level_threshold = ActivityConfig.objects.get(level=acu.level).threshold

    if acu.level == NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_ONE:
        next_level_desc = NEW_SPRING_ACTIVITY_IMA_LEVEL.getDesc(acu.level)
    else:
        next_level_desc = NEW_SPRING_ACTIVITY_IMA_LEVEL.getDesc(acu.level - 1)

    access_token = get_wechat_access_token()

    return {
        'has_play': bool(acu),
        'current_level_desc': current_level_desc,
        'next_level_desc': next_level_desc,
        'total_threshold': current_level_threshold,
        'current_level_click_nums': current_level_click_nums,
        'level_poster': poster,
        'kick_nums': kick_nums,
        'image_url': image_url + '-halfwx' if image_url else '',
        'nickName': nickname,
        'avatarUrl': image_url + '-halfwx' if image_url else '',
        'is_share': is_share,
        'user_id': user.id,
        'access_token': access_token
    }


@bind_context('api/new_spring/upload_user_image')
def new_spring_uplaod_user_image(ctx, image_url, form_id):
    """
    save image upload by user
    :param ctx:
    :param image_url:
    :return:
    """
    user = get_user_from_context(ctx)
    if image_url.endswith('-half'):
        image_url = image_url.split('-')[0]

    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    level = random.randint(
        NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_SIX,
        NEW_SPRING_ACTIVITY_IMA_LEVEL.ACTIVITY_LEVEL_EIGHT
    )

    # delete old image
    ActivityUserImage.objects.filter(
        user_id=user.id,
    ).update(is_deleted=True)

    aui = ActivityUserImage()
    aui.image_url = image_url
    aui.user_id = user.id
    aui.level = level
    aui.form_id = form_id
    aui.save()

    return {
        "acu_id": aui.id,
        "level": aui.level,
        "user_id": aui.user_id,
    }


@bind_context('api/new_spring/share')
def new_spring_share(ctx, is_share=False):
    user = get_user_from_context(ctx)

    if not user:
        return gen(CODES.LOGIN_REQUIRED)

    ActivityUserImage.objects.filter(
        user_id=user.id,
        is_online=True,
        is_deleted=False,
        is_vest=False
    ).update(is_share=is_share)

    return "success"