package com.ytpm.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class RedisService {
    @Autowired
    StringRedisTemplate stringRedisTemplate;


    @Resource(name = "stringRedisTemplate")
    ValueOperations<String, String> valOpsStr;

    @Autowired
    RedisTemplate<Object, Object> redisTemplate;

    @Autowired(required = false)
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        //序列化key值，防止key值前面乱码
        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setHashKeySerializer(stringSerializer);
        this.redisTemplate = redisTemplate;
    }

    @Resource(name = "redisTemplate")
    ValueOperations<Object, Object> valOpsObj;

    /**
     * 根据指定key获取String
     * @param key
     * @return
     */
    public String getStr(String key){
        return valOpsStr.get(key);
    }


    /**
     * 查询并获取key的有效时间
     */
    public Long getExpire(String key) {
        return valOpsObj.getOperations().getExpire(key, TimeUnit.MINUTES);
    }

    /**
     * 设置Str缓存
     * @param key
     * @param val
     */
    public void setStr(String key, String val){
        valOpsStr.set(key,val);
    }

    /**
     * 设置Str缓存 timeOut单位  毫秒
     * @param key
     * @param val
     */
    public void setTimeOutStr(String key, String val ,long timeOut){
        valOpsStr.set(key,val,timeOut, TimeUnit.MILLISECONDS);
    }

    /**
     * 判断是否存在key
     * @param key
     * @return
     */
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 设置Str缓存 timeOut单位  小时
     * @param key
     * @param val
     * @param timeOut
     */
    public void setTimeOutHoursStr(String key, String val ,long timeOut){
        valOpsStr.set(key,val,timeOut, TimeUnit.HOURS);
    }

    /**
     * 设置Str缓存 timeOut单位  分钟
     * @param key
     * @param val
     * @param timeOut
     */
    public void setTimeOutMinutesStr(String key, String val ,long timeOut){
        valOpsStr.set(key,val,timeOut, TimeUnit.MINUTES);
    }

    /**
     * 删除指定key
     * @param key
     */
    public void del(String key){
        stringRedisTemplate.delete(key);
    }

    /**
     * 设置指定key值的超时时间
     * @param key
     */
    public void expire(String key,long timeOut){
        TimeUnit timeUnit=TimeUnit.MILLISECONDS;
        stringRedisTemplate.expire(key,timeOut, timeUnit);
    }

    /**
     * 根据前缀批量删除
     * @param keysPrefix
     */
    public void delKeys(String keysPrefix){
        Set<String> set = stringRedisTemplate.keys(keysPrefix);
        stringRedisTemplate.delete(set);
    }



    /**
     * 根据指定o获取Object
     * @param o
     * @return
     */
    public Object getObj(Object o){
        return valOpsObj.get(o);
    }

    /**
     * 设置obj缓存
     * @param o1
     * @param o2
     */
    public void setObj(Object o1, Object o2){
        valOpsObj.set(o1, o2);
    }
    /**
     * 设置obj缓存
     * @param o1
     * @param o2
     */
    public void setObj(Object o1, Object o2,long timeout){
        valOpsObj.set(o1, o2,timeout);
    }


    /**
     * 删除Obj缓存
     * @param o
     */
    public void delObj(Object o){
        redisTemplate.delete(o);
    }


    /**
     * 自增1
     * @param key
     * @return
     */
    public long incr(String key){
        long num = valOpsStr.increment(key,1);
        return num;
    }
    /**
     * 自增1
     * @param key
     * @return
     */
    public long incrByExp(String key,long timeout){
        long num = valOpsStr.increment(key,1);
        TimeUnit timeUnit=TimeUnit.MILLISECONDS;
        stringRedisTemplate.expire(key,timeout, timeUnit);
        return num;
    }
    /**
     * 自增
     * @param key
     * @param delta  自增值
     * @return
     */
    public long incrByExp(String key,int delta,long timeout){
        long num = valOpsStr.increment(key,delta);
        TimeUnit timeUnit=TimeUnit.MILLISECONDS;
        stringRedisTemplate.expire(key,timeout, timeUnit);
        return num;
    }
    /**
     * 自增
     * @param key
     * @param delta  自增值
     * @return
     */
    public long incr(String key,long delta){
        return valOpsStr.increment(key,delta);
    }

    /**
     * 获取应用用户ID
     */
    public synchronized String getAppUserId() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMdd");
        LocalDate currentDate = LocalDate.now();
        LocalDate yesterday = currentDate.minusDays(1);
        String todayKey = currentDate.format(formatter);
        String yesterdayKey = yesterday.format(formatter);
        if(this.hasKey(todayKey)){
            this.incr(todayKey);
            return this.getStr(todayKey);
        }
        this.del(yesterdayKey);
        this.setStr(todayKey, todayKey+"00001");
        return this.getStr(todayKey);
    }

    public Long getDitchId(){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDate currentDate = LocalDate.now();
        LocalDate yesterday = currentDate.minusDays(1);
        String todayKey = currentDate.format(formatter);
        String yesterdayKey = yesterday.format(formatter);
        String prefix = "Ditch_";
        if(this.hasKey(prefix+todayKey)){
            this.incr(prefix+todayKey);
            return Long.parseLong(this.getStr(prefix+todayKey));
        }
        this.del(yesterdayKey);
        this.setStr(prefix+todayKey, todayKey+"01");
        return Long.parseLong(this.getStr(prefix+todayKey));
    }

    /**
     *
     * 生成业务单编号
     * @return
     */
    public String generateOrderNo(String key){
        Calendar cl = Calendar.getInstance();
        int year = cl.get(Calendar.YEAR);
        int month = cl.get(Calendar.MONTH) + 1;
        int day = cl.get(Calendar.DATE);
        String orderNoPrefix = getTimeStr(year)+getTimeStr(month)+getTimeStr(day);
        if(this.hasKey(key)){
            String old = this.getStr(key);
            String sub = old.substring(0,8);
            if(sub.equals(orderNoPrefix)){
                long incr = this.incr(key);
                return String.valueOf(incr);
            }
        }
        this.setStr(key,orderNoPrefix+"001");
        return orderNoPrefix+"001";
    }

    private String getTimeStr(int num){
        if(num>9) {
            return String.valueOf(num);
        }
        return "0"+num;
    }
}
