#  Copyright 2026 European Union
#  Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
#  SPDX-License-Identifier: EUPL-1.2
"""Unit tests for the Worker threading helper."""

from __future__ import annotations

from typing import Callable
from unittest.mock import Mock

import pytest

pytest.importorskip('PySide6', reason='PySide6 is required for GUI tests')

from mafw.steering_gui.threading.workers import Worker

pytestmark = pytest.mark.gui


def test_worker_passes_progress_callback() -> None:
    """Ensure Worker passes progress_callback if the function accepts it."""

    # Define a function that accepts progress_callback
    def task_with_progress(progress_callback: Callable[[int], None]) -> str:
        progress_callback(50)
        return 'Success'

    worker = Worker[str](task_with_progress)

    # Mock signals
    progress_mock = Mock()
    finished_mock = Mock()
    error_mock = Mock()

    worker.connect(progress=progress_mock, finished=finished_mock, error=error_mock)

    # Run worker synchronously
    worker.run()

    progress_mock.assert_called_with(50)
    finished_mock.assert_called_with('Success')
    error_mock.assert_not_called()


def test_worker_ignores_progress_callback_if_not_accepted() -> None:
    """Ensure Worker does not pass progress_callback if the function does not accept it."""

    # Define a function that does NOT accept progress_callback
    def task_without_progress() -> str:
        return 'Success'

    worker = Worker[str](task_without_progress)

    # Mock signals
    progress_mock = Mock()
    finished_mock = Mock()
    error_mock = Mock()

    worker.connect(progress=progress_mock, finished=finished_mock, error=error_mock)

    # Run worker synchronously
    worker.run()

    progress_mock.assert_not_called()
    finished_mock.assert_called_with('Success')
    error_mock.assert_not_called()


def test_worker_handles_args_and_kwargs() -> None:
    """Ensure Worker passes args and kwargs correctly."""

    def task_with_args(a: int, b: int, progress_callback: Callable[[int], None] | None = None) -> int:
        if progress_callback:
            progress_callback(10)
        return a + b

    worker = Worker[int](task_with_args, 2, b=3)

    progress_mock = Mock()
    finished_mock = Mock()

    worker.connect(progress=progress_mock, finished=finished_mock)

    worker.run()

    progress_mock.assert_called_with(10)
    finished_mock.assert_called_with(5)
