"""High-value edge case tests for research_scheduler module.

Covers gaps not addressed by existing tests:
- DocumentSchedulerUtil error handling in get_status
- Route blueprint registration and name
- Singleton pattern for get_document_scheduler
- trigger_manual_run error handling
"""

from unittest.mock import MagicMock, patch


class TestDocumentSchedulerUtilEdgeCases:
    """Edge cases for DocumentSchedulerUtil."""

    def test_module_importable(self):
        """research_scheduler.document_scheduler module is importable."""
        from local_deep_research.research_scheduler import document_scheduler

        assert document_scheduler is not None

    @patch(
        "local_deep_research.research_scheduler.document_scheduler.get_news_scheduler"
    )
    def test_get_status_error_returns_error_dict(self, mock_get_scheduler):
        """When scheduler raises, get_status returns error dict."""
        from local_deep_research.research_scheduler.document_scheduler import (
            DocumentSchedulerUtil,
        )

        mock_get_scheduler.side_effect = Exception("Scheduler error")

        util = DocumentSchedulerUtil()
        result = util.get_status("test_user")

        assert isinstance(result, dict)
        assert "error" in result
        assert result["is_running"] is False

    @patch(
        "local_deep_research.research_scheduler.document_scheduler.get_news_scheduler"
    )
    def test_get_status_error_dict_has_all_keys(self, mock_get_scheduler):
        """Error dict from get_status has all expected keys."""
        from local_deep_research.research_scheduler.document_scheduler import (
            DocumentSchedulerUtil,
        )

        mock_get_scheduler.side_effect = Exception("Scheduler error")

        util = DocumentSchedulerUtil()
        result = util.get_status("test_user")

        expected_keys = {
            "error",
            "is_running",
            "last_run_time",
            "next_run_time",
            "total_processed",
            "currently_processing",
            "processing_ids",
            "settings",
        }
        assert set(result.keys()) == expected_keys

    @patch(
        "local_deep_research.research_scheduler.document_scheduler.get_news_scheduler"
    )
    def test_get_status_error_dict_types(self, mock_get_scheduler):
        """Error dict values have correct types."""
        from local_deep_research.research_scheduler.document_scheduler import (
            DocumentSchedulerUtil,
        )

        mock_get_scheduler.side_effect = Exception("error")

        util = DocumentSchedulerUtil()
        result = util.get_status("test_user")

        assert isinstance(result["processing_ids"], list)
        assert isinstance(result["settings"], dict)
        assert isinstance(result["total_processed"], int)

    @patch(
        "local_deep_research.research_scheduler.document_scheduler.get_news_scheduler"
    )
    def test_trigger_manual_run_error_returns_tuple(self, mock_get_scheduler):
        """When trigger fails, returns (False, message) tuple."""
        from local_deep_research.research_scheduler.document_scheduler import (
            DocumentSchedulerUtil,
        )

        mock_get_scheduler.side_effect = Exception("error")

        util = DocumentSchedulerUtil()
        success, message = util.trigger_manual_run("test_user")

        assert success is False
        assert "Failed" in message

    @patch(
        "local_deep_research.research_scheduler.document_scheduler.get_news_scheduler"
    )
    def test_trigger_manual_run_success(self, mock_get_scheduler):
        """When trigger succeeds, returns (True, message) tuple."""
        from local_deep_research.research_scheduler.document_scheduler import (
            DocumentSchedulerUtil,
        )

        mock_scheduler = MagicMock()
        mock_scheduler.trigger_document_processing.return_value = True
        mock_get_scheduler.return_value = mock_scheduler

        util = DocumentSchedulerUtil()
        success, message = util.trigger_manual_run("test_user")

        assert success is True
        assert "successfully" in message


class TestSchedulerRouteBlueprint:
    """Test research_scheduler route blueprint."""

    def test_blueprint_importable(self):
        """Scheduler blueprint is importable."""
        from local_deep_research.research_scheduler.routes import scheduler_bp

        assert scheduler_bp is not None

    def test_blueprint_name(self):
        """Blueprint has the expected name."""
        from local_deep_research.research_scheduler.routes import scheduler_bp

        assert scheduler_bp.name == "document_scheduler"

    def test_blueprint_has_url_rules(self):
        """Blueprint has registered URL rules."""
        from local_deep_research.research_scheduler.routes import scheduler_bp

        # Deferred URLs are stored in deferred_functions
        assert len(scheduler_bp.deferred_functions) > 0


class TestDocumentSchedulerSingleton:
    """Test singleton pattern of get_document_scheduler."""

    @patch(
        "local_deep_research.research_scheduler.document_scheduler.get_news_scheduler"
    )
    def test_singleton_returns_same_instance(self, mock_get_scheduler):
        """get_document_scheduler returns same instance on repeated calls."""
        from local_deep_research.research_scheduler.document_scheduler import (
            get_document_scheduler,
        )
        import local_deep_research.research_scheduler.document_scheduler as mod

        # Reset singleton
        mod._scheduler_util_instance = None

        first = get_document_scheduler()
        second = get_document_scheduler()
        assert first is second

        # Cleanup
        mod._scheduler_util_instance = None

    def test_has_expected_methods(self):
        """DocumentSchedulerUtil has get_status and trigger_manual_run."""
        from local_deep_research.research_scheduler.document_scheduler import (
            DocumentSchedulerUtil,
        )

        assert hasattr(DocumentSchedulerUtil, "get_status")
        assert hasattr(DocumentSchedulerUtil, "trigger_manual_run")
