import secrets
import time
from uuid import UUID


class UUIDv7:
    """
    Utility class for generating UUID version 7 (UUIDv7) identifiers.

    UUIDv7s are time-ordered (based on Unix epoch milliseconds) and
    include sufficient randomness, making them excellent for use as
    primary keys or message IDs in distributed systems where
    time-based ordering and uniqueness are important.
    """

    __VER: int = 0x7
    __VAR: int = 0x2

    @classmethod
    def __calculate(cls) -> int:
        rand_bits: int = secrets.randbits(74)

        unix_ts_ms: int = (time.time_ns() // 1_000_000) & 0xFFFFFFFFFFFF
        rand_a: int = (rand_bits >> 62) & 0x0FFF
        rand_b: int = rand_bits & 0x3FFFFFFFFFFFFFFF

        uuid_v_7 = unix_ts_ms << 80
        uuid_v_7 |= cls.__VER << 76
        uuid_v_7 |= rand_a << 64
        uuid_v_7 |= cls.__VAR << 62
        uuid_v_7 |= rand_b

        return uuid_v_7

    @classmethod
    def get(cls) -> UUID:
        """
        Generates a new UUIDv7.

        The UUIDv7 format is:
        - 48-bit Unix Epoch timestamp in milliseconds
        - 4-bit UUID version (0x7)
        - 12-bit 'rand_a' (random bits)
        - 2-bit UUID variant (0x2)
        - 62-bit 'rand_b' (random bits)

        Returns:
            UUID: A newly generated UUIDv7 object.
        """

        return UUID(int=cls.__calculate())

    @classmethod
    def get_as_str(cls) -> str:
        """
        Generates a new UUIDv7 and returns it as a string.

        Returns:
            str: A string representation of the newly generated UUIDv7.
        """

        return str(cls.get())

    @classmethod
    def get_as_hex(cls) -> str:
        """
        Generates a new UUIDv7 and returns its hexadecimal representation.

        Returns:
            str: The hexadecimal string of the newly generated UUIDv7.
        """

        return cls.get().hex

    @classmethod
    def get_as_int(cls) -> int:
        """
        Generates a new UUIDv7 and returns its integer representation.

        Returns:
            int: The integer value of the newly generated UUIDv7.
        """

        return int(cls.get())

    @classmethod
    def get_as_bytes(cls) -> bytes:
        """
        Generates a new UUIDv7 and returns its byte representation.

        Returns:
            bytes: The byte string of the newly generated UUIDv7.
        """

        return cls.get().bytes
