package com.tzld.piaoquan.ad.engine.commons.score.model;

import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdActionFeature;
import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
import org.apache.commons.math3.distribution.BetaDistribution;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

public class VideoAdThompsonModel extends Model{
    private static final Logger LOGGER = LoggerFactory.getLogger(VideoAdThompsonModel.class);

    private Map<String, AdActionFeature> featureCache = new HashMap<>();
    private Map<Long, AdActionFeature> adActionFeatureMap = new HashMap<>();
    private Map<Long, AdActionFeature> videoAdActionFeatureMap = new HashMap<>();
    private  double alpha_click = 60;
    private double alpha_conv = 60d;
    private double beta_click = 1000d;
    private double beta_conversion = 1000d;

    @Override
    public int getModelSize() {
        return featureCache.size();
    }

    @Override
    public boolean loadFromStream(InputStreamReader in) throws Exception {
        Map<String, AdActionFeature> initModel = new HashMap<>();
        Map<Long, AdActionFeature> tempAdActionFeatureMap =new HashMap<>();
        Map<Long, AdActionFeature> tempVideoActionFeatureMap =new HashMap<>();
        double sumClick=0d;
        double sumView=0d;
        double sumConversion=0d;
        try (BufferedReader reader = new BufferedReader(in)) {
            String line = null;
            int size = 0;
            while ((line = reader.readLine()) != null) {
                String[] items = line.split(",");
                if (items.length < 5) {
                    continue;
                }
//    headvideoid   STRING
//    ,advertiserid STRING
//    ,adid         STRING
//    ,creativeid   STRING
//    ,conversion   STRING
//    ,view         STRING
//    ,click        STRING
//    ,cpa          STRING
                Long videoId=new BigDecimal(items[0].trim()).longValue();
                Long creativeId=new BigDecimal(items[3].trim()).longValue();
                double conversion=new BigDecimal(items[4].trim()).doubleValue();
                double view= new BigDecimal(items[5].trim()).doubleValue();
                double click=new BigDecimal(items[6].trim()).doubleValue();

                this.putAdFeature(tempAdActionFeatureMap,creativeId,view,click,conversion);
                this.putVideoAdFeature(tempVideoActionFeatureMap,videoId,view,click,conversion);
                this.putFeature(
                        initModel,
                        videoId,
                        creativeId,
                        view,
                        click,
                        conversion
                );
                size++;
                sumClick+=click;
                sumView+=view;
                sumConversion+=conversion;
            }
            double k=(sumConversion+sumView)/1000d;
            this.alpha_conv=sumConversion/k;
            this.featureCache = initModel;
            this.adActionFeatureMap=tempAdActionFeatureMap;
            this.videoAdActionFeatureMap=tempVideoActionFeatureMap;
            LOGGER.info("[VIDEO_CREATIVE THOMPSON MODEL LOAD] mode load over, size {}", size);
        } catch (
                Exception e) {
            LOGGER.info("[VIDEO_CREATIVE THOMPSON  MODEL LOAD] mode load error ", e);
        } finally {
            in.close();
        }

        return true;
    }
    private void putVideoAdFeature(Map<Long, AdActionFeature> cache, Long videoId , Double view, Double click, Double conversion) {
        AdActionFeature adActionFeature=cache.getOrDefault(videoId,new AdActionFeature());
        adActionFeature.setAdClick(adActionFeature.getAdClick()+click);
        adActionFeature.setAdConversion(adActionFeature.getAdConversion()+conversion);
        adActionFeature.setAdView(adActionFeature.getAdView()+view);
        cache.put(videoId,adActionFeature);
    }

    private void putAdFeature(Map<Long, AdActionFeature> cache, Long adId , Double view, Double click, Double conversion) {
        AdActionFeature adActionFeature=cache.getOrDefault(adId,new AdActionFeature());
        adActionFeature.setAdClick(adActionFeature.getAdClick()+click);
        adActionFeature.setAdConversion(adActionFeature.getAdConversion()+conversion);
        adActionFeature.setAdView(adActionFeature.getAdView()+view);
        cache.put(adId,adActionFeature);
    }

