"""Coverage for _validate_subscription_policy (PR #4300 review).

News subscriptions persist a fixed engine + LLM provider that run on a
schedule. This validator rejects a forbidden config at create/update time
(the factory PEP is only the execution-time backstop). Returns a
human-readable reason string on rejection, or None when allowed / when the
settings backend is unavailable (best-effort).

Source: src/local_deep_research/news/api.py
"""

from unittest.mock import Mock, patch

from local_deep_research.news.api import _validate_subscription_policy


def _mgr(snapshot, primary="arxiv"):
    m = Mock()
    m.get_settings_snapshot.return_value = snapshot
    m.get_setting.side_effect = lambda key, default=None: (
        primary if key == "search.tool" else default
    )
    return m


def _patch_mgr(manager):
    return patch(
        "local_deep_research.utilities.db_utils.get_settings_manager",
        return_value=manager,
    )


class TestValidateSubscriptionPolicy:
    def test_allowed_engine_returns_none(self):
        with _patch_mgr(_mgr({"policy.egress_scope": "public_only"})):
            assert (
                _validate_subscription_policy(Mock(), "u", "arxiv", None)
                is None
            )

    def test_forbidden_engine_returns_reason(self):
        # PUBLIC_ONLY + local engine (library) => rejected.
        with _patch_mgr(_mgr({"policy.egress_scope": "public_only"})):
            reason = _validate_subscription_policy(Mock(), "u", "library", None)
        assert reason is not None
        assert "not permitted" in reason

    def test_corrupt_scope_returns_reason(self):
        with _patch_mgr(_mgr({"policy.egress_scope": "garbage"})):
            reason = _validate_subscription_policy(Mock(), "u", "arxiv", None)
        assert reason is not None
        assert "egress policy refused" in reason

    def test_cloud_llm_provider_denied_under_require_local(self):
        # require_local_llm + a cloud provider => provider rejected.
        snap = {
            "policy.egress_scope": "both",
            "llm.require_local_endpoint": True,
        }
        with _patch_mgr(_mgr(snap)):
            reason = _validate_subscription_policy(Mock(), "u", None, "openai")
        assert reason is not None
        assert "provider" in reason.lower()

    def test_non_dict_snapshot_skips(self):
        # Settings backend unavailable => best-effort skip (None).
        with _patch_mgr(_mgr(None)):
            assert (
                _validate_subscription_policy(Mock(), "u", "library", None)
                is None
            )

    def test_local_llm_provider_allowed_under_require_local(self):
        snap = {
            "policy.egress_scope": "both",
            "llm.require_local_endpoint": True,
        }
        with _patch_mgr(_mgr(snap)):
            # ollama is a localhost-default provider => allowed.
            assert (
                _validate_subscription_policy(Mock(), "u", None, "ollama")
                is None
            )
