package com.zzsn.knowbase.util;

import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * @author lkg
 * @description: 按规则生成唯一值
 * @date 2021/6/3 18:29
 */
@Component
public class CodeGenerateUtil {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 生成编码
     * @param prefix 前缀
     * @return java.lang.String
     */
    public String geneCodeNo(String prefix){
        return getCode(prefix);
    }

    /**
     *  生成id
     * @param prefix 前缀
     * @return java.lang.String
     */
    public String geneIdNo(String prefix, int num){
        return getId(prefix, num);
    }

    /**
     *  生成统一社会信用代码
     * @param prefix 前缀
     * @return java.lang.String
     */
    public String geneSocialCreditCode(String prefix){
        return getCreditCode(prefix);
    }

    //根据规则生成code(规则：前缀+格式化日期(截取后六位)+递增值(8位数))
    private String getCreditCode(String prefix) {
        String redisKey = getRedisKey(prefix);
        Date expireDate = getExpireDate();
        //返回当前redis中的key的最大值
        long seq = generate(stringRedisTemplate, redisKey, expireDate);
        //获取当天的日期，格式为yyyyMMdd
        String date = new SimpleDateFormat("yyyyMMdd").format(expireDate);
        //生成八位的序列号，如果seq不够四位，seq前面补0，
        //如果seq位数超过了八位，那么无需补0直接返回当前的seq
        String sequence = StringUtils.leftPad(Long.toString(seq), 8, "0");
        return prefix + date.substring(2) + sequence;
    }

    //生成老企业库id
    public long getEnterpriseId(String prefix) {
        String redisKey = getRedisKey(prefix);
        Date expireDate = getExpireDate();
        //返回当前redis中的key的最大值
        long seq = generate(stringRedisTemplate, redisKey, expireDate);
        //获取当天的日期，格式为yyyyMMdd
        String date = new SimpleDateFormat("yyyyMMdd").format(expireDate);
        //生成八位的序列号，如果seq不够四位，seq前面补0，
        //如果seq位数超过了八位，那么无需补0直接返回当前的seq
        String sequence = StringUtils.leftPad(Long.toString(seq), 5, "0");
        return Long.parseLong(date.substring(2) + sequence);
    }

    //根据规则生成编码(规则：前缀+格式化日期+递增值(4位数))
    private String getCode(String prefix){
        String redisKey = getRedisKey(prefix);
        Date expireDate = getExpireDate();
        //返回当前redis中的key的最大值
        long seq = generate(stringRedisTemplate, redisKey, expireDate);
        //获取当天的日期，格式为yyyyMMdd
        String date = new SimpleDateFormat("yyyyMMdd").format(expireDate);
        //生成四位的序列号，如果seq不够四位，seq前面补0，
        //如果seq位数超过了四位，那么无需补0直接返回当前的seq
        String sequence = StringUtils.leftPad(Long.toString(seq), 4, "0");
        //返回编码
        return prefix + "-" + date + "-" + sequence;
    }

    //根据规则生成id(规则：格式化日期(截取后六位)+递增值(8位数))
    private String getId(String prefix, int num){
        String redisKey = getRedisKey(prefix);
        Date expireDate = getExpireDate();
        //返回当前redis中的key的最大值
        long seq = generate(stringRedisTemplate, redisKey, expireDate);
        //获取当天的日期，格式为yyyyMMdd
        String date = new SimpleDateFormat("yyyyMMdd").format(expireDate);
        //生成八位的序列号，如果seq不够四位，seq前面补0，
        //如果seq位数超过了八位，那么无需补0直接返回当前的seq
        String sequence = StringUtils.leftPad(Long.toString(seq), num, "0");
        return date.substring(2)+sequence;
    }

    //获取redis--key
    @SneakyThrows
    private String getRedisKey(String prefix){
        if (StringUtils.isEmpty(prefix)){
            throw new Exception("前缀不能为空!");
        }
        //用作存放redis中的key前缀
        String PREFIX_KEY = "CodeGenerateUtil::";
        return PREFIX_KEY + prefix;
    }

    //获取缓存过期时间点
    private Date getExpireDate(){
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        //设置过期时间，这里设置为当天的23:59:59
        return calendar.getTime();
    }

    //获取redis缓存
    private long generate(StringRedisTemplate stringRedisTemplate,String key,Date expireTime) {
        //RedisAtomicLong为原子类，根据传入的key和redis链接工厂创建原子类
        RedisAtomicLong counter = new RedisAtomicLong(key,stringRedisTemplate.getConnectionFactory());
        //设置过期时间
        counter.expireAt(expireTime);
        //返回redis中key的值
        return counter.incrementAndGet();
    }

}
