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

import com.alibaba.fastjson.JSONObject;
import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
import com.tzld.piaoquan.ad.engine.commons.dto.AdPlatformCreativeDTO;
import com.tzld.piaoquan.ad.engine.commons.param.RankRecommendRequestParam;
import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
import com.tzld.piaoquan.ad.engine.commons.score.ScorerUtils;
import com.tzld.piaoquan.ad.engine.commons.util.AbUtil;
import com.tzld.piaoquan.ad.engine.commons.util.RootSessionIdExpConfig;
import com.tzld.piaoquan.ad.engine.commons.util.RootSessionIdTailUtil;
import com.tzld.piaoquan.ad.engine.service.log.LogHubService;
import com.tzld.piaoquan.ad.engine.service.predict.helper.NewExpInfoHelper;
import com.tzld.piaoquan.ad.engine.service.predict.param.ThresholdPredictModelParam;
import com.tzld.piaoquan.ad.engine.service.remote.FeatureRemoteService;
import com.tzld.piaoquan.ad.engine.service.score.RankService;
import com.tzld.piaoquan.ad.engine.service.score.ServiceBeanFactory;
import com.tzld.piaoquan.ad.engine.service.score.convert.RequestConvert;
import com.tzld.piaoquan.ad.engine.service.score.deprecated.BidRankRecommendRequestParam;
import com.tzld.piaoquan.ad.engine.service.score.deprecated.RankServiceThompsonImpl;
import com.tzld.piaoquan.ad.engine.service.score.deprecated.VideoAdThompsonScorerV2;
import com.tzld.piaoquan.ad.engine.service.score.deprecated.container.AdCreativeFeatureContainer;
import com.tzld.piaoquan.ad.engine.service.score.deprecated.container.PidLambdaContainer;
import com.tzld.piaoquan.ad.engine.service.score.deprecated.container.PidLambdaV2Container;
import com.tzld.piaoquan.ad.engine.service.score.strategy.*;
import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdItemFeature;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class RankServiceImpl implements RankService {

    private final static Logger log = LoggerFactory.getLogger(RankServiceImpl.class);
    private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
    private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");


    @Autowired
    private FeatureRemoteService featureRemoteService;
    @Autowired
    private RankServiceThompsonImpl rankServiceThompson;
    @Autowired
    private VideoAdThompsonScorerV2 videoAdThompsonScorerV2;
    @Autowired
    private LogHubService logHubService;
    @Autowired
    private AdCreativeFeatureContainer adCreativeFeatureContainer;

    @Autowired
    private RankStrategyBy680 rankStrategyBy680;
    @Autowired
    private RankStrategyBy683 rankStrategyBy683;
    @Autowired
    private RankStrategyBy687 rankStrategyBy687;
    @Autowired
    private RankStrategyBy688 rankStrategyBy688;
    @Autowired
    private RankStrategyBy679 rankStrategyBy679;

    @Autowired
    private RankStrategyByWeight rankStrategyByWeight;

    @Value("${ad.model.cpm.max:200}")
    Double cpmMax = 200d;
    @Value("${ad.model.cpm.min:30}")
    Double cpmMin = 30d;
    @Value("${ad.pid.cpc.exp:30}")
    private String cpcPidExpCode;
    @Value("${ad.cvr.adjusting.exp:652}")
    private String cvrAdjustingExpCode;

    @Value("${fm.model.score.exp.code:680}")
    private String fmModelScoreExpCode;

    @Value("${tactics.fm.mode.score.exp.code:679}")
    private String tacticsAndFmModelScoreExpCode;

    @ApolloJsonValue("${rank.root.session.id.tail.config:[]}")
    private List<RootSessionIdExpConfig> rankRootSessionIdConfig;

    public AdRankItem adItemRank(RankRecommendRequestParam request) {
        ScoreParam scoreParam = RequestConvert.requestConvert(request);
        RankStrategy rankStrategy = getRankStrategy(scoreParam);
        List<AdRankItem> adRankItems = rankStrategy.adItemRank(request, scoreParam);
        logHubService.scoreLogUpload(scoreParam, request.getAdIdList(), adRankItems, request, scoreParam.getExpCode());

        // 防御性检查：避免空列表导致 IndexOutOfBoundsException
        if (CollectionUtils.isEmpty(adRankItems)) {
            log.warn("adItemRank: adRankItems is empty, request={}", request);
            return null;
        }
        return adRankItems.get(0);
    }

    public RankStrategy getRankStrategy(ScoreParam scoreParam) {
        RankStrategy tailRankStrategy = getTailRankStrategy(scoreParam);
        if (tailRankStrategy != null) {
            return tailRankStrategy;
        }
        String rankStrategyCode = getRankStrategyCode(scoreParam);
        switch (rankStrategyCode) {
            case "687":
                return ServiceBeanFactory.getBean(RankStrategyBy687.class);
            case "679":
                return ServiceBeanFactory.getBean(RankStrategyBy679.class);
            case "688":
                return ServiceBeanFactory.getBean(RankStrategyBy688.class);
            case "680":
                return ServiceBeanFactory.getBean(RankStrategyBy680.class);
            case "683":
                return ServiceBeanFactory.getBean(RankStrategyBy683.class);
            case "833":
                return ServiceBeanFactory.getBean(RankStrategyBy833.class);
            case "834":
                return ServiceBeanFactory.getBean(RankStrategyBy834.class);
            case "840":
                return ServiceBeanFactory.getBean(RankStrategyBy840.class);
            case "843":
                return ServiceBeanFactory.getBean(RankStrategyBy843.class);
            case "847":
                return ServiceBeanFactory.getBean(RankStrategyBy847.class);
            case "849":
                return ServiceBeanFactory.getBean(RankStrategyBy849.class);
            case "851":
                return ServiceBeanFactory.getBean(RankStrategyBy851.class);
            case "865":
                return ServiceBeanFactory.getBean(RankStrategyBy865.class);
            case "872":
                return ServiceBeanFactory.getBean(RankStrategyBy872.class);
            case "894":
                return ServiceBeanFactory.getBean(RankStrategyBy894.class);
            case "901":
                return ServiceBeanFactory.getBean(RankStrategyBy901.class);
            case "902":
                return ServiceBeanFactory.getBean(RankStrategyBy902.class);
            default:
                return ServiceBeanFactory.getBean(RankStrategyByWeight.class);
        }
    }

    private RankStrategy getTailRankStrategy(ScoreParam scoreParam) {
        // 尾号实验 897
        if (AbUtil.isInTailExp(scoreParam.getTailExpCodeSet(), "897")) {
            scoreParam.setExpCode("897");
            return ServiceBeanFactory.getBean(RankStrategyBy897.class);
        }
        // 尾号实验 896
        if (AbUtil.isInTailExp(scoreParam.getTailExpCodeSet(), "896")) {
            scoreParam.setExpCode("896");
            return ServiceBeanFactory.getBean(RankStrategyBy896.class);
        }
        // 尾号实验 891
        if (AbUtil.isInTailExp(scoreParam.getTailExpCodeSet(), "891")) {
            scoreParam.setExpCode("891");
            return ServiceBeanFactory.getBean(RankStrategyBy891.class);
        }
        // 尾号实验 890
        if (AbUtil.isInTailExp(scoreParam.getTailExpCodeSet(), "890")) {
            scoreParam.setExpCode("890");
            return ServiceBeanFactory.getBean(RankStrategyBy890.class);
        }
        // 尾号实验 887
        if (AbUtil.isInTailExp(scoreParam.getTailExpCodeSet(), "887")) {
            scoreParam.setExpCode("887");
            return ServiceBeanFactory.getBean(RankStrategyBy887.class);
        }
        // 尾号实验 875(index 5)命中 → 走 872 排序策略；与 AB 的 expCode 完全隔离
        if (AbUtil.isInTailExp(scoreParam.getTailExpCodeSet(), "875")) {
            return ServiceBeanFactory.getBean(RankStrategyBy872.class);
        }
        // 尾号实验 895
        if (AbUtil.isInTailExp(scoreParam.getTailExpCodeSet(), "895")) {
            return ServiceBeanFactory.getBean(RankStrategyBy894.class);
        }
        if (AbUtil.isInTailExp(scoreParam.getTailExpCodeSet(), "901")) {
            return ServiceBeanFactory.getBean(RankStrategyBy901.class);
        }
        if (AbUtil.isInTailExp(scoreParam.getTailExpCodeSet(), "902")) {
            return ServiceBeanFactory.getBean(RankStrategyBy902.class);
        }
        return null;
    }

    private String getRankStrategyCode(ScoreParam scoreParam) {
        try {
            List<RootSessionIdExpConfig> expConfigs = RootSessionIdTailUtil.getRootSessionIdTailConfig(scoreParam, RootSessionIdTailUtil.rankTailN, rankRootSessionIdConfig);
            if (!expConfigs.isEmpty()) {
                RootSessionIdExpConfig expConfig = expConfigs.get(0);
                if (null != expConfig && null != expConfig.getConfig()) {
                    String expCode = expConfig.getConfig().get("rank");
                    if (null != expCode) {
                        return expCode;
                    }
                }
            }
        } catch (Exception e) {
            log.error("排序rootSessionId尾号配置异常", e);
        }
        return scoreParam.getExpCode();
    }

    private AdRankItem rankBy687(RankRecommendRequestParam request) {
        ScoreParam scoreParam = RequestConvert.requestConvert(request);
        List<AdRankItem> adRankItems = rankStrategyBy687.adItemRank(request, scoreParam);
        logHubService.scoreLogUpload(scoreParam, request.getAdIdList(), adRankItems, request, "687");
        return adRankItems.get(0);
    }

    private AdRankItem rankBy680(RankRecommendRequestParam request) {
        ScoreParam scoreParam = RequestConvert.requestConvert(request);
        List<AdRankItem> adRankItems = rankStrategyBy680.adItemRank(request, scoreParam);
        logHubService.scoreLogUpload(scoreParam, request.getAdIdList(), adRankItems, request, "680");
        return adRankItems.get(0);
    }

    private AdRankItem rankBy683(RankRecommendRequestParam request) {
        ScoreParam scoreParam = RequestConvert.requestConvert(request);
        List<AdRankItem> adRankItems = rankStrategyBy683.adItemRank(request, scoreParam);
        logHubService.scoreLogUpload(scoreParam, request.getAdIdList(), adRankItems, request, "683");
        return adRankItems.get(0);
    }

    private AdRankItem rankStrategyXGBAutoUpdateModel688(RankRecommendRequestParam request) {
        ScoreParam scoreParam = RequestConvert.requestConvert(request);
        List<AdRankItem> adRankItems = rankStrategyBy688.adItemRank(request, scoreParam);
        logHubService.scoreLogUpload(scoreParam, request.getAdIdList(), adRankItems, request, "688");
        return adRankItems.get(0);
    }

    private AdRankItem rankBy679(RankRecommendRequestParam requestParam) {
        ScoreParam scoreParam = RequestConvert.requestConvert(requestParam);
        List<AdRankItem> adRankItems = rankStrategyBy679.adItemRank(requestParam, scoreParam);
        logHubService.scoreLogUpload(scoreParam, requestParam.getAdIdList(), adRankItems, requestParam, "679");
        double score = adRankItems.get(0).getScore();
        if (score > 0) {
            return adRankItems.get(0);
        }
        return null;
    }

    // public AdRankItem adItemRankOld(RankRecommendRequestParam request) {
    //     ScoreParam param = RequestConvert.requestConvert(request);
    //
    //     UserAdFeature userAdFeature = featureRemoteService.getUserAdFeature(request.getMid());
    //     if (userAdFeature == null) {
    //         userAdFeature = new UserAdFeature();
    //     }
    //     Map<Long, List<AdPlatformCreativeDTO>> groupMap = request
    //             .getAdIdList()
    //             .stream()
    //             .collect(Collectors.groupingBy(AdPlatformCreativeDTO::getCreativeId));
    //     Map<Long, AdRankItem> cache = adCreativeFeatureContainer.getAll(new ArrayList<>(groupMap.keySet()));
    //     List<AdRankItem> rankItems = Collections.emptyList();
    //     if (!cache.isEmpty()) {
    //         rankItems = new LinkedList<>(cache.values());
    //     }
    //     // 避免recommend-feature出问题
    //     if (CollectionUtils.isEmpty(rankItems)) {
    //         rankItems = new LinkedList<>();
    //         for (Long adId : groupMap.keySet()) {
    //             AdRankItem item = new AdRankItem();
    //             item.setAdId(adId);
    //             item.setItemFeature(new AdItemFeature());
    //             rankItems.add(item);
    //         }
    //     }
    //     boolean inCpcPidExp = false;
    //     boolean inCvrAdjustingExp = false;
    //     // if (request.getAdAbExpArr() != null && request.getAdAbExpArr().size() != 0) {
    //     //     for (Map<String, Object> map : request.getAdAbExpArr()) {
    //     //         if (map.getOrDefault("abExpCode", "").equals(cpcPidExpCode)) {
    //     //             inCpcPidExp = true;
    //     //         }
    //     //         if (map.getOrDefault("abExpCode", "").equals(cvrAdjustingExpCode)) {
    //     //             inCvrAdjustingExp = true;
    //     //         }
    //     //     }
    //     // }
    //     if (CollectionUtils.isNotEmpty(request.getAdAbExpArr())) {
    //         Set<String> abExpCode = request.getAdAbExpArr().stream()
    //                 .map(map -> map.get("abExpCode"))
    //                 .filter(Objects::nonNull)
    //                 .map(Object::toString)
    //                 .collect(Collectors.toSet());
    //         inCpcPidExp = abExpCode.contains(cpcPidExpCode);
    //         inCvrAdjustingExp = abExpCode.contains(cvrAdjustingExpCode);
    //     }
    //     double lambda = -1d;
    //     if (inCpcPidExp) {
    //         for (AdRankItem item : rankItems) {
    //             try {
    //                 AdPlatformCreativeDTO dto = groupMap.get(item.getAdId()).get(0);
    //                 item.setBid1(dto.getBid1());
    //                 item.setBid2(dto.getBid2());
    //                 lambda = PidLambdaForCpcContainer.getPidLambda(item.getAdId());
    //                 if (lambda < 0) {
    //                     item.setCpa(dto.getCpa());
    //                     item.setPidLambda(1);
    //                 } else {
    //                     if (dto.getCpa() > 1 && lambda <= 1) {
    //                         lambda = 2d;
    //                     }
    //                     item.setCpa(lambda);
    //                     item.setPidLambda(1d);
    //                 }
    //             } catch (Exception e) {
    //                 log.error("rankItems info error itemId={}", item.getAdId());
    //                 e.printStackTrace();
    //             }
    //         }
    //     } else {
    //         for (AdRankItem item : rankItems) {
    //             try {
    //                 AdPlatformCreativeDTO dto = groupMap.get(item.getAdId()).get(0);
    //                 item.setBid1(dto.getBid1());
    //                 item.setBid2(dto.getBid2());
    //                 item.setCpa(dto.getCpa());
    //                 item.setPidLambda(1d);
    //             } catch (Exception e) {
    //                 log.error("rankItems info error itemId={}", item.getAdId());
    //                 e.printStackTrace();
    //             }
    //         }
    //     }
    //
    //     // 兜底方案
    //     List<AdRankItem> rankResult;
    //     if (inCvrAdjustingExp) {
    //         rankResult = rank(param, userAdFeature, rankItems, ScorerUtils.CVR_ADJUSTING);
    //     } else {
    //         rankResult = rank(param, userAdFeature, rankItems, ScorerUtils.BASE_CONF);
    //     }
    //
    //     if (!CollectionUtils.isEmpty(rankResult)) {
    //         JSONObject object = new JSONObject();
    //         object.put("mid", request.getMid());
    //         object.put("adid", rankResult.get(0).getAdId());
    //         object.put("type", rankResult.get(0).getScore_type());
    //         object.put("pctr", rankResult.get(0).getCtr());
    //         object.put("pcvr", rankResult.get(0).getCvr());
    //         object.put("score", rankResult.get(0).getScore());
    //         object.put("pidLambda", rankResult.get(0).getPidLambda());
    //         object.put("lrsamples", rankResult.get(0).getLrSampleString());
    //         object.put("dataTime", LocalDateTime.now().format(timeFormatter));
    //         object.put("creativeId", rankResult.get(0).getAdId());
    //         object.put("videoId", request.getVideoId());
    //         object.put("pqtId", request.getPqtId());
    //         log.info("svc=adItemRank {}", JSONObject.toJSONString(object));
    //         object.remove("lrsamples");
    //         if (inCpcPidExp) {
    //             AdPlatformCreativeDTO dto = groupMap.get(rankResult.get(0).getAdId()).get(0);
    //             object.put("cpa", dto.getCpa() * dto.getBid1());
    //             object.put("oCpa", dto.getCpa());
    //             object.put("realECpm", rankResult.get(0).getEcpm1());
    //             log.info("svc=cpc_pid obj={}", JSONObject.toJSONString(object));
    //         } else {
    //             log.info("svc=pid_log obj={}", JSONObject.toJSONString(object));
    //         }
    //
    //         // 日志上报
    //         logHubService.scoreLogUpload(param, request.getAdIdList(), rankResult, request, "531");
    //
    //         return rankResult.get(0);
    //     } else {
    //         // 空返回值
    //         return new AdRankItem();
    //     }
    // }

    public AdRankItem adItemRankWithVideoAdThompson(RankRecommendRequestParam request) {
        ScoreParam param = RequestConvert.requestConvert(request);
        LocalDateTime currentTime = LocalDateTime.now();
        int currentHour = currentTime.getHour();
        int dayOfWeek = currentTime.getDayOfWeek().getValue();
        param.getRequestContext().setHour(currentHour + "");
        param.getRequestContext().setWeek(dayOfWeek + "");
        param.getRequestContext().setRegion(request.getRegion().replace("省", ""));
        param.getRequestContext().setCity(request.getCity().replace("市", ""));
        param.getRequestContext().setDay(currentTime.format(dateFormatter));

        Set<String> expCodes = new HashSet<>();
        if (CollectionUtils.isNotEmpty(request.getAdAbExpArr())) {
            expCodes = request.getAdAbExpArr().stream()
                    .map(m -> m.get("abExpCode"))
                    .filter(Objects::nonNull)
                    .map(Object::toString)
                    .collect(Collectors.toSet());
        }

        ThresholdPredictModelParam modelParam = ThresholdPredictModelParam.builder()
                .build();
        // 兜底方案
        String abCode = "";
        List<AdRankItem> rankResult = null;
        if (expCodes.contains("663") ||
                (expCodes.contains(NewExpInfoHelper.flagId) && NewExpInfoHelper.checkInNewExpGroupAndSetParamIfIn(
                        request.getAppType().toString(), request.getNewExpGroup(), "663", modelParam))) {
            rankResult = videoAdThompsonScorerV2.thompsonScorerByExp663(param, request.getAdIdList());
            abCode = "663";
        } else if (expCodes.contains("664") ||
                (expCodes.contains(NewExpInfoHelper.flagId) && NewExpInfoHelper.checkInNewExpGroupAndSetParamIfIn(
                        request.getAppType().toString(), request.getNewExpGroup(), "664", modelParam))) {
            rankResult = videoAdThompsonScorerV2.thompsonScorerByExp664(param, request.getAdIdList());
            abCode = "664";
        } else if (expCodes.contains("665") ||
                (expCodes.contains(NewExpInfoHelper.flagId) && NewExpInfoHelper.checkInNewExpGroupAndSetParamIfIn(
                        request.getAppType().toString(), request.getNewExpGroup(), "665", modelParam))) {
            rankResult = videoAdThompsonScorerV2.thompsonScorerByExp665(param, request.getAdIdList());
            abCode = "665";
        } else if (expCodes.contains("666") ||
                (expCodes.contains(NewExpInfoHelper.flagId) && NewExpInfoHelper.checkInNewExpGroupAndSetParamIfIn(
                        request.getAppType().toString(), request.getNewExpGroup(), "666", modelParam))) {
            rankResult = videoAdThompsonScorerV2.thompsonScorerByExp666(param, request.getAdIdList());
            abCode = "666";
        } else if (expCodes.contains("669") ||
                (expCodes.contains(NewExpInfoHelper.flagId) && NewExpInfoHelper.checkInNewExpGroupAndSetParamIfIn(
                        request.getAppType().toString(), request.getNewExpGroup(), "669", modelParam))) {
            rankResult = videoAdThompsonScorerV2.thompsonScorerByExp669(param, request.getAdIdList());
            abCode = "669";
        } else if (expCodes.contains("670") ||
                (expCodes.contains(NewExpInfoHelper.flagId) && NewExpInfoHelper.checkInNewExpGroupAndSetParamIfIn(
                        request.getAppType().toString(), request.getNewExpGroup(), "670", modelParam))) {
            rankResult = videoAdThompsonScorerV2.thompsonScorerByExp670(param, request.getAdIdList());
            abCode = "670";
        } else if (expCodes.contains("671") ||
                (expCodes.contains(NewExpInfoHelper.flagId) && NewExpInfoHelper.checkInNewExpGroupAndSetParamIfIn(
                        request.getAppType().toString(), request.getNewExpGroup(), "671", modelParam))) {
            rankResult = videoAdThompsonScorerV2.thompsonScorerByExp671(param, request.getAdIdList());
            abCode = "671";
        } else if (expCodes.contains("672") ||
                (expCodes.contains(NewExpInfoHelper.flagId) && NewExpInfoHelper.checkInNewExpGroupAndSetParamIfIn(
                        request.getAppType().toString(), request.getNewExpGroup(), "672", modelParam))) {
            rankResult = videoAdThompsonScorerV2.thompsonScorerByExp672(param, request.getAdIdList());
            abCode = "672";
        }

        // 日志上报
        logHubService.scoreLogUpload(param, request.getAdIdList(), rankResult, request, abCode);

        if (!CollectionUtils.isEmpty(rankResult)) {
            JSONObject object = new JSONObject();
            object.put("mid", request.getMid());
            object.put("adid", rankResult.get(0).getAdId());
            object.put("type", rankResult.get(0).getScore_type());
            object.put("pctr", rankResult.get(0).getCtr());
            object.put("pcvr", rankResult.get(0).getCvr());
            object.put("score", rankResult.get(0).getScore());
            object.put("pidLambda", rankResult.get(0).getPidLambda());
            object.put("lrsamples", rankResult.get(0).getLrSampleString());
            object.put("dataTime", currentTime.format(timeFormatter));
            object.put("creativeId", rankResult.get(0).getAdId());
            object.put("videoId", rankResult.get(0).getVideoId());
            object.put("pqtId", request.getPqtId());
            log.info("svc=videoAdThompsonRank_lr_log {}", JSONObject.toJSONString(object));
            object.remove("lrsamples");
            object.put("score_500", rankResult.get(0).getTf_ctr());
            object.put("score_1000", rankResult.get(0).getTf_cvr());
            log.info("svc=videoAdThompsonRank_log obj={}", JSONObject.toJSONString(object));
            return rankResult.get(0);
        } else {
            return new AdRankItem();
        }
    }

    @Override
    public AdPlatformCreativeDTO adBidRank(BidRankRecommendRequestParam request) {

        ScoreParam param = RequestConvert.requestConvert(request);

        LocalDateTime currentTime = LocalDateTime.now();
        int currentHour = currentTime.getHour();
        int dayOfWeek = currentTime.getDayOfWeek().getValue();
        param.getRequestContext().setHour(currentHour + "");
        param.getRequestContext().setWeek(dayOfWeek + "");
        param.getRequestContext().setRegion(request.getRegion().replace("省", ""));
        param.getRequestContext().setCity(request.getCity().replace("市", ""));
        param.getRequestContext().setDay(currentTime.format(dateFormatter));

        UserAdFeature userAdFeature = featureRemoteService.getUserAdFeature(request.getMid());
        if (userAdFeature == null) {
            userAdFeature = new UserAdFeature();
        }
        Map<Long, List<AdPlatformCreativeDTO>> groupMap = request
                .getCreativeList()
                .stream()
                .collect(Collectors.groupingBy(creativeDTO -> creativeDTO.getCreativeId()));


        Map<Long, AdRankItem> cache = adCreativeFeatureContainer.getAll(new ArrayList<>(groupMap.keySet()));
        List<AdRankItem> rankItems = Collections.emptyList();
        if (!cache.isEmpty()) {
            rankItems = new LinkedList<>(cache.values());
        }
        double lambda = -1d;
        for (AdRankItem item : rankItems) {
            try {
                AdPlatformCreativeDTO dto = groupMap.get(item.getAdId()).get(0);
                item.setBid1(dto.getBid1());
                item.setBid2(dto.getBid2());
                lambda = PidLambdaContainer.getPidLambda(item.getAdId());
                if (lambda < 0) {
                    item.setCpa(dto.getCpa());
                    item.setPidLambda(0.6);
                } else {
                    if (dto.getCpa() > 1 && lambda <= 1) {
                        lambda = 2d;
                    }
                    item.setCpa(lambda);
                    item.setPidLambda(1d);
                }

            } catch (Exception e) {
                log.error("rankItems info error itemId={}", item.getAdId());
                e.printStackTrace();
            }
        }
        List<AdRankItem> rankResult;
        if (rankItems == null || rankItems.size() == 0) {
            rankItems = new LinkedList<>();
            for (AdPlatformCreativeDTO dto : request.getCreativeList()) {
                AdRankItem item = new AdRankItem();
                item.setBid1(dto.getBid1());
                item.setBid2(dto.getBid2());
                item.setAdId(dto.getCreativeId());
                item.setItemFeature(new AdItemFeature());
                lambda = PidLambdaContainer.getPidLambda(item.getAdId());
                if (lambda < 0) {
                    item.setCpa(dto.getCpa());
                    item.setPidLambda(0.6);
                } else {
                    if (dto.getCpa() > 1 && lambda <= 1) {
                        lambda = 2d;
                    }
                    item.setCpa(lambda);
                    item.setPidLambda(1d);
                }
                rankItems.add(item);
            }
            rankResult = rankServiceThompson.rank(param, userAdFeature, rankItems, null);
        } else {
            rankResult = rank(param, userAdFeature, rankItems, ScorerUtils.BASE_CONF);
        }

        AdRankItem topItem = rankResult.get(0);

        AdPlatformCreativeDTO result = AdPlatformCreativeDTO
                .builder()
                .build();
        BeanUtils.copyProperties(topItem, result);
        result.setCreativeId(topItem.getAdId());
        result.setPctr(topItem.getCtr());
        result.setPcvr(topItem.getCvr());
//        result.setCreativeCode(groupMap.get(topItem.getAdId()+"").get(0).getCreativeCode());
        result.setCreativeCode(groupMap.get(topItem.getAdId()).get(0).getCreativeCode());
        double realECpm = 0d;
        // 经验值 待定
//        realECpm=topItem.getEcpm1();
        realECpm = topItem.getEcpm2();

        if (realECpm > cpmMax / 1000d) {
            realECpm = cpmMax / 1000d;
        }
        if (realECpm < cpmMin / 1000d) {
            realECpm = cpmMin / 1000d;
        }
        result.setEcpm2(realECpm);
        AdPlatformCreativeDTO dto = groupMap.get(topItem.getAdId()).get(0);
        JSONObject object = new JSONObject();
        object.put("mid", request.getMid());
        object.put("adid", result.getCreativeId());
        object.put("creativeCode", result.getCreativeCode());
        object.put("type", topItem.getScore_type());
        object.put("pctr", topItem.getCtr());
        object.put("pcvr", topItem.getCvr());
        object.put("lrsamples", topItem.getLrSampleString());
        object.put("pidLambda", topItem.getPidLambda());
        object.put("videoId", request.getVideoId());

        // 临时加入供pid v2使用
        object.put("realECpm", realECpm);
        object.put("creativeId", result.getCreativeId());
        // CPA还原
        object.put("cpa", dto.getCpa() * dto.getBid1());
        object.put("oCpa", dto.getCpa());
        object.put("dataTime", currentTime.format(timeFormatter));
        object.put("pqtId", request.getPqtId());
        log.info("svc=adBidRank {}", JSONObject.toJSONString(object));
        object.remove("lrsamples");
        log.info("svc=pid_log obj={}", JSONObject.toJSONString(object));
        return result;
    }

    @Override
    public AdPlatformCreativeDTO adBidRankNewPid(BidRankRecommendRequestParam request) {

        ScoreParam param = RequestConvert.requestConvert(request);
        LocalDateTime currentTime = LocalDateTime.now();
        int currentHour = currentTime.getHour();
        int dayOfWeek = currentTime.getDayOfWeek().getValue();
        param.getRequestContext().setHour(currentHour + "");
        param.getRequestContext().setWeek(dayOfWeek + "");
        param.getRequestContext().setRegion(request.getRegion().replace("省", ""));
        param.getRequestContext().setCity(request.getCity().replace("市", ""));
        param.getRequestContext().setDay(currentTime.format(dateFormatter));

        UserAdFeature userAdFeature = featureRemoteService.getUserAdFeature(request.getMid());
        if (userAdFeature == null) {
            userAdFeature = new UserAdFeature();
        }
        Map<Long, List<AdPlatformCreativeDTO>> groupMap = request
                .getCreativeList()
                .stream()
                .collect(Collectors.groupingBy(creativeDTO -> creativeDTO.getCreativeId()));


        Map<Long, AdRankItem> cache = adCreativeFeatureContainer.getAll(new ArrayList<>(groupMap.keySet()));
        List<AdRankItem> rankItems = Collections.emptyList();
        if (!cache.isEmpty()) {
            rankItems = new LinkedList<>(cache.values());
        }
        double lambda = -1d;
        for (AdRankItem item : rankItems) {
            try {

                AdPlatformCreativeDTO dto = groupMap.get(item.getAdId()).get(0);
                item.setBid1(dto.getBid1());
                item.setBid2(dto.getBid2());
                lambda = PidLambdaV2Container.getPidLambda(item.getAdId());
                if (lambda < 0) {
                    item.setCpa(dto.getCpa());
                    item.setPidLambda(dto.getCpa() * 0.6);
                } else {
                    if (dto.getCpa() > 1 && lambda <= 1) {
                        lambda = 2d;
                    }
                    item.setCpa(dto.getCpa());
                    item.setPidLambda(lambda);
                }

            } catch (Exception e) {
                log.error("rankItems info error itemId={}", item.getAdId());
                e.printStackTrace();
            }
        }
        List<AdRankItem> rankResult;
        if (rankItems == null || rankItems.size() == 0) {
            rankItems = new LinkedList<>();
            for (AdPlatformCreativeDTO dto : request.getCreativeList()) {
                AdRankItem item = new AdRankItem();
                item.setBid1(dto.getBid1());
                item.setBid2(dto.getBid2());
                item.setAdId(dto.getCreativeId());
                item.setItemFeature(new AdItemFeature());
                lambda = PidLambdaV2Container.getPidLambda(item.getAdId());

                if (lambda < 0) {
                    item.setCpa(dto.getCpa());
                    item.setPidLambda(dto.getCpa() * 0.6);
                } else {
                    if (dto.getCpa() > 1 && lambda <= 1) {
                        lambda = 2d;
                    }
                    item.setCpa(dto.getCpa());
                    item.setPidLambda(lambda);
                }
                rankItems.add(item);
            }
            rankResult = rankServiceThompson.rank(param, userAdFeature, rankItems, null);
        } else {
            rankResult = rank(param, userAdFeature, rankItems, ScorerUtils.BASE_CONF);
        }

        AdRankItem topItem = rankResult.get(0);

        AdPlatformCreativeDTO result = AdPlatformCreativeDTO
                .builder()
                .build();
        BeanUtils.copyProperties(topItem, result);
        result.setCreativeId(topItem.getAdId());
        result.setPctr(topItem.getCtr());
        result.setPcvr(topItem.getCvr());
        result.setCreativeCode(groupMap.get(topItem.getAdId()).get(0).getCreativeCode());
        double realECpm = 0d;
        realECpm = topItem.getEcpm2();

        if (realECpm > cpmMax / 1000d) {
            realECpm = cpmMax / 1000d;
        }
        if (realECpm < cpmMin / 1000d) {
            realECpm = cpmMin / 1000d;
        }
        result.setEcpm2(realECpm);
        AdPlatformCreativeDTO dto = groupMap.get(topItem.getAdId()).get(0);
        JSONObject object = new JSONObject();
        object.put("mid", request.getMid());
        object.put("adid", result.getCreativeId());
        object.put("creativeCode", result.getCreativeCode());
        object.put("type", topItem.getScore_type());
        object.put("pctr", topItem.getCtr());
        object.put("pcvr", topItem.getCvr());
        object.put("lrsamples", topItem.getLrSampleString());
        object.put("pidLambda", topItem.getPidLambda());
        object.put("realECpm", realECpm);
        object.put("creativeId", result.getCreativeId());
        object.put("videoId", request.getVideoId());
        // CPA还原
        object.put("cpa", dto.getCpa() * dto.getBid1());
        object.put("oCpa", dto.getCpa());
        object.put("pqtId", request.getPqtId());
        object.put("dataTime", currentTime.format(timeFormatter));
        log.info("svc=adBidRankNewPid {}", JSONObject.toJSONString(object));
        object.remove("lrsamples");
        log.info("svc=pid_v2_log obj={}", JSONObject.toJSONString(object));
        return result;
    }

    public List<AdRankItem> rank(ScoreParam param, UserAdFeature userAdFeature, List<AdRankItem> rankItems, String configFile) {
        List<AdRankItem> rankResult = ScorerUtils
                .getScorerPipeline(configFile)
                .scoring(param, userAdFeature, rankItems);
        return rankResult;
    }


}
