"""Tests for the update manager UI dialogs."""

import pytest
from PySide6.QtCore import Qt
from PySide6.QtTest import QTest
from PySide6.QtWidgets import QApplication, QMessageBox

from webdrop_bridge.ui.update_manager_ui import (
    CheckingDialog,
    DownloadingDialog,
    ErrorDialog,
    InstallDialog,
    NoUpdateDialog,
    UpdateAvailableDialog,
)


@pytest.fixture
def qapp(qapp):
    """Provide QApplication instance."""
    return qapp


class TestCheckingDialog:
    """Tests for CheckingDialog."""

    def test_dialog_creation(self, qapp):
        """Test dialog can be created."""
        dialog = CheckingDialog()
        assert dialog is not None
        assert dialog.windowTitle() == "Checking for Updates"

    def test_progress_bar_animated(self, qapp):
        """Test progress bar is animated (maximum = 0)."""
        dialog = CheckingDialog()
        assert dialog.progress.maximum() == 0

    def test_dialog_modal(self, qapp):
        """Test dialog is modal."""
        dialog = CheckingDialog()
        assert dialog.isModal()

    def test_no_close_button(self, qapp):
        """Test dialog has no close button."""
        dialog = CheckingDialog()
        # WindowCloseButtonHint should be removed
        assert not (dialog.windowFlags() & Qt.WindowType.WindowCloseButtonHint)


class TestUpdateAvailableDialog:
    """Tests for UpdateAvailableDialog."""

    def test_dialog_creation(self, qapp):
        """Test dialog can be created."""
        dialog = UpdateAvailableDialog("0.0.2", "## Changes\n- Bug fixes")
        assert dialog is not None
        assert dialog.windowTitle() == "Update Available"

    def test_version_displayed(self, qapp):
        """Test version is displayed in dialog."""
        dialog = UpdateAvailableDialog("0.0.2", "## Changes")
        # The version should be in the dialog
        assert dialog is not None

    def test_changelog_displayed(self, qapp):
        """Test changelog is displayed."""
        changelog = "## Changes\n- Bug fixes\n- New features"
        dialog = UpdateAvailableDialog("0.0.2", changelog)
        assert dialog.changelog.toPlainText() == changelog

    def test_changelog_read_only(self, qapp):
        """Test changelog is read-only."""
        dialog = UpdateAvailableDialog("0.0.2", "Changes")
        assert dialog.changelog.isReadOnly()

    def test_signals_emitted_update_now(self, qapp, qtbot):
        """Test update now signal is emitted."""
        dialog = UpdateAvailableDialog("0.0.2", "Changes")

        with qtbot.waitSignal(dialog.update_now):
            dialog.update_now_btn.click()

    def test_signals_emitted_update_later(self, qapp, qtbot):
        """Test update later signal is emitted."""
        dialog = UpdateAvailableDialog("0.0.2", "Changes")

        with qtbot.waitSignal(dialog.update_later):
            dialog.update_later_btn.click()


class TestDownloadingDialog:
    """Tests for DownloadingDialog."""

    def test_dialog_creation(self, qapp):
        """Test dialog can be created."""
        dialog = DownloadingDialog()
        assert dialog is not None
        assert dialog.windowTitle() == "Downloading Update"

    def test_progress_bar_initialized(self, qapp):
        """Test progress bar is initialized correctly."""
        dialog = DownloadingDialog()
        assert dialog.progress.minimum() == 0
        assert dialog.progress.maximum() == 100
        assert dialog.progress.value() == 0

    def test_set_progress(self, qapp):
        """Test progress can be updated."""
        dialog = DownloadingDialog()
        dialog.set_progress(50, 100)
        assert dialog.progress.value() == 50

    def test_set_progress_formatting(self, qapp):
        """Test progress displays size in MB."""
        dialog = DownloadingDialog()
        # 10 MB of 100 MB
        dialog.set_progress(10 * 1024 * 1024, 100 * 1024 * 1024)
        assert "10.0 MB" in dialog.size_label.text()
        assert "100.0 MB" in dialog.size_label.text()

    def test_set_filename(self, qapp):
        """Test filename can be set."""
        dialog = DownloadingDialog()
        dialog.set_filename("WebDropBridge.msi")
        assert "WebDropBridge.msi" in dialog.file_label.text()

    def test_cancel_signal(self, qapp, qtbot):
        """Test cancel signal is emitted."""
        dialog = DownloadingDialog()

        with qtbot.waitSignal(dialog.cancel_download):
            dialog.cancel_btn.click()

    def test_no_close_button(self, qapp):
        """Test dialog has no close button."""
        dialog = DownloadingDialog()
        assert not (dialog.windowFlags() & Qt.WindowType.WindowCloseButtonHint)


class TestInstallDialog:
    """Tests for InstallDialog."""

    def test_dialog_creation(self, qapp):
        """Test dialog can be created."""
        dialog = InstallDialog()
        assert dialog is not None
        assert dialog.windowTitle() == "Install Update"

    def test_install_signal(self, qapp, qtbot):
        """Test install signal is emitted."""
        dialog = InstallDialog()

        with qtbot.waitSignal(dialog.install_now):
            dialog.install_btn.click()

    def test_cancel_button(self, qapp):
        """Test cancel button exists."""
        dialog = InstallDialog()
        assert dialog.cancel_btn is not None

    def test_warning_displayed(self, qapp):
        """Test warning about unsaved changes is displayed."""
        dialog = InstallDialog()
        # Warning should be in the dialog
        assert dialog is not None


class TestNoUpdateDialog:
    """Tests for NoUpdateDialog."""

    def test_dialog_creation(self, qapp):
        """Test dialog can be created."""
        dialog = NoUpdateDialog()
        assert dialog is not None
        assert dialog.windowTitle() == "No Updates Available"

    def test_dialog_modal(self, qapp):
        """Test dialog is modal."""
        dialog = NoUpdateDialog()
        assert dialog.isModal()


class TestErrorDialog:
    """Tests for ErrorDialog."""

    def test_dialog_creation(self, qapp):
        """Test dialog can be created."""
        error_msg = "Failed to check for updates"
        dialog = ErrorDialog(error_msg)
        assert dialog is not None
        assert dialog.windowTitle() == "Update Failed"

    def test_error_message_displayed(self, qapp):
        """Test error message is displayed."""
        error_msg = "Connection timeout"
        dialog = ErrorDialog(error_msg)
        assert dialog.error_text.toPlainText() == error_msg

    def test_error_message_read_only(self, qapp):
        """Test error message is read-only."""
        dialog = ErrorDialog("Error")
        assert dialog.error_text.isReadOnly()

    def test_retry_signal(self, qapp, qtbot):
        """Test retry signal is emitted."""
        dialog = ErrorDialog("Error")

        with qtbot.waitSignal(dialog.retry):
            dialog.retry_btn.click()

    def test_manual_download_signal(self, qapp, qtbot):
        """Test manual download signal is emitted."""
        dialog = ErrorDialog("Error")

        with qtbot.waitSignal(dialog.manual_download):
            dialog.manual_btn.click()
