package com.tanpu.community.service;

import com.tanpu.common.util.JsonUtil;
import com.tanpu.community.api.beans.qo.ThemeAnalysDO;
import com.tanpu.community.api.beans.resp.PythonResponse;
import com.tanpu.community.dao.entity.community.ThemeEntity;
import com.tanpu.community.util.BizUtils;
import com.tanpu.community.util.ConvertUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

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

@Slf4j
@Service
public class RecommendService {

    @Value("${recommend.python.enable}")
    public String enablePython;


    @Value("${recommend.python.url}")
    public String pythonUrl;
    @Value("${recommend.ratio.hot}")
    public Integer hotRatio;
    @Value("${recommend.ratio.new}")
    public Integer newRatio;
    @Value("${recommend.ratio.python}")
    public Integer pythonRatio;


    @Autowired
    private RankService rankService;

    @Autowired
    private ThemeService themeService;


    // 最新
    private List<ThemeAnalysDO> recentThemeList = new ArrayList<>();
    // 推荐
    private Map<String, List<String>> recommondList = new HashMap<>();

    public List<String> getRecommendThemes(Integer pageStart, Integer pageSize, String userId, List<String> excludeIds) {
        // 最热话题,筛掉用户发表的 & 最近看过的 & excludeIds
        List<String> hotThemeIds = rankService.getHotestThemes().stream()
                .filter(theme -> {
                    return !excludeIds.contains(theme.getThemeId()) && !userId.equals(theme.getAuthorId());
                })
                .map(ThemeAnalysDO::getThemeId).collect(Collectors.toList());
        hotThemeIds = BizUtils.subList(hotThemeIds, pageStart, pageSize);

        //最新话题,筛掉用户发表的 & 最近看过的 & excludeIds
        List<String> newThemeIds = getNewestThemes().stream()
                .filter(theme -> {
                    return !excludeIds.contains(theme.getThemeId()) && !userId.equals(theme.getAuthorId());
                })
                .map(ThemeAnalysDO::getThemeId).collect(Collectors.toList());
        newThemeIds = BizUtils.subList(newThemeIds, pageStart, pageSize);

        //推荐话题
        List<String> recThemeIds = getPythonRecommendList(userId).stream()
                .filter(id -> {
                    return !excludeIds.contains(id);
                }).collect(Collectors.toList());
        recThemeIds = BizUtils.subList(recThemeIds, pageStart, pageSize);

        // merge
        return mergeRecommend(hotThemeIds, newThemeIds, recThemeIds);
    }

    // 获取最新话题
    public List<ThemeAnalysDO> getNewestThemes() {
        if (recentThemeList.size() == 0) {
            refreshNewestThemes();
        }
        return recentThemeList;
    }

    // 从数据库查询最新主题
    public void refreshNewestThemes() {
        List<ThemeEntity> themeEntities = themeService.queryLatestThemes(100);
        this.recentThemeList = ConvertUtil.themeEntityToAnalysDOs(themeEntities);
    }

    //查询python计算推荐列表
    public List<String> getPythonRecommendList(String userId) {
        if (recommondList.containsKey(userId)) {
            return recommondList.get(userId);
        } else {
            return refreshPythonRecommendList(userId);
        }
    }

    //HTTP查询python推荐主题 python返回最多50个
    public List<String> refreshPythonRecommendList(String userId) {
        if (!"true".equals(enablePython)) {
            return Collections.emptyList();
        }
        RestTemplate restTemplate = new RestTemplate();
        HashMap<String, String> param = new HashMap<>();
        param.put("user_id", userId);
        try {
            String response = restTemplate.getForObject(pythonUrl, String.class, param);
            PythonResponse pythonResponse = JsonUtil.toBean(response, PythonResponse.class);
            recommondList.put(userId, pythonResponse.getAttributes());
            return pythonResponse.getAttributes();
        } catch (Exception e) {
            log.error("调用python失败");
            return Collections.emptyList();
        }


    }

    // 合并,去重
    private List<String> mergeList(List<String> hotThemeIds, List<String> newThemeIds, List<String> recThemeIds, Set<String> set) {
        ArrayList<String> result = new ArrayList<>();
        // 3个集合的指针
        Integer hotIdx = 0;
        Integer newIdx = 0;
        Integer recIdx = 0;
        while (hotThemeIds.size() > hotIdx || newThemeIds.size() > newIdx || recThemeIds.size() > recIdx) {
            int hotTimes = hotRatio;
            int newTimes = newRatio;
            int recTimes = pythonRatio;
            String id;
            while (newTimes > 0 && newThemeIds.size() > newIdx) {
                id = newThemeIds.get(newIdx);
                if (!set.contains(id)) {
                    result.add(id);
                    set.add(id);
                }

                newIdx++;
                newTimes--;
            }

            while (hotTimes > 0 && hotThemeIds.size() > hotIdx) {
                id = hotThemeIds.get(hotIdx);
                if (!set.contains(id)) {
                    result.add(id);
                    set.add(id);
                }

                hotIdx++;
                hotTimes--;
            }

            while (recTimes > 0 && recThemeIds.size() > recIdx) {
                id = recThemeIds.get(recIdx);
                if (!set.contains(id)) {
                    result.add(id);
                    set.add(id);
                }

                recIdx++;
                recTimes--;
            }

        }
        return result;
    }

    // 按照 6,3,1的比例
    private List<String> mergeRecommend(List<String> hotIds, List<String> newestIds, List<String> recmdIds) {
        List<String> retList = new ArrayList<>();
        int round = 0;
        while (true) {

            int newestStart = round * newRatio;
            int hotStart = round * hotRatio;
            int recmdStart = round * pythonRatio;
            if (hotStart >= hotIds.size() && newestStart >= newestIds.size() && recmdStart >= recmdIds.size()) {
                break;
            }
            retList.addAll(BizUtils.subList(newestIds, newestStart, newRatio));
            retList.addAll(BizUtils.subList(hotIds, hotStart, hotRatio));
            retList.addAll(BizUtils.subList(recmdIds, recmdStart, pythonRatio));

            round++;
        }
        return retList;
    }


}