package hw.tagApi.common.utils.uuid;

import java.net.NetworkInterface;
import java.net.SocketException;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Enumeration;

/**
 * ID生成器工具类
 * 仿照MyBatis-Plus的雪花算法实现
 *
 * @author Yinq
 * @date 2025-04-15
 */
public class IdGenerator {
    /**
     * 开始时间戳（2025-01-01 00:00:00）
     */
    private static final long START_TIMESTAMP = LocalDateTime.of(2025, 1, 1, 0, 0, 0)
            .toInstant(ZoneOffset.of("+8")).toEpochMilli();

    /**
     * 机器ID所占位数
     */
    private static final long WORKER_ID_BITS = 10L;

    /**
     * 序列号所占位数
     */
    private static final long SEQUENCE_BITS = 12L;

    /**
     * 机器ID最大值
     */
    private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);

    /**
     * 序列号掩码
     */
    private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);

    /**
     * 机器ID左移位数
     */
    private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;

    /**
     * 时间戳左移位数
     */
    private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;

    /**
     * 序列号
     */
    private static long sequence = 0L;

    /**
     * 上次生成ID的时间戳
     */
    private static long lastTimestamp = -1L;

    /**
     * 机器ID
     */
    private static long workerId;

    static {
        try {
            workerId = getWorkerId();
        } catch (Exception e) {
            workerId = 1L;
        }
    }

    /**
     * 获取机器ID
     */
    private static long getWorkerId() throws SocketException {
        long macPiece;
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        while (networkInterfaces.hasMoreElements()) {
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            byte[] mac = networkInterface.getHardwareAddress();
            if (mac != null) {
                macPiece = ((0x000000FFL & (mac[mac.length - 1])) | (0x0000FF00L & (((mac[mac.length - 2]) << 8)))) >> 6;
                return macPiece;
            }
        }
        return 1L;
    }

    /**
     * 生成下一个ID
     */
    public static synchronized Long nextId() {
        long timestamp = System.currentTimeMillis();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("时钟回拨，拒绝生成ID");
        }
        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & SEQUENCE_MASK;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        return ((timestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT) | (workerId << WORKER_ID_SHIFT) | sequence;
    }

    /**
     * 等待下一个毫秒
     */
    private static long tilNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }
} 