package com.tzld.piaoquan.ad.engine.service.score.scorer;


import com.google.common.collect.Lists;
import com.tzld.piaoquan.ad.engine.commons.score.AbstractScorer;
import com.tzld.piaoquan.ad.engine.commons.score.BaseXGBoostModelScorer;
import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
import com.tzld.piaoquan.ad.engine.commons.score.ScorerConfigInfo;
import com.tzld.piaoquan.ad.engine.commons.score.model.PAIModelV1;
import com.tzld.piaoquan.ad.engine.commons.score.model.PAIModelV2;
import com.tzld.piaoquan.ad.engine.commons.score.model.XGBoostModel683;
import com.tzld.piaoquan.ad.engine.commons.thread.ThreadPoolFactory;
import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
import com.tzld.piaoquan.recommend.feature.domain.ad.base.UserAdFeature;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;

public class PAIScorer extends AbstractScorer {

    private final static Logger LOGGER = LoggerFactory.getLogger(PAIScorer.class);


    public PAIScorer(ScorerConfigInfo configInfo) {
        super(configInfo);
    }

    @Override
    public List<AdRankItem> scoring(final ScoreParam param,
                                    final UserAdFeature userAdFeature,
                                    final List<AdRankItem> rankItems) {
        throw new NoSuchMethodError();
    }

    public List<AdRankItem> scoring(final Map<String, String> sceneFeatureMap,
                                    final Map<String, String> userFeatureMap,
                                    final List<AdRankItem> rankItems) {
        if (CollectionUtils.isEmpty(rankItems)) {
            return rankItems;
        }

        return rankByJava(sceneFeatureMap, userFeatureMap, rankItems);
    }

//    private List<AdRankItem> rankByJava(final Map<String, String> sceneFeatureMap,
//                                        final Map<String, String> userFeatureMap,
//                                        final List<AdRankItem> items) {
//        long startTime = System.currentTimeMillis();
//        PAIModelV1 model = PAIModelV1.getModel();
//        // 所有都参与打分，按照ctr排序
//        multipleCtrScore(items, userFeatureMap, sceneFeatureMap, model);
//
//        // debug log
//        if (LOGGER.isDebugEnabled()) {
//            for (int i = 0; i < items.size(); i++) {
//                LOGGER.debug("before enter feeds model predict ctr score [{}] [{}]", items.get(i), items.get(i));
//            }
//        }
//
//        Collections.sort(items);
//
//        LOGGER.debug("ctr ranker java execute time: [{}]", System.currentTimeMillis() - startTime);
//        LOGGER.debug("[ctr ranker time java] items size={}, cost={} ", items != null ? items.size() : 0,
//                System.currentTimeMillis() - startTime);
//        return items;
//    }

    private List<AdRankItem> rankByJava(final Map<String, String> sceneFeatureMap,
                                        final Map<String, String> userFeatureMap,
                                        final List<AdRankItem> items) {
        if (items == null || items.isEmpty()) {
            return Collections.emptyList();
        }

        long startTime = System.currentTimeMillis();
        PAIModelV1 model = PAIModelV1.getModel();

        final int batchSize = 300;
        List<List<AdRankItem>> batches = new ArrayList<>();
        for (int i = 0; i < items.size(); i += batchSize) {
            batches.add(new ArrayList<>(items.subList(i, Math.min(i + batchSize, items.size()))));
        }

        ExecutorService executor = ThreadPoolFactory.score();
        List<Future<List<AdRankItem>>> futures = new ArrayList<>();

        for (List<AdRankItem> batch : batches) {
            futures.add(executor.submit(() -> {
                try {
                    multipleCtrScore(batch, userFeatureMap, sceneFeatureMap, model);
                } catch (Exception e) {
                    LOGGER.error("Error during multipleCtrScore batch execution", e);
                }
                return batch;
            }));
        }

        // 合并结果
        List<AdRankItem> merged = new ArrayList<>();
        for (Future<List<AdRankItem>> future : futures) {
            try {
                merged.addAll(future.get(400, TimeUnit.MILLISECONDS));
            } catch (Exception e) {
                LOGGER.error("Execution error in batch", e);
            }
        }

        Collections.sort(merged);

        LOGGER.debug("ctr ranker java execute time: [{}ms]", System.currentTimeMillis() - startTime);
        return merged;
    }





    private void multipleCtrScore(final List<AdRankItem> items,
                                  final Map<String, String> userFeatureMap,
                                  final Map<String, String> sceneFeatureMap,
                                  final PAIModelV1 model) {

        List<Float> score = model.score(items, userFeatureMap, sceneFeatureMap);
        LOGGER.debug("PAIScorer score={}", score);
        for (int i = 0; i < items.size(); i++) {
            Double pro = Double.valueOf(score.get(i));
            items.get(i).setLrScore(pro);
            items.get(i).getScoreMap().put("ctcvrScore", pro);
        }
    }


}