"""
Tests for _get_context_window_for_provider() in llm_config.py.

Covers the 3 branches: local providers (default 8192),
cloud unrestricted (returns None), cloud restricted (default 128000).
"""

from unittest.mock import patch


def _get_fn():
    from local_deep_research.config.llm_config import (
        _get_context_window_for_provider,
    )

    return _get_context_window_for_provider


class TestLocalProviders:
    """Local providers (ollama, llamacpp, lmstudio) use smaller default."""

    @patch(
        "local_deep_research.config.thread_settings.get_setting_from_snapshot",
        return_value=4096,
    )
    def test_ollama_returns_default(self, mock_setting):
        result = _get_fn()("ollama")
        assert result == 4096
        mock_setting.assert_called_once_with(
            "llm.local_context_window_size", 8192, settings_snapshot=None
        )

    @patch(
        "local_deep_research.config.thread_settings.get_setting_from_snapshot",
        return_value=4096,
    )
    def test_llamacpp_returns_default(self, mock_setting):
        assert _get_fn()("llamacpp") == 4096

    @patch(
        "local_deep_research.config.thread_settings.get_setting_from_snapshot",
        return_value=4096,
    )
    def test_lmstudio_returns_default(self, mock_setting):
        assert _get_fn()("lmstudio") == 4096

    @patch(
        "local_deep_research.config.thread_settings.get_setting_from_snapshot",
        return_value=8192,
    )
    def test_snapshot_overrides_local_window(self, mock_setting):
        result = _get_fn()(
            "ollama", settings_snapshot={"llm.local_context_window_size": 8192}
        )
        assert result == 8192

    @patch(
        "local_deep_research.config.thread_settings.get_setting_from_snapshot",
        return_value="4096",
    )
    def test_string_coerced_to_int(self, mock_setting):
        """String values are coerced to int."""
        result = _get_fn()("ollama")
        assert result == 4096
        assert isinstance(result, int)

    @patch(
        "local_deep_research.config.thread_settings.get_setting_from_snapshot",
        return_value=None,
    )
    def test_none_falls_back_to_default_8192(self, mock_setting):
        """None value → fallback to 8192."""
        result = _get_fn()("ollama")
        assert result == 8192


class TestCloudUnrestricted:
    """Cloud providers with unrestricted=True return None."""

    @patch(
        "local_deep_research.config.thread_settings.get_setting_from_snapshot",
        return_value=True,
    )
    def test_openai_unrestricted_returns_none(self, mock_setting):
        result = _get_fn()("openai")
        assert result is None

    @patch(
        "local_deep_research.config.thread_settings.get_setting_from_snapshot",
        return_value=True,
    )
    def test_anthropic_unrestricted_returns_none(self, mock_setting):
        assert _get_fn()("anthropic") is None

    @patch(
        "local_deep_research.config.thread_settings.get_setting_from_snapshot",
        return_value=True,
    )
    def test_unknown_provider_treated_as_cloud(self, mock_setting):
        """Unknown provider goes through cloud branch."""
        assert _get_fn()("some_new_provider") is None


class TestCloudRestricted:
    """Cloud providers with unrestricted=False use configurable limit."""

    def test_cloud_restricted_returns_default_128000(self):
        """When unrestricted=False, defaults to 128000."""
        call_count = 0

        def fake_get_setting(key, default, settings_snapshot=None):
            nonlocal call_count
            call_count += 1
            if key == "llm.context_window_unrestricted":
                return False
            if key == "llm.context_window_size":
                return 128000
            return default

        with patch(
            "local_deep_research.config.thread_settings.get_setting_from_snapshot",
            side_effect=fake_get_setting,
        ):
            result = _get_fn()("openai")
            assert result == 128000

    def test_cloud_restricted_snapshot_override(self):
        """Settings snapshot overrides cloud window size."""

        def fake_get_setting(key, default, settings_snapshot=None):
            if key == "llm.context_window_unrestricted":
                return False
            if key == "llm.context_window_size":
                return 32000
            return default

        with patch(
            "local_deep_research.config.thread_settings.get_setting_from_snapshot",
            side_effect=fake_get_setting,
        ):
            result = _get_fn()(
                "openai", settings_snapshot={"llm.context_window_size": 32000}
            )
            assert result == 32000

    def test_cloud_restricted_string_coerced(self):
        """String window size coerced to int."""

        def fake_get_setting(key, default, settings_snapshot=None):
            if key == "llm.context_window_unrestricted":
                return False
            if key == "llm.context_window_size":
                return "64000"
            return default

        with patch(
            "local_deep_research.config.thread_settings.get_setting_from_snapshot",
            side_effect=fake_get_setting,
        ):
            result = _get_fn()("openai")
            assert result == 64000
            assert isinstance(result, int)

    def test_cloud_restricted_none_falls_back_to_128000(self):
        """None value → fallback to 128000."""

        def fake_get_setting(key, default, settings_snapshot=None):
            if key == "llm.context_window_unrestricted":
                return False
            if key == "llm.context_window_size":
                return None
            return default

        with patch(
            "local_deep_research.config.thread_settings.get_setting_from_snapshot",
            side_effect=fake_get_setting,
        ):
            result = _get_fn()("openai")
            assert result == 128000
