"""
Unit tests for pyWebLayout style objects.

Tests the Font class and style enums for proper functionality and immutability.
"""

import unittest
from pyWebLayout.style import Font, FontStyle, FontWeight, TextDecoration
from pyWebLayout.style import Alignment


class TestStyleObjects(unittest.TestCase):
    """Test cases for pyWebLayout style objects."""

    def test_font_weight_enum(self):
        """Test FontWeight enum values."""
        self.assertEqual(FontWeight.NORMAL.value, "normal")
        self.assertEqual(FontWeight.BOLD.value, "bold")

        # Test that all expected values exist
        weights = [FontWeight.NORMAL, FontWeight.BOLD]
        self.assertEqual(len(weights), 2)

    def test_font_style_enum(self):
        """Test FontStyle enum values."""
        self.assertEqual(FontStyle.NORMAL.value, "normal")
        self.assertEqual(FontStyle.ITALIC.value, "italic")

        # Test that all expected values exist
        styles = [FontStyle.NORMAL, FontStyle.ITALIC]
        self.assertEqual(len(styles), 2)

    def test_text_decoration_enum(self):
        """Test TextDecoration enum values."""
        self.assertEqual(TextDecoration.NONE.value, "none")
        self.assertEqual(TextDecoration.UNDERLINE.value, "underline")
        self.assertEqual(TextDecoration.STRIKETHROUGH.value, "strikethrough")

        # Test that all expected values exist
        decorations = [
            TextDecoration.NONE,
            TextDecoration.UNDERLINE,
            TextDecoration.STRIKETHROUGH]
        self.assertEqual(len(decorations), 3)

    def test_alignment_enum(self):
        """Test Alignment enum values."""
        self.assertEqual(Alignment.LEFT.value, "left")
        self.assertEqual(Alignment.CENTER.value, "center")
        self.assertEqual(Alignment.RIGHT.value, "right")
        self.assertEqual(Alignment.TOP.value, "top")
        self.assertEqual(Alignment.BOTTOM.value, "bottom")
        self.assertEqual(Alignment.JUSTIFY.value, "justify")
        self.assertEqual(Alignment.MIDDLE.value, "middle")

    def test_font_initialization_defaults(self):
        """Test Font initialization with default values."""
        font = Font()

        self.assertIsNone(font._font_path)
        self.assertEqual(font.font_size, 16)
        self.assertEqual(font.colour, (0, 0, 0))
        self.assertEqual(font.color, (0, 0, 0))  # Alias
        self.assertEqual(font.weight, FontWeight.NORMAL)
        self.assertEqual(font.style, FontStyle.NORMAL)
        self.assertEqual(font.decoration, TextDecoration.NONE)
        self.assertEqual(font.background, (255, 255, 255, 0))  # Transparent
        self.assertEqual(font.language, "en_EN")

    def test_font_initialization_custom(self):
        """Test Font initialization with custom values."""
        font = Font(
            font_path="/path/to/font.ttf",
            font_size=16,
            colour=(255, 0, 0),
            weight=FontWeight.BOLD,
            style=FontStyle.ITALIC,
            decoration=TextDecoration.UNDERLINE,
            background=(255, 255, 0, 255),
            language="fr_FR"
        )

        self.assertEqual(font._font_path, "/path/to/font.ttf")
        self.assertEqual(font.font_size, 16)
        self.assertEqual(font.colour, (255, 0, 0))
        self.assertEqual(font.weight, FontWeight.BOLD)
        self.assertEqual(font.style, FontStyle.ITALIC)
        self.assertEqual(font.decoration, TextDecoration.UNDERLINE)
        self.assertEqual(font.background, (255, 255, 0, 255))
        self.assertEqual(font.language, "fr_FR")

    def test_font_with_methods(self):
        """Test Font immutable modification methods."""
        original_font = Font(
            font_size=12,
            colour=(0, 0, 0),
            weight=FontWeight.NORMAL,
            style=FontStyle.NORMAL,
            decoration=TextDecoration.NONE
        )

        # Test with_size
        size_font = original_font.with_size(16)
        self.assertEqual(size_font.font_size, 16)
        self.assertEqual(original_font.font_size, 12)  # Original unchanged
        self.assertEqual(size_font.colour, (0, 0, 0))  # Other properties preserved

        # Test with_colour
        color_font = original_font.with_colour((255, 0, 0))
        self.assertEqual(color_font.colour, (255, 0, 0))
        self.assertEqual(original_font.colour, (0, 0, 0))  # Original unchanged
        self.assertEqual(color_font.font_size, 12)  # Other properties preserved

        # Test with_weight
        weight_font = original_font.with_weight(FontWeight.BOLD)
        self.assertEqual(weight_font.weight, FontWeight.BOLD)
        self.assertEqual(original_font.weight, FontWeight.NORMAL)  # Original unchanged

        # Test with_style
        style_font = original_font.with_style(FontStyle.ITALIC)
        self.assertEqual(style_font.style, FontStyle.ITALIC)
        self.assertEqual(original_font.style, FontStyle.NORMAL)  # Original unchanged

        # Test with_decoration
        decoration_font = original_font.with_decoration(TextDecoration.UNDERLINE)
        self.assertEqual(decoration_font.decoration, TextDecoration.UNDERLINE)
        self.assertEqual(
            original_font.decoration,
            TextDecoration.NONE)  # Original unchanged

    def test_font_property_access(self):
        """Test Font property access methods."""
        font = Font(
            font_size=20,
            colour=(128, 128, 128),
            weight=FontWeight.BOLD,
            style=FontStyle.ITALIC,
            decoration=TextDecoration.STRIKETHROUGH
        )

        # Test all property getters
        self.assertEqual(font.font_size, 20)
        self.assertEqual(font.colour, (128, 128, 128))
        self.assertEqual(font.color, (128, 128, 128))  # Alias
        self.assertEqual(font.weight, FontWeight.BOLD)
        self.assertEqual(font.style, FontStyle.ITALIC)
        self.assertEqual(font.decoration, TextDecoration.STRIKETHROUGH)

        # Test that font object is accessible
        self.assertIsNotNone(font.font)

    def test_font_immutability(self):
        """Test that Font objects behave immutably."""
        font1 = Font(font_size=12, colour=(0, 0, 0))
        font2 = font1.with_size(16)
        font3 = font2.with_colour((255, 0, 0))

        # Each should be different objects
        self.assertIsNot(font1, font2)
        self.assertIsNot(font2, font3)
        self.assertIsNot(font1, font3)

        # Original properties should be unchanged
        self.assertEqual(font1.font_size, 12)
        self.assertEqual(font1.colour, (0, 0, 0))

        self.assertEqual(font2.font_size, 16)
        self.assertEqual(font2.colour, (0, 0, 0))

        self.assertEqual(font3.font_size, 16)
        self.assertEqual(font3.colour, (255, 0, 0))

    def test_background_handling(self):
        """Test background color handling."""
        # Test default transparent background
        font1 = Font()
        self.assertEqual(font1.background, (255, 255, 255, 0))

        # Test explicit background
        font2 = Font(background=(255, 0, 0, 128))
        self.assertEqual(font2.background, (255, 0, 0, 128))

        # Test None background becomes transparent
        font3 = Font(background=None)
        self.assertEqual(font3.background, (255, 255, 255, 0))


if __name__ == '__main__':
    unittest.main()
