package com.yunfeiyun.agmp.common.utils.serialno;

import com.yunfeiyun.agmp.common.constant.ErrorCode;
import com.yunfeiyun.agmp.common.enums.FmsNoType;
import com.yunfeiyun.agmp.common.enums.RedisCacheKey;
import com.yunfeiyun.agmp.common.exception.BizException;
import com.yunfeiyun.agmp.common.framework.manager.RedisCacheManager;
import com.yunfeiyun.agmp.common.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class NoGenerator {

    @Autowired
    private RedisCacheManager redisCacheManager;

    public String getPlanNo() {

        return gen(RedisCacheKey.FMS_NO_GENERATOR, FmsNoType.SERIAL_PREFIX_PLAN,getRemainderTime(ExpireTimeType.DAY),"yyMMdd");
    }

    public String getPickNo() {
        return gen(RedisCacheKey.FMS_NO_GENERATOR, FmsNoType.SERIAL_PREFIX_TASK_PICK,getRemainderTime(ExpireTimeType.DAY),"yyMMdd");
    }

    public String getTaskNo() {
        return gen(RedisCacheKey.FMS_NO_GENERATOR, FmsNoType.SERIAL_PREFIX_TASK,getRemainderTime(ExpireTimeType.DAY),"yyMMdd");
    }

    public String getSpmOrderNo(){
        return gen(RedisCacheKey.FMS_NO_GENERATOR,FmsNoType.SERIAL_PREFIX_SPM_ORDER,getRemainderTime(ExpireTimeType.DAY),"yyMMdd");

    }

    public String getBuyNo() {
        return gen(RedisCacheKey.FMS_NO_GENERATOR, FmsNoType.SERIAL_PREFIX_BUY,getRemainderTime(ExpireTimeType.DAY),"yyMMdd");
    }

    public String getProcessNo() {
        return gen(RedisCacheKey.FMS_NO_GENERATOR, FmsNoType.SERIAL_PREFIX_PROCESS,getRemainderTime(ExpireTimeType.DAY),"yyMMdd");
    }

    public String getPackNo() {
        return gen(RedisCacheKey.FMS_NO_GENERATOR, FmsNoType.SERIAL_PREFIX_PACK,getRemainderTime(ExpireTimeType.DAY),"yyMMdd");
    }
    public String getSourceNo(){
        return gen(RedisCacheKey.FMS_NO_GENERATOR,FmsNoType.SERIAL_PREFIX_SOURCE_NO,getRemainderTime(ExpireTimeType.MINUTE),"yyyyMMddHHmm");
    }

    private String gen(RedisCacheKey redisCacheKey, FmsNoType fmsNoType,long expireTime,String timeFormat) {
        Object object = redisCacheManager.getCacheObject(redisCacheKey, fmsNoType.getName());
        // 判断是不是有初始化此实体类
        // 根据流水号的前缀判断今天是否有生成过流水号
        if (object == null) {
            redisCacheManager.setCacheObject(redisCacheKey, fmsNoType.getName(),0,expireTime*1000,TimeUnit.MILLISECONDS);
        }

        // 进行自增操作
        StringBuffer sn = new StringBuffer();
        // 和前缀、时间、随机数进行组合
        sn.append(fmsNoType.getPrefix());
        try {
            String date = DateUtils.turnDateFormat(DateUtils.dateTimeNow(),DateUtils.YYYY_MM_DD_HH_MM_SS,timeFormat);
            sn.append(date);
        }catch (Exception e){
            throw new BizException(ErrorCode.SYSTEM_ERROR);
        }
        //流水号自动自增
        Long num = redisCacheManager.increment(redisCacheKey,fmsNoType.getName());
        sn.append(addZero(String.valueOf(num), fmsNoType.getMaxLength()));
        //介于0-1000之前生成随机数
//            String random = String.valueOf(new Random().nextInt(1000));
//            sn.append(random);
        return sn.toString();


    }

    // 自动补零
    private String addZero(String numStr, Integer maxNum) {
        int addNum = maxNum - numStr.length();
        StringBuffer rStr = new StringBuffer();
        for (int i = 0; i < addNum; i++) {
            rStr.append("0");
        }
        rStr.append(numStr);
        return rStr.toString();
    }

    private long getRemainderTime(ExpireTimeType expireTimeType){
        Long expireTime = 0L;
        if(ExpireTimeType.DAY.equals(expireTimeType)){
            // 设置到第二天早上00：00：01过期
            expireTime = LocalDate.now().plusDays(1).atTime(0, 0, 0, 1).atOffset(ZoneOffset.ofHours(8)).toEpochSecond();
        }
        if(ExpireTimeType.HOUR.equals(expireTimeType)){
            expireTime = LocalDateTime.now().plusHours(1).withMinute(0).withSecond(0).atOffset(ZoneOffset.ofHours(8)).toEpochSecond();
        }
        if(ExpireTimeType.MINUTE.equals(expireTimeType)){
            expireTime = LocalDateTime.now().plusMinutes(1).withSecond(0).atOffset(ZoneOffset.ofHours(8)).toEpochSecond();
        }
        Long nowTime = LocalDateTime.now().atOffset(ZoneOffset.ofHours(8)).toEpochSecond();
        return expireTime - nowTime;
    }
    private enum ExpireTimeType{
        DAY,
        HOUR,
        MINUTE
    }
}