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

import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
import com.google.common.base.Stopwatch;
import com.tzld.piaoquan.recommend.server.repository.WxVideoTagRel;
import com.tzld.piaoquan.recommend.server.repository.WxVideoTagRelRepository;
import com.tzld.piaoquan.recommend.server.util.CommonCollectionUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author sunxy
 */
@Service
public class VideoCityFilterService {

//    private final Logger logger = Logger.getLogger(VideoCityFilterService.class.getName());

    private final Logger logger = LoggerFactory.getLogger(VideoCityFilterService.class);

//    @Value("${video.filter.city.tagid.json:}")
//    private String videoFilterTagIdJson;

    @ApolloJsonValue("${video.filter.city.tagid.json:{}}")
    private Map<String, List<Long>> videoFilterCityTagIdMap;
    @Value("#{'${block.hotscenetype.list:}'.split(',')}")
    private Set<Long> excludeScenes;
    @Value("${securityAbExpCode:625}")
    private String securityAbExpCode;
    @Resource
    private WxVideoTagRelRepository wxVideoTagRelRepository;
    private Map<String, Set<Long>> videoTagCache = new ConcurrentHashMap<>();

    @PostConstruct
    public void init() {
        initCacheByValue();
    }

    @Scheduled(cron = "0 0 0/2 * * ? ")
    public void cornInit() {
        initCacheByValue();
    }

    private void initCacheByValue() {
        Stopwatch stopwatch = Stopwatch.createStarted();
        if (Objects.isNull(videoFilterCityTagIdMap) || videoFilterCityTagIdMap.isEmpty()) {
            videoTagCache = new ConcurrentHashMap<>();
            return;
        }
        Map<String, Set<Long>> tmp = new ConcurrentHashMap<>();
        for (Map.Entry<String, List<Long>> entry : videoFilterCityTagIdMap.entrySet()) {
            if (Objects.isNull(entry)) {
                continue;
            }
            String cityCode = entry.getKey();
            List<Long> tagList = entry.getValue();
            if (Objects.isNull(cityCode) || Objects.isNull(tagList) || tagList.isEmpty()) {
                continue;
            }
            Set<Long> videosByTag = wxVideoTagRelRepository.findAllByTagIdIn(tagList).stream()
                    .map(WxVideoTagRel::getVideoId).collect(Collectors.toSet());
            tmp.put(cityCode, videosByTag);
        }
        videoTagCache = tmp;
        logger.info("initCacheByValue videoTagCache.size = {} execute time = {}", videoTagCache.size(), stopwatch.stop().elapsed(TimeUnit.MILLISECONDS));

    }

    public List<Long> filterVideosByCity(List<Long> videoIds, Set<String> abExpCodes,
                                         Long hotSceneType, String cityCode) {
        if (CollectionUtils.isEmpty(videoIds) || StringUtils.isBlank(cityCode) || hotSceneType == null) {
            return videoIds;
        }
        if (CollectionUtils.isNotEmpty(excludeScenes) && excludeScenes.contains(hotSceneType)) {
            return videoIds;
        }
        if (!CommonCollectionUtils.contains(abExpCodes, securityAbExpCode)) {
            return videoIds;
        }
        List<Long> tagIdList = videoFilterCityTagIdMap.get(cityCode);
        if (tagIdList == null || tagIdList.isEmpty()) {
            return videoIds;
        }

        Set<Long> riskCityVideoIdSet = videoTagCache.get(cityCode);
        if (riskCityVideoIdSet == null || riskCityVideoIdSet.isEmpty()) {
            return videoIds;
        }

        videoIds.removeIf(riskCityVideoIdSet::contains);

        return videoIds;
    }

}
