"""Timezone-aware datetime helpers.

All datetimes in BanGUI are stored and transmitted in UTC.
Conversion to the user's display timezone happens only at the presentation
layer (frontend). These utilities provide a consistent, safe foundation
for working with time throughout the backend.
"""

import datetime


def utc_now() -> datetime.datetime:
    """Return the current UTC time as a timezone-aware :class:`datetime.datetime`.

    Returns:
        Current UTC datetime with ``tzinfo=datetime.UTC``.
    """
    return datetime.datetime.now(datetime.UTC)


def utc_from_timestamp(ts: float) -> datetime.datetime:
    """Convert a POSIX timestamp to a timezone-aware UTC datetime.

    Args:
        ts: POSIX timestamp (seconds since Unix epoch).

    Returns:
        Timezone-aware UTC :class:`datetime.datetime`.
    """
    return datetime.datetime.fromtimestamp(ts, tz=datetime.UTC)


def add_minutes(dt: datetime.datetime, minutes: int) -> datetime.datetime:
    """Return a new datetime that is *minutes* ahead of *dt*.

    Args:
        dt: The source datetime (must be timezone-aware).
        minutes: Number of minutes to add. May be negative.

    Returns:
        A new timezone-aware :class:`datetime.datetime`.
    """
    return dt + datetime.timedelta(minutes=minutes)


def is_expired(expires_at: datetime.datetime) -> bool:
    """Return ``True`` if *expires_at* is in the past relative to UTC now.

    Args:
        expires_at: The expiry timestamp to check (must be timezone-aware).

    Returns:
        ``True`` when the timestamp is past, ``False`` otherwise.
    """
    return utc_now() >= expires_at


def hours_ago(hours: int) -> datetime.datetime:
    """Return a timezone-aware UTC datetime *hours* before now.

    Args:
        hours: Number of hours to subtract from the current time.

    Returns:
        Timezone-aware UTC :class:`datetime.datetime`.
    """
    return utc_now() - datetime.timedelta(hours=hours)
