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

import com.tzld.piaoquan.recommend.server.model.Video;
import com.tzld.piaoquan.recommend.server.service.rank.RankParam;
import com.tzld.piaoquan.recommend.server.util.DateUtils;
import com.tzld.piaoquan.recommend.server.util.MathUtil;
import com.tzld.piaoquan.recommend.server.util.WeightRandom;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author sunxy
 */
public class RankProcessorInsert {
    public static void insertByTag(RankParam param, List<Video> rovList,
                                   Map<String, Map<String, String>> rulesMap) {
        if (CollectionUtils.isEmpty(rovList) || rulesMap == null || rulesMap.isEmpty()) {
            return;
        }
        String tagName = null, insertWeight = null;
        for (Map.Entry<String, Map<String, String>> entry : rulesMap.entrySet()) {
            Map<String, String> value = entry.getValue();

//            if ("小年".equals(entry.getKey())){
//                String provinceCn = param.getProvince();
//                if (provinceCn == null){
//                    provinceCn = "中国";
//                }else{
//                    provinceCn = provinceCn.replaceAll("省$", "");
//                }
//                boolean ifNorth = NORTHERN_PROVINCES.contains(provinceCn);
//                Calendar calendar = Calendar.getInstance();
//                String date = new SimpleDateFormat("yyyyMMdd").format(calendar.getTime());
//                if (ifNorth && date.compareTo("20240202")>0){
//                    continue;
//                }
//            }

            String insertDates = value.get("insert_date");
            String insertRules = value.get("insert");
            if (StringUtils.isBlank(insertDates) || StringUtils.isBlank(insertRules)) {
                continue;
            }
            String[] insertDateArr = insertDates.split(",");
            String[] insertWeights = insertRules.split(";");
            if (insertDateArr.length != insertWeights.length) {
                continue;
            }
            for (int i = 0; i < insertDateArr.length; i++) {
                String insertDate = insertDateArr[i];
                // 判断是否在允许强插的时间范围内
                boolean ifTimeRangeInNow = DateUtils.ifTimeRangeInNow(insertDate);
                if (ifTimeRangeInNow) {
                    tagName = entry.getKey();
                    insertWeight = insertWeights[i];
                    break;
                }
            }
            // 如果已经筛选出强插的tag以及对应权重，就不再继续遍历
            if (StringUtils.isNotBlank(tagName) && StringUtils.isNotBlank(insertWeight)) {
                break;
            }
        }

        final String finalTagName = tagName;

        // 判断是否前几个已经有该tag的视频了
        boolean isExistResultTagVideo = rovList.stream()
                .limit(param.getSize())
                .anyMatch(video -> video.getTags().contains(finalTagName));
        if (isExistResultTagVideo) {
            return;
        }

        // 获取需要插入的视频
        Video insertTagVideo = null;
        int tagVideoIndex = -1;
        for (int i = param.getSize(); i < rovList.size(); i++) {
            if (rovList.get(i).getTags().contains(finalTagName)) {
                insertTagVideo = rovList.get(i);
                tagVideoIndex = i;
                break;
            }
        }
        if (insertTagVideo == null) {
            return;
        }

        // 获取插入的权重
        String[] insertWeightArr = insertWeight.split(",");
        List<Double> insertWeightList = Arrays.stream(insertWeightArr)
                .map(Double::valueOf).collect(Collectors.toList());

        if (CollectionUtils.size(insertWeightList) != 5) {
            return;
        }
        Double showProbability = insertWeightList.get(0);
        double randomDouble = MathUtil.nextDouble(0, 1);
        if (randomDouble > showProbability) {
            // 没有命中强插规则
            return;
        }
        // 遍历权重，获取插入位置
        List<WeightRandom.ItemWithWeight<Integer>> items = new ArrayList<>(insertWeightList.size());
        for (int i = 1; i < insertWeightList.size(); i++) {
            WeightRandom.ItemWithWeight<Integer> itemWithWeight = new WeightRandom.ItemWithWeight<>(i, insertWeightList.get(i));
            items.add(itemWithWeight);
        }
        WeightRandom<Integer> integerWeightRandom = new WeightRandom<>(items);
        Integer insertIndex = integerWeightRandom.choose();
        if (insertIndex == null) {
            return;
        }
        // 删除原视频
        rovList.remove(tagVideoIndex);
        // 插入该视频到指定位置
        rovList.add(insertIndex - 1, insertTagVideo);

    }

}
