package com.tzld.piaoquan.ad.engine.server.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import com.tzld.piaoquan.ad.engine.commons.dto.AdPlatformCreativeDTO;
import com.tzld.piaoquan.ad.engine.commons.enums.GuaranteedTypeEnum;
import com.tzld.piaoquan.ad.engine.commons.param.LayerParam;
import com.tzld.piaoquan.ad.engine.commons.param.RankRecommendRequestParam;
import com.tzld.piaoquan.ad.engine.commons.redis.AlgorithmRedisHelper;
import com.tzld.piaoquan.ad.engine.service.score.RankService;
import com.tzld.piaoquan.ad.engine.service.score.deprecated.BidRankRecommendRequestParam;
import com.tzld.piaoquan.ad.engine.service.user.UserService;
import com.tzld.piaoquan.recommend.feature.domain.ad.base.AdRankItem;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

@RestController
@RequestMapping("/recommend")
public class AdRecommendController {

    private static final List<String> ECPM_FACTOR_KEYS = Arrays.asList(
            "modelCtcvrScore", "bid", "fRankCoefficient", "rcRankCoefficient", "bidCoefficient", "ecpm");

    private final static Logger log = LoggerFactory.getLogger(AdRecommendController.class);
    @Autowired
    @Qualifier("rankServiceImpl")
    RankService rankService;

    @Autowired
    private UserService userService;

    @RequestMapping("/top1/basic")
    public Map<String, Object> adRecommendTop1Basic(@RequestBody RankRecommendRequestParam request) {
        Map<String, Object> map = new HashMap<>();
        if (CollectionUtils.isEmpty(request.getAdIdList())) {
            map.put("code", "1");
            map.put("msg", "score error");
            return map;
        }
        try {
            AdRankItem rankResult = rankService.adItemRank(request);
            if (Objects.nonNull(rankResult)) {
                map.put("code", "0");
                map.put("msg", "success");
                Map<String, Object> contentMap = new HashMap<>();
                contentMap.put("adId", rankResult.getAdId());
                contentMap.put("adScore", rankResult.getScore());
                Double ctcvrScore = rankResult.getScoreMap().get("ctcvrScore");
                if (ctcvrScore != null && ctcvrScore > 0) {
                    contentMap.put("ctcvrScore", ctcvrScore);
                    if (rankResult.getExt().get("ecpm") != null) {
                        contentMap.put("ecpm", rankResult.getExt().get("ecpm"));
                    }
                    if (rankResult.getExt().get("filterEcpm") != null) {
                        contentMap.put("filterEcpm", rankResult.getExt().get("filterEcpm"));
                    }
                    if (rankResult.getExt().get("correctionFactor") != null) {
                        contentMap.put("revisedBid", ctcvrScore * rankResult.getCpa() * (double) rankResult.getExt().get("correctionFactor"));
                    } else {
                        contentMap.put("revisedBid", ctcvrScore * rankResult.getCpa());
                    }
                } else {
                    contentMap.put("revisedBid", rankResult.getCpm() / 1000);
                }
                // 883 会将实际 eCPM 计算项全部写入 scoreMap；条件透出可保持其他策略的返回结构不变。
                if (rankResult.getScoreMap().containsKey("fRankCoefficient")
                        && rankResult.getScoreMap().containsKey("rcRankCoefficient")
                        && rankResult.getScoreMap().containsKey("bidCoefficient")) {
                    for (String key : ECPM_FACTOR_KEYS) {
                        if (rankResult.getScoreMap().containsKey(key)) {
                            contentMap.put(key, rankResult.getScoreMap().get(key));
                        }
                    }
                }
                List<String> participateCompetitionType = new ArrayList<>();
                participateCompetitionType.add("engine");
                if (rankResult.getExt().get("isGuaranteed") != null && rankResult.getExt().get("isGuaranteed").equals(true)) {
                    contentMap.put("type", GuaranteedTypeEnum.IS_GUARANTEED.getType());
                } else if (rankResult.getExt().containsKey("isHotRank") && Boolean.TRUE.equals(rankResult.getExt().get("isHotRank"))) {
                    contentMap.put("type", 2);
                    participateCompetitionType.add("weight");
                } else {
                    contentMap.put("type", GuaranteedTypeEnum.NOT_GUARANTEED.getType());
                }
                if (rankResult.getExt().containsKey("isGuaranteeType") && (boolean) rankResult.getExt().get("isGuaranteeType")) {
                    participateCompetitionType.add("guarantee");
                }
                contentMap.put("participateCompetitionType", StringUtils.join(participateCompetitionType, ","));
                contentMap.put("coefficientRate", rankResult.getExt().get("coefficientRate"));
                map.put("content", contentMap);
                return map;
            }
        } catch (Exception e) {
            log.error("模型排序异常: ", e);
        }

        map.put("code", "1");
        map.put("msg", "score error");
        return map;
    }

    @RequestMapping("/top1/video/ad/thompson")
    public Map<String, Object> adRecommendTop1VideoAdThompson(@RequestBody RankRecommendRequestParam request) {
        AdRankItem rankResult = rankService.adItemRankWithVideoAdThompson(request);
        HashMap map = new HashMap();
        map.put("code", "0");
        map.put("msg", "success");
        HashMap contentMap = new HashMap<>();
        contentMap.put("adId", rankResult.getAdId());
        contentMap.put("adScore", rankResult.getScore());
        map.put("content", contentMap);
        return map;
    }

    @RequestMapping("/top1/bid/basic")
    public Map<String, Object> adRecommendTop1BidBasic(@RequestBody BidRankRecommendRequestParam request) {
        AdPlatformCreativeDTO rankResult = rankService.adBidRank(request);
        HashMap map = new HashMap();
        map.put("code", "0");
        map.put("msg", "success");
        map.put("content", rankResult);
        return map;
    }

    @RequestMapping("/top1/bid/new/pid")
    public Map<String, Object> adRecommendTop1BidNewPid(@RequestBody BidRankRecommendRequestParam request) {
        AdPlatformCreativeDTO rankResult = rankService.adBidRankNewPid(request);
        HashMap map = new HashMap();
        map.put("code", "0");
        map.put("msg", "success");
        map.put("content", rankResult);
        return map;
    }

    @RequestMapping("/layer")
    public Map<String, Object> getMidWithLayer(@RequestBody LayerParam request) {
        Map<String, Object> map = new HashMap<>();
        if (request == null || StringUtils.isEmpty(request.getMid())) {
            map.put("code", "1");
            map.put("msg", "mid is null");
            return map;
        }
        map.put("code", "0");
        map.put("msg", "success");
        Map<String, String> userLayer = userService.getUserLayer(request.getMid());
        map.put("content", userLayer);
        return map;
    }


}
