import pytest

from crystflux.v1.boundary.error_contracts import ModeNotSupportedError
from crystflux.v1.boundary.mode_contracts import (
    DEFAULT_MODE,
    SUPPORTED_MODES,
    decide_mode,
    infer_value_mode,
    resolve_mode,
)
from crystflux.v1.core.value_modes import DreamValue, LatentValue, StrictValue


def test_resolve_mode_normalizes_and_validates() -> None:
    assert resolve_mode("StRiCt") == "strict"
    assert resolve_mode(None, fallback="dream") == "dream"
    with pytest.raises(ModeNotSupportedError):
        resolve_mode("hyper")


def test_infer_value_mode_matches_concrete_types() -> None:
    assert infer_value_mode(StrictValue(1)) == "strict"
    assert infer_value_mode(LatentValue(1)) == "latent"
    assert infer_value_mode(DreamValue(1)) == "dream"
    with pytest.raises(ModeNotSupportedError):
        infer_value_mode(object())  # type: ignore[arg-type]


def test_decide_mode_prefers_explicit_and_falls_back_to_infer() -> None:
    strict = StrictValue({"x": 1})
    assert decide_mode(strict, "dream") == "dream"
    dream = DreamValue("x")
    assert decide_mode(dream, None) == "dream"
    with pytest.raises(ModeNotSupportedError):
        decide_mode(None, None)


def test_supported_modes_constant_is_in_sync_with_functions() -> None:
    for mode in SUPPORTED_MODES:
        assert resolve_mode(mode) == mode
    assert DEFAULT_MODE in SUPPORTED_MODES
