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


import com.typesafe.config.Config;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


@Slf4j
public final class ScorerUtils {
    private static Logger LOGGER = LoggerFactory.getLogger(ScorerUtils.class);

    private static Map<String, ScorerPipeline> scorerPipelineCache = new ConcurrentHashMap<>();

    public static String BASE_CONF = "feeds_score_config_baseline.conf";

    public static String THOMPSON_CONF = "feeds_score_config_thompson.conf";

    public static String LR_ROV_SCORE_20240626 = "ad_score_config_20240626.conf";

    public static String XGBOOST_SCORE_CONF = "ad_score_config_xgboost.conf";
    public static String XGBOOST_SCORE_CONF_683 = "ad_score_config_xgboost_683.conf";
    public static String XGBOOST_SCORE_CONF_20240909 = "ad_score_config_xgboost_20240909.conf";
    public static String XGBOOST_SCORE_CONF_20241105 = "ad_score_config_xgboost_20241105.conf";
    public static String PAI_SCORE_CONF_20250214 = "ad_score_config_pai_20250214.conf";
    public static String PAI_SCORE_CONF_20250804 = "ad_score_config_pai_20250804.conf";
    public static String PAI_SCORE_CONF_20260804 = "ad_score_config_pai_20260804.conf";



    public static void warmUp() {
        log.info("scorer warm up ");

        ScorerUtils.init(LR_ROV_SCORE_20240626);

        ScorerUtils.init(XGBOOST_SCORE_CONF_683);
        ScorerUtils.init(XGBOOST_SCORE_CONF);
        ScorerUtils.init(XGBOOST_SCORE_CONF_20240909);
        ScorerUtils.init(XGBOOST_SCORE_CONF_20241105);
        ScorerUtils.init(PAI_SCORE_CONF_20250214);
        ScorerUtils.init(PAI_SCORE_CONF_20250804);
    }

    private ScorerUtils() {
    }

    public static void init(String configFile) {
        ScorerConfig scorerConfig = new ScorerConfig();
        scorerConfig.load(configFile);
        List<AbstractScorer> scorers = ScorerUtils.constructScorers(scorerConfig);

        initLoadModel(scorers);
        scorerPipelineCache.put(configFile, new ScorerPipeline(scorers));
    }

    /**
     * init load model
     *
     * @param scorers
     */
    public static void initLoadModel(List<AbstractScorer> scorers) {
        for (AbstractScorer scorer : scorers) {
            if (scorer.isEnable()) {
                scorer.loadModel();
            }
        }
    }

    public static void initLoadModel(String configFile) {
        ScorerConfig scorerConfig = new ScorerConfig();
        scorerConfig.load(configFile);
        List<AbstractScorer> scorers = ScorerUtils.constructScorers(scorerConfig);
        initLoadModel(scorers);
    }

    public static void initLoadModel(Config config) {
        ScorerConfig scorerConfig = new ScorerConfig();
        scorerConfig.load(config);
        List<AbstractScorer> scorers = ScorerUtils.constructScorers(scorerConfig);
        initLoadModel(scorers);
    }

    public static ScorerPipeline getScorerPipeline(String configFile) {
        // 不需要保证严格意义的单例
        if (scorerPipelineCache.containsKey(configFile)) {
            return scorerPipelineCache.get(configFile);
        }

        ScorerConfig scorerConfig = new ScorerConfig();
        scorerConfig.load(configFile);
        List<AbstractScorer> scorers = ScorerUtils.constructScorers(scorerConfig);
        ScorerPipeline pipeline = new ScorerPipeline(scorers);
        scorerPipelineCache.put(configFile, pipeline);
        return pipeline;
    }

    public static ScorerPipeline getScorerPipeline(Config mergeConfig) {
        ScorerConfig scorerConfig = new ScorerConfig();
        scorerConfig.load(mergeConfig);
        List<AbstractScorer> scorers = ScorerUtils.constructScorers(scorerConfig);
        return new ScorerPipeline(scorers);
    }

    public static ScorerPipeline getScorerPipeline(Config baselineConfig, List<Config> configList) {
        ScorerConfig scorerConfig = new ScorerConfig();
        scorerConfig.load(baselineConfig, configList);
        List<AbstractScorer> scorers = ScorerUtils.constructScorers(scorerConfig);
        return new ScorerPipeline(scorers);
    }

    /**
     * construct scorers
     *
     * @param scorerConfig
     * @return
     */
    public static List<AbstractScorer> constructScorers(ScorerConfig scorerConfig) {

        List<AbstractScorer> scorers = new ArrayList<AbstractScorer>();
        for (ScorerConfigInfo configInfo : scorerConfig.getConfigInfoList()) {
            if (!configInfo.getDisableSwitch()) {
                try {
                    AbstractScorer scorer = (AbstractScorer) Class.forName(configInfo.getScorerName())
                            .getConstructor(ScorerConfigInfo.class)
                            .newInstance(configInfo);
                    scorers.add(scorer);
                    LOGGER.debug("construct score [{}]", configInfo.getScorerName());
                } catch (Exception e) {
                    LOGGER.error("instance scorer {} failed {}", configInfo.getScorerName(), ExceptionUtils.getFullStackTrace(e));
                }

            }
        }
        return scorers;
    }

    /**
     * construct scorers
     *
     * @param scorerConfig
     * @return
     */
    public static List<AbstractScorer> constructQueueScorers(ScorerConfig scorerConfig, String queueName) {

        List<AbstractScorer> scorers = new ArrayList<AbstractScorer>();
        for (ScorerConfigInfo configInfo : scorerConfig.getConfigInfoList()) {
            if (!configInfo.getDisableSwitch() && configInfo.isQueueEnable(queueName)) {
                try {
                    AbstractScorer scorer = (AbstractScorer) Class.forName(configInfo.getScorerName())
                            .getConstructor(ScorerConfigInfo.class)
                            .newInstance(configInfo);
                    scorers.add(scorer);
                    LOGGER.debug("construct queue scorer [{}] [{}]", queueName, configInfo.getScorerName());
                } catch (Exception e) {
                    LOGGER.error("instance scorer {} failed {}", configInfo.getScorerName(), ExceptionUtils.getFullStackTrace(e));
                }
            }
        }
        return scorers;
    }


    public static void main(String[] args) {
        ScorerUtils.init(BASE_CONF);
    }
}
