package com.tzld.piaoquan.ad.engine.commons.redis;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

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

@Component
public class AlgorithmRedisHelper {
    private final static Logger log = LoggerFactory.getLogger(AlgorithmRedisHelper.class);

    private final static Long AD_FILTER_DEFAULT_EXPIRE_TIME = 30L * 24 * 60 * 60; // 排除人群（广告、计划）默认设置30天,单位秒
    private final static Long AD_FILTER_DELAY_QUEUE_EXPIRETIME = 5L * 60 * 1000; // 排除人群优化默认设置5分钟,单位毫秒
    private final static Long AD_FILTER_DEFAULT_USER_BEHAVIOR_EXPIRETIME = 1L * 24 * 60 * 60; // 排除人群优化默认设置1天,单位秒
    @Resource(name = "algorithmRedisTemplate")
    private RedisTemplate<String, String> redisTemplate;

    public boolean containsKey(String key) {
        return redisTemplate.hasKey(key);
    }

    public Double zScore(String key, String value) {
        return redisTemplate.opsForZSet().score(key, value);
    }

    public String getString(String key) {
        Object obj = redisTemplate.opsForValue().get(key);
        return Objects.isNull(obj) ? null : obj.toString();
    }

    public List<String> getValues(List<String> keys) {
        List<String> values = redisTemplate.opsForValue().multiGet(keys);
        return CollectionUtils.isEmpty(values) ? new ArrayList<>(keys.size()) : values;
    }


    public Long getLong(String key) {
        long longVal = 0L;
        Object obj = redisTemplate.opsForValue().get(key);
        if (Objects.nonNull(obj)) {
            try {
                longVal = Long.parseLong(obj.toString());
            } catch (Exception e) {
                e.printStackTrace();
                return longVal;
            }

        }
        return longVal;
    }

    public void setValueWithExpire(String key, String value, Date date) {
        long expireTime;
        if (date != null) {
            expireTime = (date.getTime() - System.currentTimeMillis()) / 1000;
            if (expireTime < 0) { // 过期时间有问题，或者小于当前时间
                expireTime = AD_FILTER_DEFAULT_USER_BEHAVIOR_EXPIRETIME;
            }
        } else {
            expireTime = AD_FILTER_DEFAULT_USER_BEHAVIOR_EXPIRETIME;
        }
        redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
    }

    public void setIncrementValue(String key, long value, Date date) {
        Long expireTime;
        if (date != null) {
            expireTime = (date.getTime() - System.currentTimeMillis()) / 1000;
            // 过期时间有问题，或者小于当前时间
            if (expireTime < 0) {
                expireTime = AD_FILTER_DEFAULT_EXPIRE_TIME;
            }
        } else { // date为null
            expireTime = AD_FILTER_DEFAULT_EXPIRE_TIME;
        }
        // 只在第一次进行设置过期时间
        if (!containsKey(key)) {
            redisTemplate.opsForValue().increment(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
        } else {
            redisTemplate.opsForValue().increment(key, value);
        }
    }

    public void setIncrementValue(String key, double value, Date date) {
        Long expireTime;
        if (date != null) {
            expireTime = (date.getTime() - System.currentTimeMillis()) / 1000;
            // 过期时间有问题，或者小于当前时间
            if (expireTime < 0) {
                expireTime = AD_FILTER_DEFAULT_EXPIRE_TIME;
            }
        } else { // date为null
            expireTime = AD_FILTER_DEFAULT_EXPIRE_TIME;
        }
        // 只在第一次进行设置过期时间
        if (!containsKey(key)) {
            redisTemplate.opsForValue().increment(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
        } else {
            redisTemplate.opsForValue().increment(key, value);
        }
    }

    public int getInteger(String key) {
        Object obj = redisTemplate.opsForValue().get(key);
        if (Objects.isNull(obj)) {
            return 0;
        }
        return Integer.valueOf(obj.toString());
    }

    public void putDelayQueueMsg(String key, String value) {
        redisTemplate.opsForZSet().add(key, value, System.currentTimeMillis() + AD_FILTER_DELAY_QUEUE_EXPIRETIME);
    }

    public Set<String> processDelayQueue(String key) {
        long currentTimeMillis = System.currentTimeMillis();
        Set<String> values = redisTemplate.opsForZSet().rangeByScore(key, 0, currentTimeMillis);
        if (!CollectionUtils.isEmpty(values)) {
            redisTemplate.opsForZSet().removeRangeByScore(key, 0, currentTimeMillis);
        }
        return values;
    }

    public void addVal(String key, String val) {
        redisTemplate.opsForValue().set(key, val);
    }

    public Long getKeyExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    public void expire(String key, Long time) {
        redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    public Long countExistingKeys(List<String> keys) {
        return redisTemplate.countExistingKeys(keys);
    }

    public boolean del(String key) {
        return redisTemplate.delete(key);
    }

    public boolean set(String key, String value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                redisTemplate.opsForValue().set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Redis 分布式锁
     *
     * @param key        锁键
     * @param value      锁值，可以为随机数或者 UUID 等唯一标识符
     * @param expireTime 锁过期时间，单位为秒
     * @return true：获取锁成功，false：获取锁失败
     */
    public boolean tryLock(String key, String value, long expireTime) {
        Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, TimeUnit.SECONDS);
        if (result != null && result) {
            // 获取锁成功
            return true;
        }
        return false;
    }

    public void listLeftPush(String key, String value) {
        redisTemplate.opsForList().leftPush(key, value);

    }

    public String listRightPop(String key) {
        return redisTemplate.opsForList().rightPop(key);
    }

    public Double getDouble(String key) {
        String val = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(val)) {
            return Double.valueOf(val);
        }
        return null;
    }

    public String get(String key) {
        String val = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(val)) {
            return val;
        }
        return null;
    }

    public List<String> mget(Collection<String> keys) {
        if (CollectionUtils.isEmpty(keys)) {
            return new ArrayList<>();
        }
        return redisTemplate.opsForValue().multiGet(keys);
    }
}
