"""Progress reporting and cooperative cancellation primitives.

Re-export shim over :mod:`mgf.common.progress`. The upstream module's
docstring records that it was **lifted from** VManager's own copy
(closes upstream FEEDBACK API-03), so the canonical implementation
lives upstream now and VManager consumes it through this thin
re-export.

Round 2 of `docs/MGF_COMMON_CATCHUP.md` (Phase MGF-8) retired the
local implementation. Existing call sites (~76 across `src/` +
`tests/`) keep working unchanged — they continue to do
``from mgf.vm.common.progress import CancellationToken,
ProgressReporter, NullReporter, RecordingReporter`` and the names
resolve to the upstream definitions.

One small adapter: the upstream :class:`mgf.common.progress.RecordingReporter`
exposes its accumulator under :attr:`calls`; VManager's tests pin
the legacy name :attr:`messages` (~19 call sites). The local
:class:`RecordingReporter` here is a one-line subclass that adds
``messages`` as a read-only alias for ``calls`` — backwards-compatible
at the shim boundary, no test churn. New code MAY use either name;
``calls`` is the upstream-canonical spelling.

New non-test code MAY import directly from :mod:`mgf.common.progress`.
The shim is kept (rather than dropped) for code-search continuity
and because it absorbs any future VManager-specific extension.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from mgf.common.progress import (
    CancellationToken,
    NullReporter,
    ProgressReporter,
)
from mgf.common.progress import RecordingReporter as _UpstreamRecordingReporter

if TYPE_CHECKING:
    from mgf.common.typing import CancellationProtocol


class RecordingReporter(_UpstreamRecordingReporter):
    """``mgf.common.progress.RecordingReporter`` + VManager compat aliases.

    Two adapters preserve VManager's pre-shim test surface:

    - ``.messages`` is a read-only alias for the upstream
      :attr:`calls` field (~19 test sites use the legacy name).
    - ``.token`` is a read-only alias for the upstream private
      :attr:`_token` field (2 test sites do ``reporter.token.cancel()``).
      The constructor also defaults the token to a fresh
      :class:`CancellationToken` when none is passed, matching the
      legacy local default-factory shape so a no-arg
      ``RecordingReporter()`` still has a usable cancellation
      handle.

    New code SHOULD use the upstream names (``calls`` /
    constructor-injected token) directly.
    """

    def __init__(self, token: CancellationProtocol | None = None) -> None:
        if token is None:
            token = CancellationToken()
        super().__init__(token)

    @property
    def messages(self) -> list[tuple[str, int, int]]:
        """Backwards-compat alias for :attr:`calls`."""
        return self.calls

    @property
    def token(self) -> CancellationProtocol:
        """Backwards-compat alias for the upstream private ``_token``.

        ``__init__`` always sets ``_token`` to a non-None value (the
        legacy default-factory shape), so the assertion is sound.
        """
        assert self._token is not None  # ensured by __init__
        return self._token


__all__ = [
    "CancellationToken",
    "NullReporter",
    "ProgressReporter",
    "RecordingReporter",
]
