"""Tests for dream_context module."""

import pytest

from crystflux.v1 import Crystallizer
from crystflux.v1.adapters import enable_dream_mode, with_dream_mode
from crystflux.v1.adapters.dream_context import require_dream_mode
from crystflux.v1.boundary.error_contracts import ModeNotSupportedError


def test_require_dream_mode_raises_when_not_enabled() -> None:
    """Verify require_dream_mode() raises when Dream mode is not enabled."""
    with pytest.raises(ModeNotSupportedError, match="Crystallizer.dream.*locked"):
        require_dream_mode()


def test_require_dream_mode_succeeds_when_enabled() -> None:
    """Verify require_dream_mode() does not raise when Dream mode is enabled."""
    with enable_dream_mode():
        require_dream_mode()  # Should not raise


def test_enable_dream_mode_context_manager() -> None:
    """Test enable_dream_mode() context manager basic functionality."""
    from crystflux.v1.adapters import enable_dream_mode

    # Outside context: should raise
    with pytest.raises(ModeNotSupportedError):
        Crystallizer.dream({"a": 1})

    # Inside context: should work
    with enable_dream_mode():
        dream = Crystallizer.dream({"a": 1})
        assert dream.get("a").as_int() == 1


def test_decorator_enables_dream_mode() -> None:
    """Test with_dream_mode() decorator enables Dream mode for decorated function."""

    @with_dream_mode
    def create_dream_value() -> None:
        dream = Crystallizer.dream({"test": 123})
        assert dream.get("test").as_int() == 123

    create_dream_value()


def test_nested_enable_dream_mode() -> None:
    """Test nested enable_dream_mode() contexts."""
    from crystflux.v1.adapters import enable_dream_mode

    # Inner context should work
    with enable_dream_mode():
        dream1 = Crystallizer.dream({"outer": 1})
        with enable_dream_mode():
            dream2 = Crystallizer.dream({"inner": 2})
            assert dream2.get("inner").as_int() == 2
        # After inner context exits, outer should still work
        assert dream1.get("outer").as_int() == 1
