package com.fs.qw.utils;

import java.security.SecureRandom;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 生成不重复的随机字符串工具类
 * 用于生成网页参数编码、短链接等场景
 */
public class UniqueStringUtil {
    
    // 字符集：数字+大小写字母
    private static final String CHAR_SET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    private static final int BASE = CHAR_SET.length();
    
    // 安全随机数生成器
    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
    
    // 自增序列（保证同一毫秒内的唯一性）
    private static final AtomicLong SEQUENCE = new AtomicLong(1);
    
    // 用于检查重复的缓存（可选，用于调试）
    private static final ConcurrentHashMap<String, Boolean> GENERATED_CACHE = new ConcurrentHashMap<>();
    
    /**
     * 生成指定长度的不重复随机字符串
     * @param length 字符串长度
     * @return 不重复的随机字符串
     */
    public static String generateUnique(int length) {
        if (length <= 0 || length > 64) {
            throw new IllegalArgumentException("Length must be between 1 and 64");
        }
        
        String result;
        do {
            result = generateRandomString(length);
        } while (GENERATED_CACHE.putIfAbsent(result, Boolean.TRUE) != null);
        
        return result;
    }
    
    /**
     * 生成带时间戳的随机字符串（确保唯一性）
     * @param length 字符串长度
     * @return 唯一字符串
     */
    public static String generateTimeBasedUnique(int length) {
        // 时间戳部分（毫秒级，转换为36进制）
        String timePart = Long.toString(System.currentTimeMillis(), 36);
        
        // 序列号部分（转换为62进制）
        long seq = SEQUENCE.getAndIncrement();
        if (seq >= Long.MAX_VALUE / 2) {
            SEQUENCE.set(1);
        }
        String seqPart = toBase62(seq);
        
        // 随机部分
        String randomPart = generateRandomString(length - Math.min(timePart.length() + seqPart.length(), length));
        
        // 组合
        String result = (timePart + seqPart + randomPart).substring(0, length);
        
        return result;
    }
    
    /**
     * 生成短字符串（8-16位，适合做网页参数）
     * @return 唯一短字符串
     */
    public static String generateShortUnique() {
        return generateTimeBasedUnique(12);
    }
    
    /**
     * 生成长字符串（32位，类似UUID）
     * @return 唯一长字符串
     */
    public static String generateLongUnique() {
        return generateTimeBasedUnique(32);
    }
    
    /**
     * 生成随机字符串
     */
    private static String generateRandomString(int length) {
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            int index = SECURE_RANDOM.nextInt(BASE);
            sb.append(CHAR_SET.charAt(index));
        }
        return sb.toString();
    }
    
    /**
     * 将数字转换为62进制字符串
     */
    private static String toBase62(long number) {
        if (number == 0) return "0";
        
        StringBuilder sb = new StringBuilder();
        long num = number;
        
        while (num > 0) {
            int remainder = (int) (num % 62);
            sb.append(CHAR_SET.charAt(remainder));
            num = num / 62;
        }
        
        return sb.reverse().toString();
    }
    
    /**
     * 生成批量唯一字符串
     */
    public static String[] generateBatch(int count, int length) {
        String[] results = new String[count];
        for (int i = 0; i < count; i++) {
            results[i] = generateTimeBasedUnique(length);
        }
        return results;
    }
    
    public static void main(String[] args) {
        System.out.println("=== 测试生成唯一字符串 ===");
        
        // 测试生成10个短字符串
        System.out.println("\n生成10个短字符串（12位）：");
        for (int i = 0; i < 10; i++) {
            System.out.println(generateShortUnique());
        }
        
        // 测试生成长字符串
        System.out.println("\n生成长字符串（32位）：");
        System.out.println(generateLongUnique());
        
        // 测试批量生成
        System.out.println("\n批量生成5个16位字符串：");
        String[] batch = generateBatch(5, 16);
        for (String s : batch) {
            System.out.println(s);
        }
    }
}