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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Sets;
import com.tzld.commons.aliyun.log.AliyunLogManager;
import com.tzld.piaoquan.ad.engine.commons.dto.AdPlatformCreativeDTO;
import com.tzld.piaoquan.ad.engine.commons.param.RecommendRequestParam;
import com.tzld.piaoquan.ad.engine.commons.score.ScoreParam;
import com.tzld.piaoquan.ad.engine.service.log.LogHubService;
import com.tzld.piaoquan.ad.engine.service.predict.v2.PredictContext;
import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRequestContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class LogHubServiceImpl implements LogHubService {

    private static final ThreadPoolExecutor logUploadThreadPool = new ThreadPoolExecutor(20, 40, 30,
            TimeUnit.MINUTES, new LinkedBlockingDeque<>(), new ThreadPoolExecutor.CallerRunsPolicy());

    @Value("${aliyun.log.logstore.statistics}")
    private String scoreStatisticsLogStore;
    @Value("${aliyun.log.project}")
    private String project;

    @Value("${aliyun.log.logstore.crowdChooseStatistics}")
    private String crowdChooseStatisticsLogStore;

    @Autowired
    private AliyunLogManager aliyunLogManager;

    private static final Set<String> FEATURE_FIELD_SET = Sets.newHashSet();

    @Override
    public void scoreLogUpload(ScoreParam param, List<AdPlatformCreativeDTO> adIdList, List<AdRankItem> rankItems, RecommendRequestParam requestParam, String abCode) {
        logUploadThreadPool.execute(new Runnable() {
            @Override
            public void run() {

                AdRequestContext context = param.getRequestContext();

                JSONObject logMap = new JSONObject();
                logMap.put("pqtid", param.getPqtId());
                logMap.put("mid", param.getMid());
                logMap.put("vid", param.getVideoId());
                logMap.put("abcode", param.getAdAbGroup());
                logMap.put("expid", abCode);
                logMap.put("apptype", context.getApptype());
                logMap.put("extractstrategy", "engine");

                // 获取AB实验列表
                Set<String> abExpCode = new HashSet<>();
                if (CollectionUtils.isNotEmpty(requestParam.getAdAbExpArr())) {
                    for (Map map : requestParam.getAdAbExpArr()) {
                        if (map.containsKey("abExpCode")) {
                            abExpCode.add(map.get("abExpCode").toString());
                        }
                    }
                }
                logMap.put("expids", abExpCode);

                List<JSONObject> scoreResult = new ArrayList<>();
                for (AdRankItem rankItem : rankItems) {
                    JSONObject json = new JSONObject();
                    json.put("cid", rankItem.getAdId());
                    json.put("score", rankItem.getScore());
                    rankItem.getScoreMap().put("score", rankItem.getScore());
                    json.put("scoremap", rankItem.getScoreMap());
                    scoreResult.add(json);
                }

                JSONObject result = new JSONObject();
                result.put("score", scoreResult);
                logMap.put("result", JSON.toJSONString(result));

                AdRankItem top1 = rankItems.get(0);
                logMap.put("cid", top1.getAdId());
                logMap.put("adverid", top1.getAdVerId());
                logMap.put("adid", top1.getId());
                logMap.put("campaignid", top1.getCampaignId());
                logMap.put("score", top1.getScore());
                logMap.put("extinfo", JSON.toJSONString(top1.getExt()));


                top1.getScoreMap().put("score", top1.getScore());
                logMap.put("scoremap", JSON.toJSONString(top1.getScoreMap()));
                // logMap.put("allfeature", JSON.toJSONString(top1.getFeatureMap()));
                logMap.put("metafeature", JSON.toJSONString(top1.getMetaFeatureMap()));

                long featureTableSize = 0;
                if (MapUtils.isNotEmpty(top1.getMetaFeatureMap())) {
                    featureTableSize = top1.getMetaFeatureMap().entrySet()
                            .stream()
                            .filter(e -> MapUtils.isNotEmpty(e.getValue()))
                            .count();
                }
                logMap.put("featuretablesize", featureTableSize);

                aliyunLogManager.sendLog(project, scoreStatisticsLogStore, "", logMap);
            }
        });
    }

    @Override
    public void crowdChooseLogUpload(PredictContext context) {
        logUploadThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                Map<String, Object> logMap = new HashMap<>();
                logMap.put("mid", context.getMid());
                logMap.put("vid", context.getVideoId());
                logMap.put("apptype", context.getAppType());
                logMap.put("abcode", context.getAdAbCode());
                logMap.put("pqtid", context.getPqtId());
                logMap.put("isshowad", context.getLogParam().isAIsShowAd());
                logMap.put("expid", context.getLogParam().getExpId());
                logMap.put("score", context.getLogParam().getScore());
                logMap.put("allfeature", JSON.toJSONString(context.getLogParam().getAllFeature()));
                logMap.put("metafeature", JSON.toJSONString(context.getLogParam().getMetaFeature()));
                logMap.put("scoremap", JSON.toJSONString(context.getLogParam().getScoreMap()));
                logMap.put("isnewuser", context.getLogParam().isBIsNewUser());
                aliyunLogManager.sendLog(project, crowdChooseStatisticsLogStore, "", logMap);
            }
        });
    }
}