"""
Tests for loading_widget module
"""

import pytest
from unittest.mock import Mock, patch
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QWidget


class TestLoadingWidget:
    """Tests for LoadingWidget class"""

    def test_init(self, qtbot):
        """Test LoadingWidget initialization"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        assert widget.isHidden()
        assert widget.width() == 280
        assert widget.height() == 80

    def test_init_with_parent(self, qtbot):
        """Test LoadingWidget initialization with parent"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)

        assert widget.parent() == parent

    def test_opacity_property(self, qtbot):
        """Test opacity property getter and setter"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        # Test getter
        assert widget.opacity == 1.0

        # Test setter
        widget.opacity = 0.5
        assert widget.opacity == 0.5

    def test_show_loading(self, qtbot):
        """Test showing the loading widget"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)

        widget.show_loading("Processing...")

        assert widget.isVisible()
        assert widget._status_label.text() == "Processing..."
        assert widget._progress_bar.value() == 0

    def test_show_loading_default_message(self, qtbot):
        """Test showing loading widget with default message"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)

        widget.show_loading()

        assert widget._status_label.text() == "Loading..."

    def test_hide_loading(self, qtbot):
        """Test hiding the loading widget"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)

        # Show first
        widget.show_loading()
        assert widget.isVisible()

        # Then hide
        widget.hide_loading()

        # Animation starts but widget may not be immediately hidden
        # Just verify the method runs without error

    def test_set_status(self, qtbot):
        """Test setting status message"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        widget.set_status("Processing files...")

        assert widget._status_label.text() == "Processing files..."

    def test_set_progress(self, qtbot):
        """Test setting progress value"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        widget.set_progress(50)

        assert widget._progress_bar.value() == 50
        assert widget._progress_bar.maximum() == 100

    def test_set_progress_with_custom_maximum(self, qtbot):
        """Test setting progress with custom maximum"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        widget.set_progress(75, maximum=200)

        assert widget._progress_bar.value() == 75
        assert widget._progress_bar.maximum() == 200

    def test_set_indeterminate_true(self, qtbot):
        """Test setting indeterminate mode to True"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        widget.set_indeterminate(True)

        assert widget._progress_bar.minimum() == 0
        assert widget._progress_bar.maximum() == 0

    def test_set_indeterminate_false(self, qtbot):
        """Test setting indeterminate mode to False"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        # First set to indeterminate
        widget.set_indeterminate(True)

        # Then set back to normal
        widget.set_indeterminate(False)

        assert widget._progress_bar.minimum() == 0
        assert widget._progress_bar.maximum() == 100

    def test_reposition_with_parent(self, qtbot):
        """Test repositioning in lower-right corner of parent"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)
        widget._reposition()

        # Should be in lower-right corner with 20px margin
        expected_x = 800 - 280 - 20
        expected_y = 600 - 80 - 20

        assert widget.x() == expected_x
        assert widget.y() == expected_y

    def test_reposition_no_parent(self, qtbot):
        """Test repositioning when there's no parent"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        # Should not crash
        widget._reposition()

    def test_show_event(self, qtbot):
        """Test show event triggers repositioning"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)

        with patch.object(widget, '_reposition') as mock_reposition:
            widget.show()
            mock_reposition.assert_called()

    def test_resize_parent(self, qtbot):
        """Test resizeParent method"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)
        widget.show_loading()

        # Resize parent
        parent.resize(1000, 800)

        with patch.object(widget, '_reposition') as mock_reposition:
            widget.resizeParent()
            mock_reposition.assert_called_once()

    def test_resize_parent_when_hidden(self, qtbot):
        """Test resizeParent when widget is hidden"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)
        # Widget is hidden by default

        with patch.object(widget, '_reposition') as mock_reposition:
            widget.resizeParent()
            # Should not call reposition when hidden
            mock_reposition.assert_not_called()

    def test_fade_animation_on_show(self, qtbot):
        """Test fade animation starts on show_loading"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)

        widget.show_loading("Test")

        # Animation should be running
        assert widget._fade_animation.state() != 0  # Not stopped

    def test_fade_animation_on_hide(self, qtbot):
        """Test fade animation starts on hide_loading"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)
        widget.show_loading()

        widget.hide_loading()

        # Animation should be running
        assert widget._fade_animation.state() != 0  # Not stopped

    def test_progress_bar_format(self, qtbot):
        """Test progress bar displays percentage format"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        assert widget._progress_bar.format() == "%p%"

    def test_progress_bar_text_visible(self, qtbot):
        """Test progress bar text is visible"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        assert widget._progress_bar.isTextVisible() is True

    def test_window_flags(self, qtbot):
        """Test widget has correct window flags"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        flags = widget.windowFlags()
        assert Qt.WindowType.ToolTip in Qt.WindowType(flags)
        assert Qt.WindowType.FramelessWindowHint in Qt.WindowType(flags)

    def test_fixed_size(self, qtbot):
        """Test widget has fixed size"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        assert widget.minimumWidth() == 280
        assert widget.maximumWidth() == 280
        assert widget.minimumHeight() == 80
        assert widget.maximumHeight() == 80

    def test_sequential_show_hide(self, qtbot):
        """Test showing and hiding widget multiple times"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)

        # First cycle
        widget.show_loading("Task 1")
        widget.set_progress(50)
        widget.hide_loading()

        # Second cycle
        widget.show_loading("Task 2")
        widget.set_progress(25)
        assert widget._status_label.text() == "Task 2"
        assert widget._progress_bar.value() == 25

    def test_update_progress_while_visible(self, qtbot):
        """Test updating progress while widget is visible"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)
        widget.show_loading("Processing")

        # Update progress multiple times
        for i in range(0, 101, 10):
            widget.set_progress(i)
            assert widget._progress_bar.value() == i

    def test_status_label_alignment(self, qtbot):
        """Test status label is left-aligned"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        assert widget._status_label.alignment() == Qt.AlignmentFlag.AlignLeft

    def test_initial_opacity(self, qtbot):
        """Test initial opacity value"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        assert widget._opacity == 1.0

    def test_fade_animation_duration(self, qtbot):
        """Test fade animation has correct duration"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        widget = LoadingWidget()
        qtbot.addWidget(widget)

        assert widget._fade_animation.duration() == 300

    def test_show_loading_resets_progress(self, qtbot):
        """Test that show_loading resets progress to 0"""
        from pyPhotoAlbum.loading_widget import LoadingWidget

        parent = QWidget()
        parent.resize(800, 600)
        qtbot.addWidget(parent)

        widget = LoadingWidget(parent)

        # Set some progress
        widget.set_progress(75)

        # Show loading should reset to 0
        widget.show_loading("New task")

        assert widget._progress_bar.value() == 0
