package com.clx.performance.component;

import com.clx.performance.constant.RedisConstants;
import com.clx.performance.dao.OrderGoodsDao;
import com.clx.performance.enums.PerformanceResultEnum;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.Component;

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

@Component
@Slf4j
public class OrderGoodsIdGenerate {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private OrderGoodsDao orderGoodsDao;

    @Autowired
    private RedissonClient redissonClient;

    private static final String type = "id";


    public long getOrderGoodsId(Integer size) {
        RLock rLock = null;
        try {
            rLock = redissonClient.getLock(RedisConstants.ORDER_NO_BLOCK + type);

            rLock.lock(5, TimeUnit.SECONDS);
            long baseStart = Long.parseLong(DateUtils.formatDate(LocalDate.now(), "yyyyMMdd").get() + "00001");
            Object o = redisTemplate.opsForHash().get(RedisConstants.ORDER_GOODS_ID, type);
            if (o == null) {
                Long maxOrderGoodsId = null;
                String maxID = orderGoodsDao.getMaxOrderGoodsId();
                if (StringUtils.isNotBlank(maxID)) {
                    maxOrderGoodsId = Long.valueOf(maxID.substring(2));
                }

                if (maxOrderGoodsId == null) {
                    maxOrderGoodsId = 0L;
                }
                if (baseStart > maxOrderGoodsId) {
                    redisTemplate.opsForHash().put(RedisConstants.ORDER_GOODS_ID, type, String.valueOf(baseStart + size));
                    return baseStart;
                } else {
                    long orderGoodsId = maxOrderGoodsId + size;
                    redisTemplate.opsForHash().put(RedisConstants.ORDER_GOODS_ID, type, String.valueOf(orderGoodsId));
                    return maxOrderGoodsId + 1;
                }
            } else {
                long redisOrderGoodsId = Long.parseLong(o.toString());
                if (redisOrderGoodsId < baseStart) {
                    redisOrderGoodsId = baseStart;
                }
                long orderGoodsId = redisOrderGoodsId + size;
                redisTemplate.opsForHash().put(RedisConstants.ORDER_GOODS_ID, type, String.valueOf(orderGoodsId));
                return redisOrderGoodsId;
            }
        } catch (Exception e) {
            throw new ServiceSystemException(PerformanceResultEnum.ORDER_GOODS_ID_GENERATE_LOCK, e.getMessage());

        } finally {
            try {
                if (rLock != null && rLock.isLocked()) {
                    rLock.unlock();
                }
                log.info("锁释放完成货单ID生成");
            } catch (Exception e) {
                log.error("redis 货单ID生成 分布式锁释放异常!", e);
            }
        }

    }
}
