"""``PassthroughRefiner`` — no-op :class:`ConditionalRefiner` (AZ-348).

The reference baseline implementation. Returns the input
:class:`MatchResult` unchanged (same object reference;
``inlier_correspondences`` ndarrays are bit-identical and share
references per contract INV-5). Always sets :meth:`was_invoked`
to ``False`` per INV-8.

Both helpers (``ransac_filter``, ``inference_runtime``) are held
by reference for parity with :class:`AdHoPRefiner` (AZ-349) but
neither is invoked. ``inference_runtime`` is typed as ``object``
because the C3 matcher → C3.5 refiner → C4 pose layering forbids
L3-to-L3 imports (architecture test ``test_az270_compose_root``);
the composition-root factory at
:mod:`gps_denied_onboard.runtime_root.refiner_factory`
narrows the type at construction time.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from gps_denied_onboard._types.matcher import MatchResult
    from gps_denied_onboard._types.nav import NavCameraFrame
    from gps_denied_onboard.config.schema import Config
    from gps_denied_onboard.helpers.ransac_filter import RansacFilter

__all__ = ["PassthroughRefiner", "create"]


class PassthroughRefiner:
    """Reference passthrough strategy.

    See module docstring. Stateless except for the ``_was_invoked``
    flag (always ``False`` per INV-8); concurrent calls are unsafe
    (single-thread invariant covers).
    """

    def __init__(
        self,
        *,
        ransac_filter: "RansacFilter",
        inference_runtime: object,
    ) -> None:
        # Held for parity with AdHoPRefiner; neither is invoked.
        self._ransac_filter = ransac_filter
        self._inference_runtime = inference_runtime
        self._was_invoked: bool = False

    def refine_if_needed(
        self,
        frame: "NavCameraFrame",
        mr: "MatchResult",
        residual_threshold_px: float,
    ) -> "MatchResult":
        if residual_threshold_px <= 0.0:
            raise ValueError(
                "residual_threshold_px must be > 0; "
                f"got {residual_threshold_px}"
            )
        self._was_invoked = False
        # `MatchResult` defaults `refinement_label="passthrough"`
        # and `refinement_added_latency_ms=0.0` already; the input
        # is bit-identical per contract INV-5 so we return it by
        # reference rather than recreating via `dataclasses.replace`.
        return mr

    def was_invoked(self) -> bool:
        return self._was_invoked


def create(
    config: "Config",
    *,
    ransac_filter: "RansacFilter",
    inference_runtime: object,
) -> PassthroughRefiner:
    """Module-level factory entry point consumed by the
    composition-root :func:`build_refiner_strategy`."""
    return PassthroughRefiner(
        ransac_filter=ransac_filter,
        inference_runtime=inference_runtime,
    )
