package com.lovenav.service.serviceImpl;

import com.lovenav.service.RedisService;
import com.lovenav.utils.RedisKeyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.redis.core.*;
import javax.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import java.util.*;


@Transactional
@Service("redisService")
public class RedisServiceImpl implements RedisService {

    private Logger logger = LoggerFactory.getLogger(RedisService.class);

    /**
     * 取热搜前几名返回
     */
    private static final Integer HOT_SEARCH_NUMBER = 9;

    /**
     * 多少时间内的搜索记录胃热搜
     */
    private static final Long HOT_SEARCH_TIME = 30 * 24 * 60 * 60L;

    @Resource
    private  StringRedisTemplate stringRedisTemplate;

    //新增一条该userid用户在搜索栏的历史记录
    //searchkey 代表输入的关键词
    /**
     * 新增一条该userid用户在搜索栏的历史记录
     */
    public Long addSearchHistoryByUserId(String userId, String searchKey) {
        try{
            String redisKey = RedisKeyUtils.getSearchHistoryKey(userId);
            // 如果存在这个key
            boolean b = Boolean.TRUE.equals(stringRedisTemplate.hasKey(redisKey));
            if (b) {
                // 获取这个关键词hash的值，有就返回，没有就新增
                Object hk = stringRedisTemplate.opsForHash().get(redisKey, searchKey);
                if (hk != null) {
                    return 1L;
                }else{
                    stringRedisTemplate.opsForHash().put(redisKey, searchKey, "1");
                }
            }else{
                // 没有这个关键词就新增
                stringRedisTemplate.opsForHash().put(redisKey, searchKey, "1");
            }
            return 1L;
        }catch (Exception e){
            logger.error("redis发生异常，异常原因：",e);
            return 0L;
        }
    }

    /**
     * 删除个人历史数据
     */
    public Long delSearchHistoryByUserId(String userId, String searchKey) {
        try {
            String redisKey = RedisKeyUtils.getSearchHistoryKey(userId);
            // 删除这个用户的关键词记录
            return stringRedisTemplate.opsForHash().delete(redisKey, searchKey);
        }catch (Exception e){
            logger.error("redis发生异常，异常原因：",e);
            return 0L;
        }
    }

    /**
     * 获取个人历史数据列表
     */
    public List<String> getSearchHistoryByUserId(String userId) {
        try{
            List<String> stringList = null;
            String redisKey = RedisKeyUtils.getSearchHistoryKey(userId);
            // 判断存不存在
            boolean b = Boolean.TRUE.equals(stringRedisTemplate.hasKey(redisKey));
            if(b){
                stringList = new ArrayList<>();
                // 逐个扫描，ScanOptions.NONE为获取全部键对，ScanOptions.scanOptions().match("map1").build() 匹配获取键位map1的键值对,不能模糊匹配
                Cursor<Map.Entry<Object, Object>> cursor = stringRedisTemplate.opsForHash().scan(redisKey, ScanOptions.NONE);
                while (cursor.hasNext()) {
                    Map.Entry<Object, Object> map = cursor.next();
                    String key = map.getKey().toString();
                    stringList.add(key);
                }
                return stringList;
            }
            return null;
        }catch (Exception e){
            logger.error("redis发生异常，异常原因：",e);
            return null;
        }
    }

    /**
     * 根据searchKey搜索其相关最热的前十名 (如果searchKey为null空，则返回redis存储的前十最热词条)
     */
    public List<String> getHotList(String searchKey) {
        try {
            Long now = System.currentTimeMillis();
            List<String> result = new ArrayList<>();
            ZSetOperations<String, String> zSetOperations = stringRedisTemplate.opsForZSet();
            ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
            Set<String> value = zSetOperations.reverseRangeByScore(RedisKeyUtils.getHotSearchKey(), 0, Double.MAX_VALUE);
            //key不为空的时候 推荐相关的最热前十名
            if(StringUtils.isNotEmpty(searchKey)){
                for (String val : value) {
                    if (StringUtils.containsIgnoreCase(val, searchKey)) {
                        //只返回最热的前十名
                        if (result.size() > HOT_SEARCH_NUMBER) {
                            break;
                        }

                        Long time = Long.valueOf(Objects.requireNonNull(valueOperations.get("search:search-time:"+val)));
                        //返回最近一个月的数据
                        if ((now - time) < HOT_SEARCH_TIME) {
                            result.add(val);
                        } else {//时间超过一个月没搜索就把这个词热度归0
                            zSetOperations.add(RedisKeyUtils.getHotSearchKey(), val, 0);
                        }
                    }
                }
            }else{
                for (String val : value) {
                    //只返回最热的前十名
                    if (result.size() > HOT_SEARCH_NUMBER) {
                        break;
                    }
                    System.out.println(valueOperations.get(val));
                    Long time = Long.valueOf(Objects.requireNonNull(valueOperations.get("search:search-time:"+val)));
                    //返回最近一个月的数据
                    if ((now - time) < HOT_SEARCH_TIME) {
                        result.add(val);
                    } else {
                        //时间超过一个月没搜索就把这个词热度归0
                        zSetOperations.add(RedisKeyUtils.getHotSearchKey(), val, 0);
                    }
                }
            }
            return result;
        }catch (Exception e){
            logger.error("redis发生异常，异常原因：",e);
            return null;
        }
    }

    /**
     * 新增一条热词搜索记录，将用户输入的热词存储下来
     */
    public int incrementScoreByUserId(String searchKey) {
        Long now = System.currentTimeMillis();
        ZSetOperations<String, String> zSetOperations = stringRedisTemplate.opsForZSet();
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        List<String> title = new ArrayList<>();
        title.add(searchKey);
        for (int i = 0, length = title.size(); i < length; i++) {
            String tle = title.get(i);
            try {
                if (zSetOperations.score(RedisKeyUtils.getHotSearchKey(), tle) <= 0) {
                    zSetOperations.add(RedisKeyUtils.getHotSearchKey(), tle, 0);
                    valueOperations.set(RedisKeyUtils.getSearchTimeKey(tle), String.valueOf(now));
                }
            } catch (Exception e) {
                zSetOperations.add(RedisKeyUtils.getHotSearchKey(), tle, 0);
                valueOperations.set(RedisKeyUtils.getSearchTimeKey(tle), String.valueOf(now));
            }
        }
        return 1;
    }

    /**
     * 每次点击给相关词searchKey热度 +1
     */
    public Long incrementScore(String searchKey) {
        try{
            Long now = System.currentTimeMillis();
            ZSetOperations<String, String> zSetOperations = stringRedisTemplate.opsForZSet();
            ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
            // 没有的话就插入，有的话的直接更新；add是有就覆盖，没有就插入
            zSetOperations.incrementScore(RedisKeyUtils.getHotSearchKey(), searchKey, 1);
            valueOperations.getAndSet(RedisKeyUtils.getSearchTimeKey(searchKey), String.valueOf(now));

            return 1L;
        }catch (Exception e){
            logger.error("redis发生异常，异常原因：",e);
            return 0L;
        }
    }



}
