"""
Test file demonstrating word spacing constraints functionality.

This test shows how to use the new min/max word spacing constraints
in the style system.
"""

from pyWebLayout.style.abstract_style import AbstractStyle, AbstractStyleRegistry
from pyWebLayout.style.concrete_style import StyleResolver, RenderingContext


class TestWordSpacingConstraints:
    """Test cases for word spacing constraints feature."""

    def test_abstract_style_with_word_spacing_constraints(self):
        """Test that AbstractStyle accepts word spacing constraint fields."""
        style = AbstractStyle(
            word_spacing=5.0,
            word_spacing_min=2.0,
            word_spacing_max=10.0
        )

        assert style.word_spacing == 5.0
        assert style.word_spacing_min == 2.0
        assert style.word_spacing_max == 10.0

    def test_concrete_style_resolution_with_constraints(self):
        """Test that word spacing constraints are resolved correctly."""
        # Create rendering context
        context = RenderingContext(base_font_size=16)
        resolver = StyleResolver(context)

        # Create abstract style with constraints
        abstract_style = AbstractStyle(
            word_spacing=5.0,
            word_spacing_min=2.0,
            word_spacing_max=12.0
        )

        # Resolve to concrete style
        concrete_style = resolver.resolve_style(abstract_style)

        # Check that constraints are preserved
        assert concrete_style.word_spacing == 5.0
        assert concrete_style.word_spacing_min == 2.0
        assert concrete_style.word_spacing_max == 12.0

    def test_default_constraint_logic(self):
        """Test default constraint logic when not specified."""
        context = RenderingContext(base_font_size=16)
        resolver = StyleResolver(context)

        # Style with only base word spacing
        abstract_style = AbstractStyle(word_spacing=6.0)
        concrete_style = resolver.resolve_style(abstract_style)

        # Should apply default logic: min = base, max = base * 2
        assert concrete_style.word_spacing == 6.0
        assert concrete_style.word_spacing_min == 6.0
        assert concrete_style.word_spacing_max == 12.0

    def test_no_word_spacing_defaults(self):
        """Test defaults when no word spacing is specified."""
        context = RenderingContext(base_font_size=16)
        resolver = StyleResolver(context)

        # Style with no word spacing specified
        abstract_style = AbstractStyle()
        concrete_style = resolver.resolve_style(abstract_style)

        # Should apply font-based defaults
        assert concrete_style.word_spacing == 0.0
        assert concrete_style.word_spacing_min == 2.0  # Minimum default
        assert concrete_style.word_spacing_max == 8.0  # 50% of font size (16 * 0.5)

    def test_partial_constraints(self):
        """Test behavior when only min or max is specified."""
        context = RenderingContext(base_font_size=16)
        resolver = StyleResolver(context)

        # Only min specified
        abstract_style_min = AbstractStyle(
            word_spacing=4.0,
            word_spacing_min=3.0
        )
        concrete_style_min = resolver.resolve_style(abstract_style_min)

        assert concrete_style_min.word_spacing_min == 3.0
        assert concrete_style_min.word_spacing_max == 6.0  # 3.0 * 2

        # Only max specified
        abstract_style_max = AbstractStyle(
            word_spacing=4.0,
            word_spacing_max=8.0
        )
        concrete_style_max = resolver.resolve_style(abstract_style_max)

        assert concrete_style_max.word_spacing_min == 4.0  # max(word_spacing, 2.0)
        assert concrete_style_max.word_spacing_max == 8.0

    def test_style_registry_with_constraints(self):
        """Test that style registry handles word spacing constraints."""
        registry = AbstractStyleRegistry()

        # Create style with constraints
        style_id, style = registry.get_or_create_style(
            word_spacing=5.0,
            word_spacing_min=3.0,
            word_spacing_max=10.0
        )

        # Verify the style was created correctly
        retrieved_style = registry.get_style_by_id(style_id)
        assert retrieved_style.word_spacing == 5.0
        assert retrieved_style.word_spacing_min == 3.0
        assert retrieved_style.word_spacing_max == 10.0

    def test_em_units_in_constraints(self):
        """Test that em units work in word spacing constraints."""
        context = RenderingContext(base_font_size=16)
        resolver = StyleResolver(context)

        # Use em units
        abstract_style = AbstractStyle(
            word_spacing="0.25em",
            word_spacing_min="0.1em",
            word_spacing_max="0.5em"
        )

        concrete_style = resolver.resolve_style(abstract_style)

        # Should convert em to pixels based on font size (16px)
        assert concrete_style.word_spacing == 4.0  # 0.25 * 16
        assert concrete_style.word_spacing_min == 1.6  # 0.1 * 16
        assert concrete_style.word_spacing_max == 8.0  # 0.5 * 16


if __name__ == "__main__":
    # Run basic tests
    test = TestWordSpacingConstraints()
    test.test_abstract_style_with_word_spacing_constraints()
    test.test_concrete_style_resolution_with_constraints()
    test.test_default_constraint_logic()
    test.test_no_word_spacing_defaults()
    test.test_partial_constraints()
    test.test_style_registry_with_constraints()
    test.test_em_units_in_constraints()

    print("All word spacing constraint tests passed!")
