package com.sckw.redis.utils;

import org.redisson.api.RAtomicLong;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.util.Random;

/**
 * @desc:
 * @author: Lt
 * @date: 2024-05-27
 */
@Component
public class GenOrderCode {
    // 创建Redisson客户端实例
    private final RedissonClient redissonClient;

    public GenOrderCode(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    /**
     * 生成指定长度的订单号
     *
     * @param length   订单总长度
     * @param prefix   前缀 当天日期-yyMMdd
     * @param lockKey 分布式锁id
     * @return 订单号
     */
    public String genOrderCode(int length, String prefix, String lockKey) {
        // 检查参数合法性
        if (length <= 0) {
            throw new RuntimeException("订单总长度或随机码长度不能小于0");
        }
        if (length <= prefix.length()) {
            throw new RuntimeException("订单总长度长度小于前缀长度");
        }

        // 获取分布式锁
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        try {
            // 从Redis中获取递增的序列号
            RAtomicLong counter = redissonClient.getAtomicLong("counter");
            // 递增计数器
            long incrementedValue = counter.incrementAndGet();
            String counterValue = String.valueOf(incrementedValue);
            int incrLength = counterValue.length();

            // 如果前缀长度加数字自增长度大于指定位数，则直接使用自增数据
            if (incrLength + prefix.length() > length) {
                return prefix + counterValue;
            }

            // 生成随机码
            int randomLength = length - incrLength;
            String randomAlphabetic = generateRandomAlphabeticString(randomLength);
            // 格式化订单号
            return prefix + randomAlphabetic + counterValue;
        } finally {
            // 释放锁
            lock.unlock();
        }
    }


    public static String generateRandomAlphabeticString(int length) {
        if (length < 0) {
            throw new IllegalArgumentException("Length cannot be negative.");
        }

        StringBuilder sb = new StringBuilder(length);
        Random random = new Random();
        String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        for (int i = 0; i < length; i++) {
            int index = random.nextInt(alphabet.length());
            sb.append(alphabet.charAt(index));
        }

        return sb.toString();
    }
}
