from crystflux.v1 import Crystallizer
from crystflux.v1.adapters import enable_dream_mode
from crystflux.v1.core import VOID, DreamValue, StrictValue
from crystflux.v1.core.void_reason import VoidReason


def test_latent_void_reason_missing_key_opt_in() -> None:
    value = Crystallizer.latent({"老子": {"name": "laozi"}}, void_reasoning=True)
    voided = value.get("弟子").get("name")
    assert voided.is_void()
    assert voided.void_reason() is VoidReason.MISSING_KEY
    # chaining keeps the same reason
    assert voided.get("domain").void_reason() is VoidReason.MISSING_KEY


def test_latent_void_reason_non_array_operation_map_and_filter() -> None:
    value = Crystallizer.latent({"道": "tao"}, void_reasoning=True)
    mapped = value.map(lambda v: v)  # non-array → VOID with reason
    filtered = value.filter(lambda v: True)
    assert mapped.is_void() and filtered.is_void()
    assert mapped.void_reason() is VoidReason.NON_ARRAY_OPERATION
    assert filtered.void_reason() is VoidReason.NON_ARRAY_OPERATION


def test_dream_desire_call_sets_reason_and_chain_steps() -> None:
    with enable_dream_mode():
        dream = Crystallizer.dream({"道": 1, "sage": "laozi"}, void_reasoning=True)
        voided = dream.nonexistent().get("anything")
    assert isinstance(voided, DreamValue)
    assert voided.is_void()
    assert voided.void_reason() is VoidReason.DESIRE_CALL
    assert getattr(voided, "chain_steps") == ("nonexistent",)


def test_flag_off_preserves_void_singleton_and_no_reason() -> None:
    value = Crystallizer.latent({"k": "v"})
    voided = value.get("missing")
    assert voided is VOID
    assert voided.void_reason() is None
    strict = Crystallizer.strict({"k": "v"})
    assert isinstance(strict, StrictValue)
