package com.tzld.piaoquan.recommend.server.service;

import com.google.common.collect.Lists;
import com.google.common.reflect.TypeToken;
import com.tzld.piaoquan.recommend.server.client.ModelType;
import com.tzld.piaoquan.recommend.server.common.base.RankItem;
import com.tzld.piaoquan.recommend.server.gen.common.Result;
import com.tzld.piaoquan.recommend.server.gen.model.ScoreRequest;
import com.tzld.piaoquan.recommend.server.gen.model.ScoreResponse;
import com.tzld.piaoquan.recommend.server.service.score.ScorerUtils;
import com.tzld.piaoquan.recommend.server.util.JSONUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author dyp
 */
@Service
@Slf4j
public class ModelService {

    @Qualifier("featureRedisTemplate")
    @Autowired
    private RedisTemplate<String, String> featureRedisTemplate;

    private final Map<String, String> modelNameMap = new HashMap<>();

    @PostConstruct
    public void init() {
        modelNameMap.put("VlogShareLRScorer", ModelType.STR.getKey());
    }

    /**
     * workaround 广告调用返回分数
     * <p>
     * 因为是重复代码，尽量保持不变
     */
    public ScoreResponse score(ScoreRequest request) {

        Map<String, String> userFeatureMap = new HashMap<>();
        if (request.getMid() != null && !request.getMid().isEmpty()) {
            String midKey = "user_info_4video_" + request.getMid();
            String userFeatureStr = featureRedisTemplate.opsForValue().get(midKey);
            if (userFeatureStr != null) {
                try {
                    userFeatureMap = JSONUtils.fromJson(userFeatureStr,
                            new TypeToken<Map<String, String>>() {
                            },
                            userFeatureMap);
                } catch (Exception e) {
                    log.error(String.format("parse user json is wrong in {} with {}",
                            this.getClass().getSimpleName(), e));
                }
            } else {
                userFeatureMap = new HashMap<>();
//                return ScoreResponse.newBuilder()
//                        .setResult(Result.newBuilder().setCode(1))
//                        .build();
            }
        }
        final Set<String> userFeatureSet = new HashSet<>(Arrays.asList(
                "machineinfo_brand", "machineinfo_model", "machineinfo_platform", "machineinfo_system",
                "u_1day_exp_cnt", "u_1day_click_cnt", "u_1day_share_cnt", "u_1day_return_cnt",
                "u_ctr_1day", "u_str_1day", "u_rov_1day", "u_ros_1day",
                "u_3day_exp_cnt", "u_3day_click_cnt", "u_3day_share_cnt", "u_3day_return_cnt",
                "u_ctr_3day", "u_str_3day", "u_rov_3day", "u_ros_3day"
        ));
        Iterator<Map.Entry<String, String>> iterator = userFeatureMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            if (!userFeatureSet.contains(entry.getKey())) {
                // 删除键值对
                iterator.remove();
            }
        }


        final Set<String> itemFeatureSet = new HashSet<>(Arrays.asList(
                "total_time", "play_count_total",
                "i_1day_exp_cnt", "i_1day_click_cnt", "i_1day_share_cnt", "i_1day_return_cnt",
                "i_ctr_1day", "i_str_1day", "i_rov_1day", "i_ros_1day",
                "i_3day_exp_cnt", "i_3day_click_cnt", "i_3day_share_cnt", "i_3day_return_cnt",
                "i_ctr_3day", "i_str_3day", "i_rov_3day", "i_ros_3day"
        ));

        List<RankItem> rankItems = Lists.newArrayList(new RankItem(request.getVideoId()));
        List<Long> videoIds = Lists.newArrayList(request.getVideoId());
        List<String> videoFeatureKeys = videoIds.stream().map(r -> "video_info_" + r)
                .collect(Collectors.toList());
        List<String> videoFeatures = featureRedisTemplate.opsForValue().multiGet(videoFeatureKeys);
        if (videoFeatures != null) {
            for (int i = 0; i < videoFeatures.size(); ++i) {
                String vF = videoFeatures.get(i);
                Map<String, String> vfMap = new HashMap<>();
                if (vF == null) {
                    continue;
                }
                try {
                    vfMap = JSONUtils.fromJson(vF, new TypeToken<Map<String, String>>() {
                    }, vfMap);
                    Iterator<Map.Entry<String, String>> iteratorIn = vfMap.entrySet().iterator();
                    while (iteratorIn.hasNext()) {
                        Map.Entry<String, String> entry = iteratorIn.next();
                        if (!itemFeatureSet.contains(entry.getKey())) {
                            // 删除键值对
                            iteratorIn.remove();
                        }
                    }
                    // rankItems.get(i).setFeatureMap(vfMap);
                } catch (Exception e) {
                    log.error(String.format("parse video json is wrong in {} with {}",
                            this.getClass().getSimpleName(), e));
                }
            }
        }

        // Map<String, String> sceneFeatureMap = this.getSceneFeature(request);
        Map<String, Float> sceneFeatureMap = new HashMap<>(0);
        Map<String, Float> userMap = new HashMap<>(0);

        List<RankItem> result = ScorerUtils.getScorerPipeline(ScorerUtils.VIDEO_SCORE_CONF_FOR_AD)
                .scoring(sceneFeatureMap, userMap, rankItems);

        if (CollectionUtils.isEmpty(result)) {
            return ScoreResponse.newBuilder()
                    .setResult(Result.newBuilder().setCode(1))
                    .build();
        }
        Map<String, Double> score = new HashMap<>();
        score.put(ModelType.STR.getKey(), result.get(0).getScoreStr());
        score.put(ModelType.ROS.getKey(), result.get(0).getScoreRos());

        return ScoreResponse.newBuilder()
                .setResult(Result.newBuilder().setCode(1))
                .putAllScore(score)
                .build();
//        return ScoreResponse.newBuilder()
//                .setResult(Result.newBuilder().setCode(1))
//                .putAllScore(CommonCollectionUtils.toMap(result.get(0).getRankerScore().entrySet(),
//                        e -> modelNameMap.containsKey(e.getKey())
//                                ? modelNameMap.get(e.getKey())
//                                : e.getKey(),
//                        e -> e.getValue()))
//                .build();
    }

    private Map<String, String> getSceneFeature(ScoreRequest request) {
        Map<String, String> sceneFeatureMap = new HashMap<>();
        String provinceCn = request.getProvince();
        provinceCn = provinceCn.replaceAll("省$", "");
        sceneFeatureMap.put("ctx_region", provinceCn);
        String city = request.getCity();
        if ("台北市".equals(city) |
                "高雄市".equals(city) |
                "台中市".equals(city) |
                "桃园市".equals(city) |
                "新北市".equals(city) |
                "台南市".equals(city) |
                "基隆市".equals(city) |
                "吉林市".equals(city) |
                "新竹市".equals(city) |
                "嘉义市".equals(city)
        ) {
        } else {
            city = city.replaceAll("市$", "");
        }
        sceneFeatureMap.put("ctx_city", city);

        Calendar calendar = Calendar.getInstance();
        sceneFeatureMap.put("ctx_week", (calendar.get(Calendar.DAY_OF_WEEK) + 6) % 7 + "");
        sceneFeatureMap.put("ctx_hour", new SimpleDateFormat("HH").format(calendar.getTime()));

        return sceneFeatureMap;
    }
}
