"""``WallClock`` strategy (AZ-398) — live + REALTIME replay.

Thin :class:`Clock` adapter over the standard-library :mod:`time`
module. Owned by ``clock/`` so the AC-4 AST scan over ``components/``
remains clean: components MUST NOT call :func:`time.monotonic_ns`
directly; they call :meth:`WallClock.monotonic_ns` via injection.
"""

from __future__ import annotations

import time


class WallClock:
    """Default :class:`Clock` strategy backed by :mod:`time`.

    Stateless; constructable without arguments. All three methods are
    trivially Liskov-clean over the Protocol.
    """

    __slots__ = ()

    def monotonic_ns(self) -> int:
        return time.monotonic_ns()

    def time_ns(self) -> int:
        return time.time_ns()

    def sleep_until_ns(self, target_ns: int) -> None:
        """Block until ``time.monotonic_ns() >= target_ns``.

        A target already in the past is a no-op. Sub-millisecond
        oversleep is accepted (AC-5: ≤ 5 ms drift on a 100 ms sleep).
        """
        now = time.monotonic_ns()
        delta_ns = target_ns - now
        if delta_ns <= 0:
            return
        time.sleep(delta_ns / 1_000_000_000.0)


__all__ = ["WallClock"]
