package com.sw.mes.wms.service;

import cn.hutool.core.convert.Convert;
import com.sw.mes.core.utils.StringUtils;
import com.sw.mes.redis.server.RedissonUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * @author liuzemin
 * @date 2022/12/16 17:00
 * @description
 */
@Service
@Slf4j
public class GenerateReportWms {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 生成报工单据号
     * @param type 1毛棒 2圆晶段
     * @return
     */
    public String getPlanNo(Integer type){

        try {
            if (type == 1){
                String preMB = "MB" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
                return preMB + genSerialNumber(preMB);
            }else {
                String preYB = "YB" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
                return preYB + genSerialNumber(preYB);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成报工单据号失败", e);
            return null;
        }

    }


    /**
     * 生成当日5位流水号-10进制5位，如果超出5位报错？
     * @return
     */
    private String genSerialNumber(String key) {
        String serialNumber = redisTemplate.opsForValue().get(key);
        if(StringUtils.isBlank(serialNumber)){

            RLock rLock = RedissonUtils.getRLock(redissonClient, "&" + key);
            if (RedissonUtils.getRLockExpireTime(rLock, 5L)){
                try {
                    serialNumber="1";
                    redisTemplate.opsForValue().set(key, serialNumber, 90L, TimeUnit.DAYS);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                } finally {
                    rLock.unlock();
                }
            }else {
                throw new RuntimeException("报工流水号初始化中, 请稍后再试");
            }

        }else{

            Long increment = redisTemplate.opsForValue().increment(key);
            redisTemplate.expire(key, 90L, TimeUnit.DAYS);
            serialNumber = Convert.toStr(increment);

        }

        int sequence = Convert.toInt(serialNumber);
        String strSequence = Convert.toStr(sequence);
        if (sequence < 100000){
            strSequence = StringUtils.leftPad(strSequence, 5, "0");
        }else {
            throw new RuntimeException("生成 报工单据号的流水号超出5位，无法生成！");
        }
        return strSequence;
    }
}
