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

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Lists;
import com.tzld.piaoquan.recommend.server.repository.WxVideoTagRel;
import com.tzld.piaoquan.recommend.server.repository.WxVideoTagRelRepository;
import com.tzld.piaoquan.recommend.server.service.filter.FilterParam;
import com.tzld.piaoquan.recommend.server.service.filter.FilterStrategy;
import com.tzld.piaoquan.recommend.server.util.CommonCollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author dyp
 */
@Component
@Slf4j
public class TagStrategy implements FilterStrategy {

    @Autowired
    private WxVideoTagRelRepository repository;

    @Value("${video.filter.tagids:}")
    private String videoFilterTagIds;

    // 内存持久保存不淘汰
    private LoadingCache<Long, Set<Long>> videoTagCache = CacheBuilder.newBuilder()
            .maximumSize(100)
            .refreshAfterWrite(60, TimeUnit.SECONDS)
            .expireAfterWrite(60, TimeUnit.SECONDS)
            .expireAfterAccess(60, TimeUnit.SECONDS)
            .build(new CacheLoader<Long, Set<Long>>() {
                @Override
                public Set<Long> load(Long tagId) {
                    List<WxVideoTagRel> rels = repository.findAllByTagId(tagId);
                    return CommonCollectionUtils.toSet(rels, WxVideoTagRel::getVideoId);
                }
            });

    @PostConstruct
    public void init() {
        if (StringUtils.isNotBlank(videoFilterTagIds)) {
            // 只有涉政标签，用循环简化代码
            String[] tags = videoFilterTagIds.split(",");
            for (String tag : tags) {
                if (StringUtils.isBlank(tag)) {
                    continue;
                }
                videoTagCache.getUnchecked(NumberUtils.toLong(tag));
            }
        }
    }

    @Override
    public List<Long> filter(FilterParam param) {
        // TODO 主要是涉政标签
        if (param == null
                || CollectionUtils.isEmpty(param.getVideoIds())) {
            return Collections.emptyList();
        }


        List<Long> tagIds = new ArrayList<>();
        if (StringUtils.isBlank(videoFilterTagIds)) {
            return param.getVideoIds();
        }
        String[] tags = videoFilterTagIds.split(",");
        for (String tag : tags) {
            if (Objects.isNull(tag) || Objects.equals("", tag)) {
                continue;
            }
            tagIds.add(Long.parseLong(tag));
        }

        Set<Long> retainVideoIds = new LinkedHashSet<>();
        Iterator<Long> iterator = param.getVideoIds().iterator();
        while (iterator.hasNext()) {
            Long videoId = iterator.next();
            for (Long tagId : tagIds) {
                if (!hasVideoRelTagId(videoId, tagId)) {
                    retainVideoIds.add(videoId);
                }
            }
        }

        if (CollectionUtils.isEmpty(retainVideoIds)) {
            return Collections.emptyList();
        }

        return Lists.newArrayList(retainVideoIds);
    }

    private boolean hasVideoRelTagId(Long videoId, Long tagId) {
        if (Objects.isNull(videoId) || videoId <= 0L || Objects.isNull(tagId) || tagId <= 0L) {
            return false;
        }
        Set<Long> videos = videoTagCache.getUnchecked(tagId);
        if (CollectionUtils.isEmpty(videos)) {
            return false;
        }
        return videos.contains(videoId);
    }

}
