"""
Unit tests for pyWebLayout.concrete.box module.
Tests the Box class which handles basic box model rendering with alignment.
"""

import unittest
import numpy as np
from PIL import Image
from unittest.mock import Mock

from pyWebLayout.concrete.box import Box
from pyWebLayout.style import Alignment


class TestBox(unittest.TestCase):
    """Test cases for the Box class"""

    def setUp(self):
        """Set up test fixtures"""
        self.origin = (10, 20)
        self.size = (100, 50)
        self.callback = Mock()

    def test_box_initialization_basic(self):
        """Test basic box initialization"""
        box = Box(self.origin, self.size)

        np.testing.assert_array_equal(box._origin, np.array([10, 20]))
        np.testing.assert_array_equal(box._size, np.array([100, 50]))
        np.testing.assert_array_equal(box._end, np.array([110, 70]))
        self.assertIsNone(box._callback)
        self.assertIsNone(box._sheet)
        self.assertIsNone(box._mode)
        self.assertEqual(box._halign, Alignment.CENTER)
        self.assertEqual(box._valign, Alignment.CENTER)

    def test_box_initialization_with_callback(self):
        """Test box initialization with callback"""
        box = Box(self.origin, self.size, callback=self.callback)

        self.assertEqual(box._callback, self.callback)

    def test_box_initialization_with_sheet(self):
        """Test box initialization with image sheet"""
        sheet = Image.new('RGBA', (200, 100), (255, 255, 255, 255))
        box = Box(self.origin, self.size, sheet=sheet)

        self.assertEqual(box._sheet, sheet)
        self.assertEqual(box._mode, 'RGBA')

    def test_box_initialization_with_mode(self):
        """Test box initialization with explicit mode"""
        box = Box(self.origin, self.size, mode='RGB')

        self.assertEqual(box._mode, 'RGB')

    def test_box_initialization_with_alignment(self):
        """Test box initialization with custom alignment"""
        box = Box(self.origin, self.size, halign=Alignment.LEFT, valign=Alignment.TOP)

        self.assertEqual(box._halign, Alignment.LEFT)
        self.assertEqual(box._valign, Alignment.TOP)

    def test_in_shape_point_inside(self):
        """Test in_shape method with point inside box"""
        box = Box(self.origin, self.size)

        # Test point inside
        self.assertTrue(box.in_shape(np.array([50, 40])))
        self.assertTrue(box.in_shape(np.array([10, 20])))  # Top-left corner
        self.assertTrue(box.in_shape(np.array([109, 69])))  # Just inside bottom-right

    def test_in_shape_point_outside(self):
        """Test in_shape method with point outside box"""
        box = Box(self.origin, self.size)

        # Test points outside
        self.assertFalse(box.in_shape(np.array([5, 15])))   # Before origin
        self.assertFalse(box.in_shape(np.array([110, 70])))  # At end (exclusive)
        self.assertFalse(box.in_shape(np.array([150, 100])))  # Far outside

    def test_in_shape_multiple_points(self):
        """Test in_shape method with array of points"""
        box = Box(self.origin, self.size)

        points = np.array([[50, 40], [5, 15], [109, 69], [110, 70]])
        result = box.in_shape(points)

        np.testing.assert_array_equal(result, [True, False, True, False])

    def test_properties_access(self):
        """Test that properties can be accessed correctly"""
        box = Box(self.origin, self.size, callback=self.callback)

        # Test that origin property works (should be available via inheritance)
        np.testing.assert_array_equal(box._origin, np.array([10, 20]))
        np.testing.assert_array_equal(box._size, np.array([100, 50]))


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