import traceback
import datetime
from utils import RedisHelper
from config import set_config
from log import Log
log_ = Log()
config_ = set_config()
redis_helper = RedisHelper()


def get_params(ab_exp_info, ab_test_code):
    """
    根据实验分组给定对应的参数
    :param ab_exp_info: AB实验组参数
    :param ab_test_code: 用户对应的ab组
    :return:
    """
    abtest_id, abtest_config_tag = None, None
    ad_abtest_id_list = [key.split('-')[0] for key in config_.AD_ABTEST_CONFIG]
    # 获取广告实验配置
    config_value_dict = {}
    if ab_exp_info:
        ab_exp_list = ab_exp_info.get('ab_test002', None)
        if ab_exp_list:
            for ab_item in ab_exp_list:
                ab_exp_code = ab_item.get('abExpCode', None)
                if not ab_exp_code:
                    continue
                if ab_exp_code in ad_abtest_id_list:
                    config_value = ab_item.get('configValue', None)
                    if config_value:
                        config_value_dict[str(ab_exp_code)] = eval(str(config_value))

    if len(config_value_dict) > 0:
        for ab_exp_code, config_value in config_value_dict.items():
            for tag, value in config_value.items():
                if ab_test_code in value:
                    abtest_id = ab_exp_code
                    abtest_config_tag = tag
                    break

    return abtest_id, abtest_config_tag


def get_threshold(abtest_id, abtest_config_tag, ab_test_code, mid_group, care_model_status, abtest_param):
    """获取对应的阈值"""
    # 判断是否是关怀模式实验
    care_model_status_param = abtest_param.get('care_model_status_param', None)
    care_model_ab_mid_group = abtest_param.get('care_model_ab_mid_group', None)
    if care_model_status_param is None:
        # 无关怀模式实验
        threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD
    else:
        # 关怀模式实验
        if care_model_status is None or care_model_ab_mid_group is None or care_model_status == 'null':
            # 参数缺失,走默认
            threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD
        elif int(care_model_status) == int(care_model_status_param) and mid_group == care_model_ab_mid_group:
            # 实验匹配,获取对应的阈值
            threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD_CARE_MODEL
        else:
            threshold_key_name_prefix = config_.KEY_NAME_PREFIX_AD_THRESHOLD

    threshold_key_name = f"{threshold_key_name_prefix}{abtest_id}:{abtest_config_tag}:{ab_test_code}:{mid_group}"
    threshold = redis_helper.get_data_from_redis(key_name=threshold_key_name)
    if threshold is None:
        threshold = 0
    else:
        threshold = float(threshold)
    return threshold


def ad_recommend_predict(app_type, mid, video_id, ab_exp_info, ab_test_code, care_model_status):
    """
    广告推荐预测
    :param app_type: app_type
    :param mid: mid
    :param video_id: video_id
    :param ab_exp_info: AB实验组参数
    :param ab_test_code: 用户对应的ab组
    :param care_model_status: 用户关怀模式状态 1-未开启,2-开启
    :return: ad_predict, type-int, 1-不发放广告,2-发放广告
    """
    try:
        now_date = datetime.datetime.today()
        now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
        # 获取实验参数
        abtest_id, abtest_config_tag = get_params(ab_exp_info=ab_exp_info, ab_test_code=ab_test_code)
        if abtest_id is None or abtest_config_tag is None:
            return None
        abtest_param = config_.AD_ABTEST_CONFIG.get(f'{abtest_id}-{abtest_config_tag}')
        if abtest_param is None:
            return None

        user_data_key = abtest_param['user'].get('data')
        user_rule_key = abtest_param['user'].get('rule')
        video_data_key = abtest_param['video'].get('data')
        group_class_key = abtest_param.get('group_class_key')
        no_ad_mid_group_list = abtest_param.get('no_ad_mid_group_list', [])

        # 判断mid所属分组
        mid_group_key_name = f"{config_.KEY_NAME_PREFIX_MID_GROUP}{group_class_key}:{mid}"
        mid_group = redis_helper.get_data_from_redis(key_name=mid_group_key_name)
        if mid_group is None:
            mid_group = 'mean_group'

        # 判断用户是否在免广告用户组列表中
        if mid_group in no_ad_mid_group_list:
            # 在免广告用户组列表中,则不出广告
            ad_predict = 1
            result = {
                'mid_group': mid_group,
                'ad_predict': ad_predict
            }
        else:
            # 获取用户组分享率
            group_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_GROUP}{user_data_key}:{user_rule_key}:{now_dt}"
            if not redis_helper.key_exists(group_share_rate_key):
                redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
                group_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_GROUP}{user_data_key}:{user_rule_key}:{redis_dt}"
            group_share_rate = redis_helper.get_score_with_value(key_name=group_share_rate_key, value=mid_group)
            # 获取视频分享率
            video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{video_data_key}:{now_dt}"
            if not redis_helper.key_exists(video_share_rate_key):
                redis_dt = datetime.datetime.strftime(now_date - datetime.timedelta(days=1), '%Y%m%d')
                video_share_rate_key = f"{config_.KEY_NAME_PREFIX_AD_VIDEO}{video_data_key}:{redis_dt}"
            video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=int(video_id))
            if video_share_rate is None:
                video_share_rate = redis_helper.get_score_with_value(key_name=video_share_rate_key, value=-1)

            # 计算 mid-video 分享率
            if group_share_rate is None or video_share_rate is None:
                return None
            mid_video_share_rate = float(group_share_rate) * float(video_share_rate)

            # 获取对应的阈值
            threshold = get_threshold(
                abtest_id=abtest_id,
                abtest_config_tag=abtest_config_tag,
                ab_test_code=ab_test_code,
                mid_group=mid_group,
                care_model_status=care_model_status,
                abtest_param=abtest_param
            )
            # 阈值判断
            if mid_video_share_rate > threshold:
                # 大于阈值,出广告
                ad_predict = 2
            else:
                # 否则,不出广告
                ad_predict = 1
            result = {
                'mid_group': mid_group,
                'group_share_rate': group_share_rate,
                'video_share_rate': video_share_rate,
                'mid_video_share_rate': mid_video_share_rate,
                'threshold': threshold,
                'ad_predict': ad_predict}

        return result

    except Exception as e:
        log_.error(traceback.format_exc())
        return None