package com.tzld.piaoquan.recommend.server.implement.recall;


import com.tzld.piaoquan.recommend.server.framework.candidiate.Candidate;
import com.tzld.piaoquan.recommend.server.framework.common.User;
import com.tzld.piaoquan.recommend.server.framework.recaller.AbstractFilter;
import com.tzld.piaoquan.recommend.server.framework.recaller.FilterConfigInfo;
import com.tzld.piaoquan.recommend.server.gen.recommend.RecommendRequest;
import com.tzld.piaoquan.recommend.server.model.Video;
import com.tzld.piaoquan.recommend.server.service.ServiceBeanFactory;
import com.tzld.piaoquan.recommend.server.service.SpringContextHolder;
import com.tzld.piaoquan.recommend.server.service.filter.VideoCityFilterService;
import com.tzld.piaoquan.recommend.server.service.filter.strategy.VideoView;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class ViewedHistoryFilter extends AbstractFilter<Video> {

    private final VideoCityFilterService videoCityFilterService;

    protected Set<String> historySet;

    private final RedisTemplate<String, String> redisTemplate;

    private final MongoTemplate mongoTemplate;

    private final String keyFormat = "user:exclude:videoidset:%s";

    public ViewedHistoryFilter(FilterConfigInfo filterConfigInfo,
                               RecommendRequest recommendRequest,
                               User user) {
        super(filterConfigInfo, recommendRequest, user);
        mongoTemplate = ServiceBeanFactory.getBean(MongoTemplate.class);
        redisTemplate = SpringContextHolder.getBean("filterRedisTemplate", RedisTemplate.class);
        historySet = this.loadUserHistory(user);
        if (historySet == null) {
            historySet = new HashSet<>();
        }
        videoCityFilterService = SpringContextHolder.getBean(VideoCityFilterService.class);

    }

    @Override
    public void doFilter(Candidate candidate, List<Video> videoList) {
        if (CollectionUtils.isEmpty(videoList)) {
            return;
        }
        videoList.removeIf(video -> this.historySet.contains(String.valueOf(video.getVideoId())));
        if (CollectionUtils.isEmpty(videoList)) {
            return;
        }
        List<Long> filterVideosByCity = videoCityFilterService.filterVideosByCity(videoList.stream().map(Video::getVideoId).collect(Collectors.toList()),
                new HashSet<>(requestContext.getAbExpCodeList()), requestContext.getHotSceneType(), requestContext.getCityCode());
        Set<Long> filterVideosSet = new HashSet<>(filterVideosByCity);
        videoList.removeIf(video -> !filterVideosSet.contains(video.getVideoId()));
    }


    public Set<String> loadUserHistory(User user) {
        String userid = StringUtils.isNotBlank(user.getUid()) ? user.getUid() : user.getMid();
        if (StringUtils.isBlank(userid)) {
            return new HashSet<>();
        }

        String key = String.format(keyFormat, userid);
        Set<String> viewedVideoIds = redisTemplate.opsForSet().members(key);
        if (CollectionUtils.isEmpty(viewedVideoIds)) {
            viewedVideoIds = new HashSet<>();
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            // 从mongodb中取曝光记录
            Criteria criteriatime = new Criteria();
            criteriatime.and("uid").is(userid);
            Query query = new Query();
            query.addCriteria(criteriatime);
            //查新库
            List<VideoView> list = mongoTemplate.find(query, VideoView.class);
            //限制最多10000条
            if (Objects.nonNull(list) && list.size() > 10000) {
                list = list.subList(list.size() - 10000, list.size());
            }
            if (CollectionUtils.isNotEmpty(list)) {
                viewedVideoIds.addAll(list.stream().map(VideoView::getVideoId).map(String::valueOf).collect(Collectors.toSet()));
            } else {
                // 避免缓存击穿
                viewedVideoIds.add("-1");
            }
            stopWatch.stop();

            redisTemplate.opsForSet().add(key, viewedVideoIds.toArray(new String[0]));
            redisTemplate.expire(key, 1, TimeUnit.DAYS);
        }

        return viewedVideoIds;
    }







}
