#ifndef DEVICE_CTRL_SNOWFLAKE_H
#define DEVICE_CTRL_SNOWFLAKE_H

#include <cstdint>
#include <mutex>
#include <chrono>

namespace zsy
{
    /**
     * 雪花算法 ID 生成器
     * 生成64位唯一ID，结构为：
     * - 1位符号位 (始终为0)
     * - 41位时间戳 (毫秒级)
     * - 5位数据中心ID
     * - 5位工作机器ID
     * - 12位序列号
     */
    class Snowflake
    {
    public:
        // 类型别名
        using TimePoint = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>;

        /**
         * 构造函数
         * @param workerId 工作机器ID (0-31)
         * @param datacenterId 数据中心ID (0-31)
         * @param epoch 自定义纪元时间点，默认为2025-01-01 00:00:00
         */
        explicit Snowflake(
            uint64_t workerId,
            uint64_t datacenterId,
            TimePoint epoch = TimePoint{std::chrono::milliseconds{1735660800000}}
        );

        // 禁用拷贝构造和赋值
        Snowflake(const Snowflake &) = delete;

        Snowflake &operator=(const Snowflake &) = delete;

        /**
         * 生成下一个唯一ID
         * @return 生成的64位唯一ID
         * @throws std::runtime_error 如果时钟回拨超过容忍范围
         */
        uint64_t nextId();

        /**
         * @brief 生成下一个字符串类型的唯一ID
         * @return 生成的字符串形式的唯一ID
         * @throws std::runtime_error 如果时钟回拨超过容忍范围
         */
        std::string nextIdStr();

        /**
         * 获取当前时间戳（相对于纪元）
         * @return 当前时间戳（毫秒）
         */
        uint64_t getTimestamp() const;

        /**
         * 从ID解析时间戳
         * @param id 雪花算法生成的ID
         * @param epoch 生成ID时使用的纪元时间
         * @return 对应的时间点
         */
        static TimePoint extractTimePoint(uint64_t id, TimePoint epoch);

        static Snowflake &getInstance()
        {
            static Snowflake snowflake(1, 1);
            return snowflake;
        }

        static std::string genIdStr()
        {
            return getInstance().nextIdStr();
        }

        static uint64_t genId()
        {
            return getInstance().nextId();
        }

    private:
        // 常量定义
        static constexpr uint64_t WorkerIdBits = 5; // 工作机器ID位数
        static constexpr uint64_t DatacenterIdBits = 5; // 数据中心ID位数
        static constexpr uint64_t SequenceBits = 12; // 序列号位数

        static constexpr uint64_t MaxWorkerId = (1ULL << WorkerIdBits) - 1; // 最大工作机器ID
        static constexpr uint64_t MaxDatacenterId = (1ULL << DatacenterIdBits) - 1; // 最大数据中心ID
        static constexpr uint64_t MaxSequence = (1ULL << SequenceBits) - 1; // 序列号掩码

        static constexpr uint64_t WorkerIdShift = SequenceBits; // 工作机器ID左移位数
        static constexpr uint64_t DatacenterIdShift = SequenceBits + WorkerIdBits; // 数据中心ID左移位数
        static constexpr uint64_t TimestampShift = SequenceBits + WorkerIdBits + DatacenterIdBits; // 时间戳左移位数


        // 成员变量
        const uint64_t workerId; // 工作机器ID
        const uint64_t datacenterId; // 数据中心ID
        const TimePoint epoch; // 纪元时间点

        uint64_t sequence = 0; // 当前序列号
        uint64_t lastTimestamp = 0; // 上次生成ID的时间戳

        mutable std::mutex idMutex; // 互斥锁，保证线程安全

        // 获取当前时间戳（毫秒，相对于纪元）
        uint64_t currentTimestamp() const;

        // 等待下一毫秒
        uint64_t waitNextMillis(uint64_t lastTimestamp) const;
    };
} // namespace utils

#endif // DEVICE_CTRL_SNOWFLAKE_H