    private void putFeature(Map<String, AdActionFeature> modelCache, Long videoId, Long creativeId, Double view, Double click, Double conversion) {
        AdActionFeature adActionFeature =  new AdActionFeature();
        adActionFeature.setAdView(view);
        adActionFeature.setAdClick(click);
        adActionFeature.setAdConversion(conversion);
        modelCache.put(videoId+"_"+creativeId, adActionFeature);
    }

    public double scoreByView1000(AdRankItem item) {
        AdActionFeature adActionFeature = this.featureCache.getOrDefault(item.getVideoId()+"_"+item.getAdId(),  new AdActionFeature());
        double alpha_score=0d;
        double beta_score=0d;
        if(adActionFeature.getAdView()<1000){
            adActionFeature=this.adActionFeatureMap.getOrDefault(item.getAdId(), new AdActionFeature());
            alpha_score =  adActionFeature.getAdConversion() + this.alpha_conv;
            beta_score = this.beta_conversion + adActionFeature.getAdView() - adActionFeature.getAdConversion();
        }else {
            AdActionFeature videoAdFeature=this.videoAdActionFeatureMap.getOrDefault(item.getVideoId(),new AdActionFeature());
            double k=(videoAdFeature.getAdConversion()+videoAdFeature.getAdView())/1000d;
            double alpha=(videoAdFeature.getAdConversion())/k;
            alpha_score =adActionFeature.getAdConversion() + alpha;
            beta_score = 1000d +  adActionFeature.getAdView() -  adActionFeature.getAdConversion();
        }
        return this.betaSampler(alpha_score, beta_score);
    }

    public double scoreByView500(AdRankItem item) {
        AdActionFeature adActionFeature = this.featureCache.getOrDefault(item.getVideoId()+"_"+item.getAdId(),  new AdActionFeature());
        double alpha_score=0d;
        double beta_score=0d;
        if(adActionFeature.getAdView()<500){
            adActionFeature=this.adActionFeatureMap.getOrDefault(item.getAdId(), new AdActionFeature());
            alpha_score =  adActionFeature.getAdConversion() + this.alpha_conv;
            beta_score = this.beta_conversion + adActionFeature.getAdView() - adActionFeature.getAdConversion();
        }else {
            AdActionFeature videoAdFeature=this.videoAdActionFeatureMap.getOrDefault(item.getVideoId(),new AdActionFeature());
            double k=(videoAdFeature.getAdConversion()+videoAdFeature.getAdView())/1000d;
            double alpha=(videoAdFeature.getAdConversion())/k;
            alpha_score =adActionFeature.getAdConversion() + alpha;
            beta_score = 1000d +  adActionFeature.getAdView() -  adActionFeature.getAdConversion();
        }
        return this.betaSampler(alpha_score, beta_score);
    }

    public double score(AdRankItem item) {
        AdActionFeature adActionFeature = this.featureCache.getOrDefault(item.getVideoId()+"_"+item.getAdId(),  new AdActionFeature());
        double alpha_score=0d;
        double beta_score=0d;
        if(adActionFeature.getAdView()<200){
            adActionFeature=this.adActionFeatureMap.getOrDefault(item.getAdId(), new AdActionFeature());
            alpha_score =  adActionFeature.getAdConversion() + this.alpha_conv;
            beta_score = this.beta_conversion + adActionFeature.getAdView() - adActionFeature.getAdConversion();
        }else {
            AdActionFeature videoAdFeature=this.videoAdActionFeatureMap.getOrDefault(item.getVideoId(),new AdActionFeature());
            double k=(videoAdFeature.getAdConversion()+videoAdFeature.getAdView())/1000d;
            double alpha=(videoAdFeature.getAdConversion())/k;
            alpha_score =adActionFeature.getAdConversion() + alpha;
            beta_score = 1000d +  adActionFeature.getAdView() -  adActionFeature.getAdConversion();
        }
        return this.betaSampler(alpha_score, beta_score);
    }

    public double betaSampler(double alpha, double beta) {
        BetaDistribution betaSample = new BetaDistribution(alpha, beta);
        return betaSample.sample();
    }
}
