"""
Tests for DistributionOperationsMixin
"""

import pytest
from unittest.mock import Mock, patch
from PyQt6.QtWidgets import QMainWindow
from pyPhotoAlbum.mixins.operations.distribution_ops import DistributionOperationsMixin
from pyPhotoAlbum.models import ImageData
from pyPhotoAlbum.commands import CommandHistory


class TestDistributionWindow(DistributionOperationsMixin, QMainWindow):
    """Test window with distribution operations mixin"""

    def __init__(self):
        super().__init__()
        self.gl_widget = Mock()
        self.gl_widget.selected_elements = set()
        self.project = Mock()
        self.project.history = CommandHistory()
        self._update_view_called = False
        self._status_message = None
        self._require_selection_count = None

    def require_selection(self, min_count=1):
        self._require_selection_count = min_count
        return len(self.gl_widget.selected_elements) >= min_count

    def update_view(self):
        self._update_view_called = True

    def show_status(self, message, timeout=0):
        self._status_message = message


class TestGetSelectedElementsList:
    """Test _get_selected_elements_list helper"""

    def test_get_selected_elements_list(self, qtbot):
        window = TestDistributionWindow()
        qtbot.addWidget(window)

        element1 = ImageData(image_path="/test1.jpg", x=0, y=0, width=100, height=100)
        element2 = ImageData(image_path="/test2.jpg", x=100, y=100, width=100, height=100)
        element3 = ImageData(image_path="/test3.jpg", x=200, y=200, width=100, height=100)

        window.gl_widget.selected_elements = {element1, element2, element3}

        result = window._get_selected_elements_list()

        assert isinstance(result, list)
        assert len(result) == 3


class TestDistributeHorizontally:
    """Test distribute_horizontally method"""

    @patch("pyPhotoAlbum.mixins.operations.distribution_ops.AlignmentManager")
    def test_distribute_horizontally_success(self, mock_manager, qtbot):
        window = TestDistributionWindow()
        qtbot.addWidget(window)

        element1 = ImageData(image_path="/test1.jpg", x=0, y=0, width=100, height=100)
        element2 = ImageData(image_path="/test2.jpg", x=150, y=0, width=100, height=100)
        element3 = ImageData(image_path="/test3.jpg", x=500, y=0, width=100, height=100)

        window.gl_widget.selected_elements = {element1, element2, element3}

        mock_manager.distribute_horizontally.return_value = [
            (element1, (0, 0)),
            (element2, (150, 0)),
            (element3, (500, 0)),
        ]

        window.distribute_horizontally()

        assert mock_manager.distribute_horizontally.called
        assert window._update_view_called
        assert "distributed" in window._status_message.lower()
        assert "horizontally" in window._status_message.lower()

    def test_distribute_horizontally_insufficient_selection(self, qtbot):
        window = TestDistributionWindow()
        qtbot.addWidget(window)

        element1 = ImageData(image_path="/test1.jpg", x=0, y=0, width=100, height=100)
        element2 = ImageData(image_path="/test2.jpg", x=100, y=100, width=100, height=100)

        window.gl_widget.selected_elements = {element1, element2}

        window.distribute_horizontally()

        assert window._require_selection_count == 3
        assert not window._update_view_called


class TestDistributeVertically:
    """Test distribute_vertically method"""

    @patch("pyPhotoAlbum.mixins.operations.distribution_ops.AlignmentManager")
    def test_distribute_vertically_success(self, mock_manager, qtbot):
        window = TestDistributionWindow()
        qtbot.addWidget(window)

        element1 = ImageData(image_path="/test1.jpg", x=0, y=0, width=100, height=100)
        element2 = ImageData(image_path="/test2.jpg", x=0, y=150, width=100, height=100)
        element3 = ImageData(image_path="/test3.jpg", x=0, y=500, width=100, height=100)

        window.gl_widget.selected_elements = {element1, element2, element3}

        mock_manager.distribute_vertically.return_value = [
            (element1, (0, 0)),
            (element2, (0, 150)),
            (element3, (0, 500)),
        ]

        window.distribute_vertically()

        assert mock_manager.distribute_vertically.called
        assert window._update_view_called
        assert "vertically" in window._status_message.lower()


class TestSpaceHorizontally:
    """Test space_horizontally method"""

    @patch("pyPhotoAlbum.mixins.operations.distribution_ops.AlignmentManager")
    def test_space_horizontally_success(self, mock_manager, qtbot):
        window = TestDistributionWindow()
        qtbot.addWidget(window)

        element1 = ImageData(image_path="/test1.jpg", x=0, y=0, width=100, height=100)
        element2 = ImageData(image_path="/test2.jpg", x=100, y=0, width=100, height=100)
        element3 = ImageData(image_path="/test3.jpg", x=200, y=0, width=100, height=100)

        window.gl_widget.selected_elements = {element1, element2, element3}

        mock_manager.space_horizontally.return_value = [(element1, (0, 0)), (element2, (100, 0)), (element3, (200, 0))]

        window.space_horizontally()

        assert mock_manager.space_horizontally.called
        assert window._update_view_called
        assert "spaced" in window._status_message.lower()


class TestSpaceVertically:
    """Test space_vertically method"""

    @patch("pyPhotoAlbum.mixins.operations.distribution_ops.AlignmentManager")
    def test_space_vertically_success(self, mock_manager, qtbot):
        window = TestDistributionWindow()
        qtbot.addWidget(window)

        element1 = ImageData(image_path="/test1.jpg", x=0, y=0, width=100, height=100)
        element2 = ImageData(image_path="/test2.jpg", x=0, y=100, width=100, height=100)
        element3 = ImageData(image_path="/test3.jpg", x=0, y=200, width=100, height=100)

        window.gl_widget.selected_elements = {element1, element2, element3}

        mock_manager.space_vertically.return_value = [(element1, (0, 0)), (element2, (0, 100)), (element3, (0, 200))]

        window.space_vertically()

        assert mock_manager.space_vertically.called
        assert window._update_view_called


class TestDistributionCommandPattern:
    """Test distribution operations with command pattern"""

    @patch("pyPhotoAlbum.mixins.operations.distribution_ops.AlignmentManager")
    def test_distribution_creates_command(self, mock_manager, qtbot):
        window = TestDistributionWindow()
        qtbot.addWidget(window)

        element1 = ImageData(image_path="/test1.jpg", x=0, y=0, width=100, height=100)
        element2 = ImageData(image_path="/test2.jpg", x=100, y=0, width=100, height=100)
        element3 = ImageData(image_path="/test3.jpg", x=200, y=0, width=100, height=100)

        window.gl_widget.selected_elements = {element1, element2, element3}

        mock_manager.distribute_horizontally.return_value = [
            (element1, (0, 0)),
            (element2, (100, 0)),
            (element3, (200, 0)),
        ]

        assert not window.project.history.can_undo()

        window.distribute_horizontally()

        assert window.project.history.can_undo()
