#coding: utf8
import random
import json
from datetime import datetime
from django.conf import settings
from django.db import transaction
from gm_types.gaia import LIPSTICK_ITEM_TYPE, POINTS_TYPE
from rpc.decorators import bind, bind_context
from rpc.tool.error_code import gen, CODES
from rpc.cache import lipstick_cache
import point
from api.tool.datetime_tool import get_timestamp, get_timestamp_epoch
from api.tool.user_tool import get_user_from_context, get_user_extra_by_user_id
from api.tool.variety_vote import get_current_activity_by_time
from api.tool.sms_tool import is_plus_phone_num
from api.tool.log_tool import logging_exception
from api.tool.coupon_tool import check_can_get_channel_gift_ids, _try_get_gift

from api.models import User
from api.models import VarietyTotalInvite, VarietyActivity
from api.models import ChannelGift
from .models import LipstickPrize, LipstickRecord


@bind_context('api/lipstick/index')
def lipstick_index(ctx):
    """转盘页的数据"""
    user = get_user_from_context(ctx)
    result = {}
    activity, end = get_current_activity_by_time(datetime.now())
    lipstick_info = json.loads(lipstick_cache.get('lipstick'))
    update_time = datetime.now()
    start_time = datetime.strptime(lipstick_info.get('update_time'), '%Y-%m-%d %H:%M:%S')
    current_nums = lipstick_info.get('current_nums')
    current_nums -= (update_time - start_time).seconds * lipstick_info.get('speed') // 3600
    result['lipstick_count'] = current_nums if current_nums >= lipstick_info.get('expert_nums') else lipstick_info.get('expert_nums')
    if user:
        try:
            invite_count = VarietyTotalInvite.objects.get(inviter=user, activity=activity).real_total_invite
        except:
            invite_count = 0
        result['invite_count'] = invite_count
        result['remain_draw'] = max(invite_count // 3 - LipstickRecord.objects.filter(user=user, item__activity=activity).count(), 0)
    else:
        result['invite_count'] = 0
        result['remain_draw'] = 0
    result['start_time'] = get_timestamp_epoch(activity.start_time)
    result['end_time'] = get_timestamp_epoch(activity.end_time)
    items = LipstickPrize.objects.filter(activity=activity,
                                         is_online=True).order_by('rank')
    if len(items) != 8:
        return gen(CODES.UNIVERSAL)

    item_info = []
    for item in items:
        data = {
            'id': item.id,
            'pos': item.rank,
            'name': item.name,
            'image': item.image,
            'type': item.type,
        }
        item_info.append(data)
    result['item'] = item_info
    return {
        'result': result,
    }


@bind_context('api/lipstick/get_address')
def lipstick_address(ctx):
    """获取地址信息"""
    user = get_user_from_context(ctx)
    express_info = {}
    if user:
        user_extra = get_user_extra_by_user_id(user.id)
        express_info = {
            'name': user_extra.name or u'',
            'phone': user_extra.phone if user_extra.phone and is_plus_phone_num(user_extra.phone) else u'',
            'region': user_extra.city.name if user_extra.city else u'',
            'address': user_extra.address or u'',
        }
    return {'express_info': express_info}


@bind_context('api/lipstick/set_address')
def lipstick_address(ctx, record_id, express_info):
    """存储地址信息"""
    try:
        obj = LipstickRecord.objects.get(id=record_id)
        obj.express_info = express_info
        obj.save()
    except LipstickRecord.DoesNotExist:
        logging_exception()


@bind_context('api/lipstick/draw')
def lipstick_draw(ctx, unused):
    """生成抽奖记录，处理领奖"""
    user = get_user_from_context(ctx)
    res = {}
    if user is None:
        return gen(CODES.UNIVERSAL)
    with transaction.atomic():
        activity, end = get_current_activity_by_time(datetime.now())
        if end:
            return gen(CODES.UNIVERSAL)
        used = LipstickRecord.objects.filter(user=user,
                                             item__activity=activity).count()
        try:
            total_invite = VarietyTotalInvite.objects.get(inviter=user, activity=activity).real_total_invite
        except:
            total_invite = 0
        if total_invite // 3 - used == int(unused) and unused > 0:
            hit = draw_prize(activity)
            p_obj = LipstickPrize.objects.select_for_update().get(activity=activity, rank=hit, is_online=True)
            p_obj.draw_count += 1
            p_obj.stock -= 1
            p_obj.save()
            obj = LipstickRecord.objects.create(item_id=p_obj.id, user_id=user.id)
            # 领取虚拟奖品
            if p_obj.type == LIPSTICK_ITEM_TYPE.COUPON:
                channel_gift_id = p_obj.channel_gift.id
                try:
                    cg = ChannelGift.objects.select_for_update().get(id=channel_gift_id)
                except:
                    return gen(CODES.UNIVERSAL)
                success, codes = _try_get_gift(cg, user)
                if success == False:
                    return gen(CODES.UNIVERSAL)
            elif p_obj.type == LIPSTICK_ITEM_TYPE.SCORE:
                point.add(user_id=user.id,
                          reason=POINTS_TYPE.LIPSTICK_POINTS,
                          point=p_obj.points)
            res['pos'] = hit
            res['record_id'] = obj.id
        else:
            return gen(CODES.UNIVERSAL)
    return res


@bind_context('api/lipstick/record')
def lipstick_record(ctx):
    """查看获奖记录"""
    user = get_user_from_context(ctx)
    activity, end = get_current_activity_by_time(datetime.now())
    if user:
        records = LipstickRecord.objects.filter(user=user, item__activity=activity).exclude(item__type=LIPSTICK_ITEM_TYPE.THANKS).order_by('-create_time')
    else:
        records = []
    return {
        'records': [record.get_record for record in records]
    }


def random_weight(weight_data, hit):
    total = sum(weight_data.values())
    ra = random.randint(1, max(total, 1))
    curr_sum = 0
    for k, v in weight_data.items():
        curr_sum += v
        if ra <= curr_sum:
            hit = k
            break
    return hit


def draw_prize(activity):
    items = LipstickPrize.objects.filter(activity=activity,
                                         is_online=True).order_by('rank')
    weight_data = {item.rank: item.prob for item in items}
    index = -1
    prob = 0
    for item in items:
        if int(item.stock) <= 0 and item.type != LIPSTICK_ITEM_TYPE.THANKS:
            prob += weight_data[item.rank]
            weight_data[item.rank] = 0
        if index < 0 and item.type == LIPSTICK_ITEM_TYPE.THANKS:
            index = item.rank
    weight_data[index] += prob
    hit = random_weight(weight_data, index)
    return hit


@bind_context('hera/campaign/get_lipstick_config')
def get_lipstick_config(ctx):
    """

    :param ctx:
     origin_nums 总库存
     expert_nums 线
     current_nums 当前剩余
     speed 每小时下降速度
     update_time 当前剩余更新时间
    :return:
    """
    data = {
        "origin_nums": 100000,
        "expert_nums": 0,
        "current_nums": 100000,
        "speed": 0,
        "update_time": datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    }
    config = lipstick_cache.get('lipstick')
    datetime_now = datetime.now()
    if config:
        data = json.loads(config)
        if data.get('update_time'):
            start_time = datetime.strptime(data['update_time'], '%Y-%m-%d %H:%M:%S')
            data['update_time'] = datetime_now.strftime('%Y-%m-%d %H:%M:%S')
        else:
            data['update_time'] = datetime_now.strftime('%Y-%m-%d %H:%M:%S')
            start_time = datetime_now
        update_time = datetime_now
        current_nums = data.get('current_nums')
        current_nums -= (update_time - start_time).seconds * data.get('speed') // 3600
        data['current_nums'] = max(current_nums, data['expert_nums'])
        lipstick_cache.set('lipstick', json.dumps(data))
    return data


@bind_context('hera/campaign/set_lipstick_config')
def set_lipstick_config(ctx, config):
    data = lipstick_cache.get('lipstick')
    if data:
        data = json.loads(data)
        update_time = datetime.now()
        current_nums = data.get('current_nums')
        current_nums -= (update_time - datetime.strptime(config['update_time'], '%Y-%m-%d %H:%M:%S')).seconds * data.get('speed') // 3600
        data['current_nums'] = current_nums
        config['update_time'] = update_time.strftime('%Y-%m-%d %H:%M:%S')
    lipstick_cache.set('lipstick', json.dumps(config))
    return