package com.fs.his.utils;

public class Base62Utils {
    private static final String BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    private static final int BASE62 = 62;
    
    /**
     * 将字节数组转换为 Base62 字符串
     */
    public static String bytesToBase62(byte[] data) {
        if (data == null || data.length == 0) {
            return "";
        }
        
        StringBuilder sb = new StringBuilder();
        int idx = 0;
        
        while (idx < data.length) {
            long value = 0;
            int count = 0;
            
            for (int i = 0; i < 7 && idx < data.length; i++, idx++, count++) {
                value = (value << 8) | (data[idx] & 0xFF);
            }
            
            long[] encoded = encodeBase62(value, count);
            for (int i = encoded.length - 1; i >= 0; i--) {
                sb.append(BASE62_CHARS.charAt((int)encoded[i]));
            }
        }
        
        return sb.toString();
    }
    
    /**
     * 将 Base62 字符串转换为字节数组
     */
    public static byte[] base62ToBytes(String base62String) {
        if (base62String == null || base62String.isEmpty()) {
            return new byte[0];
        }
        
        byte[] result = new byte[(base62String.length() * 7 + 7) / 8];
        int resultIdx = 0;
        int strIdx = 0;
        
        while (strIdx < base62String.length()) {
            long value = 0;
            int count = 0;
            
            for (int i = 0; i < 11 && strIdx < base62String.length(); i++, strIdx++) {
                char c = base62String.charAt(strIdx);
                int digit = decodeBase62Char(c);
                if (digit == -1) {
                    throw new IllegalArgumentException("Invalid Base62 character: " + c);
                }
                value = value * BASE62 + digit;
                count++;
            }
            
            int bytesToWrite = (count * 6 + 7) / 8;
            for (int i = bytesToWrite - 1; i >= 0 && resultIdx < result.length; i--, resultIdx++) {
                result[resultIdx] = (byte)((value >> (i * 8)) & 0xFF);
            }
        }
        
        return trimZeroBytes(result);
    }
    
    private static long[] encodeBase62(long value, int byteCount) {
        int outputSize = (byteCount * 8 + 5) / 6;
        long[] result = new long[outputSize];
        int idx = 0;
        
        while (value > 0) {
            result[idx++] = value % BASE62;
            value /= BASE62;
        }
        
        return java.util.Arrays.copyOf(result, idx);
    }
    
    private static int decodeBase62Char(char c) {
        if (c >= '0' && c <= '9') return c - '0';
        if (c >= 'A' && c <= 'Z') return c - 'A' + 10;
        if (c >= 'a' && c <= 'z') return c - 'a' + 36;
        return -1;
    }
    
    private static byte[] trimZeroBytes(byte[] data) {
        int nonZeroCount = 0;
        for (byte b : data) {
            if (b != 0) nonZeroCount++;
        }
        
        if (nonZeroCount == data.length) {
            return data;
        }
        
        byte[] trimmed = new byte[nonZeroCount];
        int idx = 0;
        for (byte b : data) {
            if (b != 0) {
                trimmed[idx++] = b;
            }
        }
        return trimmed;
    }
}
