package com.tzld.piaoquan.ad.engine.service.predict.helper;

import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
import com.tzld.piaoquan.ad.engine.service.predict.constant.RuleRedisKeyConst;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class RuleParamHelper {

    @Autowired
    private AlgorithmRedisHelper redisHelper;

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
    //避免空指异常及重复创建过多Obj
    Map<String,Object> defaultMap=new HashMap<>();
    final Double zeroDefaultValue=new Double(0);
    public Double getGroupShareRate( Map<String, Object> abTestParam,Date nowDate,String midGroup){
        String nowDt = dateFormat.format(nowDate);
        String shareUserDataKey = (String) ((Map<String,Object>)
                ((Map<String,Object>)abTestParam.getOrDefault("share",defaultMap))
                        .getOrDefault("user",defaultMap)).get("data");
        String shareUserRuleKey = (String) ((Map<String,Object>)
                ((Map<String,Object>)abTestParam.getOrDefault("share",defaultMap))
                        .getOrDefault("user",defaultMap)).get("rule");
        String groupShareRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_GROUP + shareUserDataKey + ":" + shareUserRuleKey + ":" + nowDt;

        if (StringUtils.isEmpty(shareUserDataKey)||StringUtils.isEmpty(shareUserRuleKey)|| !redisHelper.containsKey(groupShareRateKey)) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(nowDate);
            cal.add(Calendar.DATE, -1);
            Date yesterday = cal.getTime();
            String redisDt = dateFormat.format(yesterday);
            groupShareRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_GROUP + shareUserDataKey + ":" + shareUserRuleKey + ":" + redisDt;
        }

        Double groupShareRate = redisHelper.zScore(groupShareRateKey, midGroup);
        if(Objects.isNull(groupShareRate)){
            groupShareRate=zeroDefaultValue;
        }
        return groupShareRate;
    }
    public Double getGroupShareRateForBasic( Map<String, Object> abTestParam,Date nowDate,String midGroup){
        String nowDt = dateFormat.format(nowDate);
        String shareUserDataKey = (String) ((Map<String,Object>) abTestParam
                        .getOrDefault("user",defaultMap)).get("data");
        String shareUserRuleKey = (String)
                ((Map<String,Object>)abTestParam.getOrDefault("user",defaultMap)).get("rule");
        String groupShareRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_GROUP + shareUserDataKey + ":" + shareUserRuleKey + ":" + nowDt;

        if (StringUtils.isEmpty(shareUserDataKey)||StringUtils.isEmpty(shareUserRuleKey)|| !redisHelper.containsKey(groupShareRateKey)) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(nowDate);
            cal.add(Calendar.DATE, -1);
            Date yesterday = cal.getTime();
            String redisDt = dateFormat.format(yesterday);
            groupShareRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_GROUP + shareUserDataKey + ":" + shareUserRuleKey + ":" + redisDt;
        }

        Double groupShareRate = redisHelper.zScore(groupShareRateKey, midGroup);
        if(Objects.isNull(groupShareRate)){
            groupShareRate=zeroDefaultValue;
        }
        return groupShareRate;
    }

    public Double getVideoShareRateForBasic( Map<String, Object> abTestParam,Date nowDate,Long videoId){
        String nowDt = dateFormat.format(nowDate);
        String shareVideoDataKey = (String)
                ((Map<String,Object>)abTestParam
                        .getOrDefault("video",defaultMap)).get("data");
        String videoShareRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_VIDEO + shareVideoDataKey + ":" + nowDt;

        if (StringUtils.isEmpty(shareVideoDataKey)||!redisHelper.containsKey(videoShareRateKey)) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(nowDate);
            cal.add(Calendar.DATE, -1);
            Date yesterday = cal.getTime();
            String redisDt = dateFormat.format(yesterday);
            videoShareRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_VIDEO + shareVideoDataKey + ":" + redisDt;
        }

        Double videoShareRate = redisHelper.zScore(videoShareRateKey, videoId.toString());
        if (videoShareRate == null) {
            videoShareRate = redisHelper.zScore(videoShareRateKey, -1+"");
        }
        if(Objects.isNull(videoShareRate)){
            videoShareRate=zeroDefaultValue;
        }
        return videoShareRate;
    }


    public Double getVideoShareRate( Map<String, Object> abTestParam,Date nowDate,Long videoId){
        String nowDt = dateFormat.format(nowDate);
        String shareVideoDataKey = (String) ((Map<String,Object>)
                ((Map<String,Object>)abTestParam.getOrDefault("share",defaultMap))
                        .getOrDefault("video",defaultMap)).get("data");
        String videoShareRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_VIDEO + shareVideoDataKey + ":" + nowDt;

        if (StringUtils.isEmpty(shareVideoDataKey)||!redisHelper.containsKey(videoShareRateKey)) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(nowDate);
            cal.add(Calendar.DATE, -1);
            Date yesterday = cal.getTime();
            String redisDt = dateFormat.format(yesterday);
            videoShareRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_VIDEO + shareVideoDataKey + ":" + redisDt;
        }

        Double videoShareRate = redisHelper.zScore(videoShareRateKey, videoId.toString());
        if (videoShareRate == null) {
                videoShareRate = redisHelper.zScore(videoShareRateKey, -1+"");
        }
        if(Objects.isNull(videoShareRate)){
            videoShareRate=zeroDefaultValue;
        }
        return videoShareRate;
    }

    public Double getGroupOutRate(Map<String, Object> abTestParam,Date nowDate,String midGroup){
        String nowDt = dateFormat.format(nowDate);
        String outUserDataKey = (String) ((Map<String,Object>)
                ((Map<String,Object>)abTestParam.getOrDefault("out",defaultMap))
                        .getOrDefault("user",defaultMap)).get("data");
        String outUserRuleKey = (String) ((Map<String,Object>)
                ((Map<String,Object>)abTestParam.getOrDefault("out",defaultMap))
                        .getOrDefault("user",defaultMap)).get("rule");
        String groupOutRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_GROUP + outUserDataKey + ":" + outUserRuleKey + ":" + nowDt;

        if (StringUtils.isEmpty(outUserDataKey)||StringUtils.isEmpty(outUserRuleKey)
                ||!redisHelper.containsKey(groupOutRateKey)) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(nowDate);
            cal.add(Calendar.DATE, -1);
            Date yesterday = cal.getTime();
            String redisDt = dateFormat.format(yesterday);
            groupOutRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_GROUP + outUserDataKey + ":" + outUserRuleKey + ":" + redisDt;
        }
        Double groupOutRate=redisHelper.zScore(groupOutRateKey, midGroup);
        if(Objects.isNull(groupOutRate)){
            groupOutRate=zeroDefaultValue;
        }
        return groupOutRate;
    }

    public Double getVideoOutRate(Map<String, Object> abTestParam,Date nowDate,Long videoId){
        String nowDt = dateFormat.format(nowDate);
        String outVideoDataKey = (String)((Map<String,Object>)
                ((Map<String,Object>)abTestParam.getOrDefault("out",defaultMap)).getOrDefault("video",defaultMap)).get("data");
        String videoOutRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_VIDEO + outVideoDataKey + ":" + nowDt;

        if (StringUtils.isEmpty(outVideoDataKey)||!redisHelper.containsKey(videoOutRateKey)) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(nowDate);
            cal.add(Calendar.DATE, -1);
            Date yesterday = cal.getTime();
            String redisDt = dateFormat.format(yesterday);
            videoOutRateKey = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_VIDEO + outVideoDataKey + ":" + redisDt;
        }

        Double videoOutRate = redisHelper.zScore(videoOutRateKey, videoId.toString());
        if (Objects.isNull(videoOutRate) ) {
                videoOutRate = redisHelper.zScore(videoOutRateKey, -1+"");
        }
        if(Objects.isNull(videoOutRate)){
            videoOutRate=zeroDefaultValue;
        }
        return videoOutRate;
    }

    public double getThreshold(
            String abtestId,
            String abtestConfigTag,
            String abTestCode,
            String midGroup,
            Long careModelStatus,
            @NotNull Map<String, Object> abtestParam
    ) {
        // Check if it is a care model experiment
//        Map<String, Object> careModelStatusParam = (Map<String, Object>) abtestParam.get("care_model_status_param");
        Integer careModelStatusParam = (Integer) abtestParam.get("care_model_status_param");
        List<String> careModelAbMidGroup = (List<String>) abtestParam.get("care_model_ab_mid_group");

        String thresholdKeyNamePrefix;
        if (careModelStatusParam == null) {
            // No care model experiment
            thresholdKeyNamePrefix = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_THRESHOLD;
        } else {
            // Care model experiment
            if (careModelStatus == null || careModelAbMidGroup.isEmpty() || "null".equals(careModelStatus)) {
                // Missing parameters, use default
                thresholdKeyNamePrefix = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_THRESHOLD;
            } else if (careModelStatusParam.equals(careModelStatus.intValue()) && careModelAbMidGroup.contains(midGroup)) {
                // Experiment matches, get the corresponding threshold
                thresholdKeyNamePrefix = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_THRESHOLD_CARE_MODEL;
            } else {
                thresholdKeyNamePrefix = RuleRedisKeyConst.KEY_NAME_PREFIX_AD_THRESHOLD;
            }
        }

       String thresholdKeyName = thresholdKeyNamePrefix + abtestId + ":" + abtestConfigTag + ":" + abTestCode + ":" + midGroup;
        // String thresholdKeyName = thresholdKeyNamePrefix + "ad-engine" + ":" + abtestConfigTag + ":" + abTestCode + ":" + midGroup;

        String thresholdStr = redisHelper.get(thresholdKeyName);
        double threshold = (thresholdStr != null) ? Double.parseDouble(thresholdStr) : 0.0;

        return threshold;
    }
}
