# #region Test.TaskCleanupService [C:3] [TYPE Module] [SEMANTICS test,task,cleanup,retention]
# @BRIEF Tests for core/task_manager/cleanup.py — TaskCleanupService.
# @RELATION BINDS_TO -> [TaskCleanupModule]

from pathlib import Path
import sys

sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))

from unittest.mock import MagicMock, patch
import pytest


# #region test_task_cleanup_service [C:2] [TYPE Function]
# @BRIEF Test TaskCleanupService.run_cleanup and delete_task_with_logs.
class TestTaskCleanupService:
    @pytest.fixture
    def mock_persistence(self):
        return MagicMock()

    @pytest.fixture
    def mock_log_persistence(self):
        return MagicMock()

    @pytest.fixture
    def mock_config_manager(self):
        mgr = MagicMock()
        mgr.get_config.return_value.settings.task_retention_days = 30
        mgr.get_config.return_value.settings.task_retention_limit = 3
        return mgr

    @pytest.fixture
    def service(self, mock_persistence, mock_log_persistence, mock_config_manager):
        from src.core.task_manager.cleanup import TaskCleanupService
        return TaskCleanupService(mock_persistence, mock_log_persistence, mock_config_manager)

    def test_init_stores_dependencies(self, service, mock_persistence, mock_log_persistence, mock_config_manager):
        assert service.persistence_service is mock_persistence
        assert service.log_persistence_service is mock_log_persistence
        assert service.config_manager is mock_config_manager

    def test_run_cleanup_no_tasks_to_delete(self, service, mock_persistence, mock_log_persistence):
        mock_persistence.load_tasks.return_value = []
        service.run_cleanup()
        mock_persistence.load_tasks.assert_called_once_with(limit=1000)
        mock_log_persistence.delete_logs_for_tasks.assert_not_called()
        mock_persistence.delete_tasks.assert_not_called()

    def test_run_cleanup_deletes_excess_tasks(self, service, mock_persistence, mock_log_persistence):
        from src.core.task_manager.models import Task
        tasks = [Task(plugin_id="p", params={}) for _ in range(5)]
        mock_persistence.load_tasks.return_value = tasks
        service.run_cleanup()
        # 5 tasks, limit=3, so should delete 2
        mock_log_persistence.delete_logs_for_tasks.assert_called_once()
        mock_persistence.delete_tasks.assert_called_once()
        deleted_ids = mock_persistence.delete_tasks.call_args[0][0]
        assert len(deleted_ids) == 2

    def test_run_cleanup_under_limit_does_nothing(self, service, mock_persistence):
        from src.core.task_manager.models import Task
        tasks = [Task(plugin_id="p", params={}) for _ in range(2)]
        mock_persistence.load_tasks.return_value = tasks
        service.run_cleanup()
        mock_persistence.delete_tasks.assert_not_called()

    def test_delete_task_with_logs(self, service, mock_persistence, mock_log_persistence):
        service.delete_task_with_logs("task-1")
        mock_log_persistence.delete_logs_for_task.assert_called_once_with("task-1")
        mock_persistence.delete_tasks.assert_called_once_with(["task-1"])

    def test_run_cleanup_with_zero_limit(self, service, mock_persistence):
        from src.core.task_manager.models import Task
        tasks = [Task(plugin_id="p", params={}) for _ in range(1)]
        mock_persistence.load_tasks.return_value = tasks
        # Override retention limit to 0
        service.config_manager.get_config.return_value.settings.task_retention_limit = 0
        service.run_cleanup()
        mock_persistence.delete_tasks.assert_called_once()
        deleted_ids = mock_persistence.delete_tasks.call_args[0][0]
        assert len(deleted_ids) == 1
# #endregion test_task_cleanup_service
# #endregion Test.TaskCleanupService
