import json
import random
import time

import gevent
from db_helper import RedisHelper
from config import set_config
from log import Log
from gevent import monkey, pool
monkey.patch_all()

config_ = set_config()
log_ = Log()
redis_helper = RedisHelper()


def thompson_process(creative_id):
    # 获取creative_id对应的Thompson参数
    st_time1 = time.time()
    thompson_param = redis_helper.get_data_from_redis(key_name=f"{config_.THOMPSON_PARAM_KEY_PREFIX}{creative_id}")
    get_redis_time = int(time.time() - st_time1) * 1000
    thompson_time = {}
    if thompson_param is None or thompson_param == '':
        # 参数不存在,随机生成[0, 1)之间的浮点数
        st_time2 = time.time()
        score = random.random()
        thompson_time['random'] = int(time.time() - st_time2) * 1000
        random_flag = 'random'
    else:
        # 参数存在
        st_time3 = time.time()
        param_alpha, param_beta = json.loads(thompson_param.strip())
        param_alpha, param_beta = int(param_alpha), int(param_beta)
        if param_alpha + param_beta >= 100:
            # ad_idea_id 曝光数 >= 100,生成参数为(param_alpha+1, param_beta+1)的beta分布随机数
            score = random.betavariate(alpha=param_alpha+1, beta=param_beta+1)
            random_flag = 'beta'
        else:
            # ad_idea_id 曝光数 < 100,随机生成[0, 1)之间的浮点数
            score = random.random()
            random_flag = 'random'
        thompson_time['beta'] = int(time.time() - st_time3) * 1000
    thompson_res = [creative_id, score, thompson_param, random_flag]
    log_.info(f"get_redis_time: {get_redis_time}, thompson_time: {thompson_time}")
    return thompson_res


def get_creative_id_with_thompson(mid, creative_id_list):
    """利用Thompson采样获取此次要展示的广告创意ID"""
    # 限制协程最大并发数:20
    st_time6 = time.time()
    gevent_pool = pool.Pool(100)
    gevent_pool_time = int(time.time() - st_time6) * 1000
    st_time5 = time.time()
    tasks = [gevent_pool.spawn(thompson_process, creative_id) for creative_id in creative_id_list]
    gevent.joinall(tasks)
    thompson_res_list = [t.get() for t in tasks]
    get_random_time = int(time.time() - st_time5) * 1000
    # 按照score排序
    st_time4 = time.time()
    thompson_res_rank = sorted(thompson_res_list, key=lambda x: x[1], reverse=True)
    sort_time = int(time.time() - st_time4) * 1000
    rank_res = {
        'mid': mid,
        'creative_id': thompson_res_rank[0][0],
        'score': thompson_res_rank[0][1],
        'thompson_param': thompson_res_rank[0][2],
        'random_flag': thompson_res_rank[0][3],
        'thompson_res_rank': thompson_res_rank
    }
    log_.info(f"gevent_pool_time: {gevent_pool_time}, get_random_time: {get_random_time}, sort_time: {sort_time}")
    return rank_res