"""Tests for ``mgf.fed.cli._version_pin``.

Closes [PAPER-52](../../../../FEEDBACK.md) (init-project pin) and
[PAPER-57](../../../../FEEDBACK.md) (federation-sync message) by
verifying the shared helper that both call sites depend on.
"""

from __future__ import annotations

import mgf.common

from mgf.fed.cli._version_pin import (
    current_pin_window,
    pin_window_for_version,
)


class TestPinWindowForVersion:
    def test_minor_window_for_canonical_zero_x_version(self) -> None:
        assert pin_window_for_version("0.38.0") == ">=0.38,<0.39"

    def test_minor_window_ignores_patch(self) -> None:
        # Both yield the same MINOR window.
        assert pin_window_for_version("0.38.0") == pin_window_for_version("0.38.5")

    def test_post_one_zero_window(self) -> None:
        # The helper isn't gated on 0.x; v1.x consumers get the same shape.
        assert pin_window_for_version("1.2.3") == ">=1.2,<1.3"

    def test_minor_overflow_yields_next_major_minor_zero(self) -> None:
        # 0.99 → 0.100 is a degenerate but legal extrapolation.
        assert pin_window_for_version("0.99.0") == ">=0.99,<0.100"

    def test_malformed_version_falls_back_to_diagnostic_shape(self) -> None:
        # Non-numeric MINOR triggers the safe fallback path — diagnostic
        # rather than ValueError, so callers don't crash on weird inputs.
        result = pin_window_for_version("0.abc.0")
        assert ">=" in result  # still resembles a pin
        assert "0.abc.0" in result  # surfaces the bad version to debug

    def test_single_part_version_falls_back(self) -> None:
        result = pin_window_for_version("42")
        assert "42" in result


class TestCurrentPinWindow:
    def test_matches_pin_window_for_version_of_installed(self) -> None:
        # The two helpers must produce the same answer for the installed
        # version — otherwise the federation-sync message and the
        # init-project snippet would drift.
        assert current_pin_window() == pin_window_for_version(
            mgf.common.__version__,
        )

    def test_starts_with_gte_and_contains_lt(self) -> None:
        # Shape guard: independent of the version, the result must be a
        # PEP-440-ish window string.
        window = current_pin_window()
        assert window.startswith(">=")
        assert ",<" in window
