"""
Behavioral tests for settings_utils module.

Tests the settings utility functions used by the programmatic API.
"""


class TestExtractSettingValue:
    """Tests for extract_setting_value function."""

    def test_extracts_value_from_dict_with_value_key(self):
        """Extracts value from setting dict with 'value' key."""
        from local_deep_research.api.settings_utils import extract_setting_value

        settings = {
            "test.setting": {"value": "test_value", "ui_element": "text"}
        }
        result = extract_setting_value(settings, "test.setting")
        assert result == "test_value"

    def test_returns_setting_directly_if_not_dict(self):
        """Returns setting directly if not a dict."""
        from local_deep_research.api.settings_utils import extract_setting_value

        settings = {"test.setting": "direct_value"}
        result = extract_setting_value(settings, "test.setting")
        assert result == "direct_value"

    def test_returns_default_for_missing_key(self):
        """Returns default value when key is missing."""
        from local_deep_research.api.settings_utils import extract_setting_value

        settings = {"other.setting": "value"}
        result = extract_setting_value(
            settings, "missing.key", default="default"
        )
        assert result == "default"

    def test_returns_none_default_for_missing_key(self):
        """Returns None by default for missing key."""
        from local_deep_research.api.settings_utils import extract_setting_value

        settings = {"other.setting": "value"}
        result = extract_setting_value(settings, "missing.key")
        assert result is None

    def test_returns_default_for_none_settings(self):
        """Returns default when settings is None."""
        from local_deep_research.api.settings_utils import extract_setting_value

        result = extract_setting_value(None, "any.key", default="fallback")
        assert result == "fallback"

    def test_extracts_integer_value(self):
        """Extracts integer value correctly."""
        from local_deep_research.api.settings_utils import extract_setting_value

        settings = {"count": {"value": 42}}
        result = extract_setting_value(settings, "count")
        assert result == 42

    def test_extracts_boolean_value(self):
        """Extracts boolean value correctly."""
        from local_deep_research.api.settings_utils import extract_setting_value

        settings = {"enabled": {"value": True}}
        result = extract_setting_value(settings, "enabled")
        assert result is True

    def test_extracts_dict_value(self):
        """Extracts dict value correctly."""
        from local_deep_research.api.settings_utils import extract_setting_value

        settings = {"config": {"value": {"key": "val"}}}
        result = extract_setting_value(settings, "config")
        assert result == {"key": "val"}

    def test_extracts_list_value(self):
        """Extracts list value correctly."""
        from local_deep_research.api.settings_utils import extract_setting_value

        settings = {"items": {"value": [1, 2, 3]}}
        result = extract_setting_value(settings, "items")
        assert result == [1, 2, 3]


class TestExtractBoolSetting:
    """Tests for extract_bool_setting function."""

    def test_extracts_true_from_boolean(self):
        """Extracts True from boolean True."""
        from local_deep_research.api.settings_utils import extract_bool_setting

        settings = {"enabled": {"value": True}}
        result = extract_bool_setting(settings, "enabled")
        assert result is True

    def test_extracts_false_from_boolean(self):
        """Extracts False from boolean False."""
        from local_deep_research.api.settings_utils import extract_bool_setting

        settings = {"enabled": {"value": False}}
        result = extract_bool_setting(settings, "enabled")
        assert result is False

    def test_converts_string_true(self):
        """Converts string 'true' to True."""
        from local_deep_research.api.settings_utils import extract_bool_setting

        settings = {"enabled": {"value": "true"}}
        result = extract_bool_setting(settings, "enabled")
        assert result is True

    def test_converts_string_false(self):
        """Converts string 'false' to False."""
        from local_deep_research.api.settings_utils import extract_bool_setting

        settings = {"enabled": {"value": "false"}}
        result = extract_bool_setting(settings, "enabled")
        assert result is False

    def test_converts_string_1(self):
        """Converts string '1' to True."""
        from local_deep_research.api.settings_utils import extract_bool_setting

        settings = {"enabled": {"value": "1"}}
        result = extract_bool_setting(settings, "enabled")
        assert result is True

    def test_converts_string_yes(self):
        """Converts string 'yes' to True."""
        from local_deep_research.api.settings_utils import extract_bool_setting

        settings = {"enabled": {"value": "yes"}}
        result = extract_bool_setting(settings, "enabled")
        assert result is True

    def test_returns_default_true_for_missing(self):
        """Returns default True for missing key."""
        from local_deep_research.api.settings_utils import extract_bool_setting

        settings = {}
        result = extract_bool_setting(settings, "missing", default=True)
        assert result is True

    def test_returns_default_false_for_missing(self):
        """Returns default False for missing key."""
        from local_deep_research.api.settings_utils import extract_bool_setting

        settings = {}
        result = extract_bool_setting(settings, "missing", default=False)
        assert result is False

    def test_returns_default_for_none_settings(self):
        """Returns default when settings is None."""
        from local_deep_research.api.settings_utils import extract_bool_setting

        result = extract_bool_setting(None, "any.key", default=True)
        assert result is True


class TestCreateSettingsSnapshot:
    """Tests for create_settings_snapshot function."""

    def test_returns_dict(self):
        """Returns a dictionary."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot()
        assert isinstance(result, dict)

    def test_applies_overrides_to_existing_settings(self):
        """Applies overrides to existing settings."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(overrides={"llm.temperature": 0.5})
        # If llm.temperature exists, it should have the override value
        if "llm.temperature" in result:
            if isinstance(result["llm.temperature"], dict):
                assert result["llm.temperature"]["value"] == 0.5
            else:
                assert result["llm.temperature"] == 0.5

    def test_creates_new_settings_for_unknown_keys(self):
        """Creates new settings for unknown keys."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(
            overrides={"custom.new_key": "new_value"}
        )
        assert "custom.new_key" in result
        assert result["custom.new_key"]["value"] == "new_value"

    def test_infers_checkbox_ui_element_for_bool(self):
        """Infers checkbox ui_element for boolean values."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(overrides={"custom.flag": True})
        assert result["custom.flag"]["ui_element"] == "checkbox"

    def test_infers_number_ui_element_for_int(self):
        """Infers number ui_element for integer values."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(overrides={"custom.count": 42})
        assert result["custom.count"]["ui_element"] == "number"

    def test_infers_number_ui_element_for_float(self):
        """Infers number ui_element for float values."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(overrides={"custom.ratio": 0.75})
        assert result["custom.ratio"]["ui_element"] == "number"

    def test_infers_json_ui_element_for_dict(self):
        """Infers json ui_element for dict values."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(overrides={"custom.config": {"a": 1}})
        assert result["custom.config"]["ui_element"] == "json"

    def test_infers_text_ui_element_for_string(self):
        """Infers text ui_element for string values."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(overrides={"custom.name": "test"})
        assert result["custom.name"]["ui_element"] == "text"

    def test_provider_kwarg_sets_llm_provider(self):
        """Provider kwarg sets llm.provider."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(provider="openai")
        assert "llm.provider" in result
        if isinstance(result["llm.provider"], dict):
            assert result["llm.provider"]["value"] == "openai"
        else:
            assert result["llm.provider"] == "openai"

    def test_api_key_kwarg_with_provider(self):
        """api_key kwarg with provider sets provider-specific key."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(provider="openai", api_key="test-key")
        api_key_setting = "llm.openai.api_key"
        assert api_key_setting in result
        if isinstance(result[api_key_setting], dict):
            assert result[api_key_setting]["value"] == "test-key"
        else:
            assert result[api_key_setting] == "test-key"

    def test_temperature_kwarg(self):
        """temperature kwarg sets llm.temperature."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(temperature=0.8)
        assert "llm.temperature" in result
        if isinstance(result["llm.temperature"], dict):
            assert result["llm.temperature"]["value"] == 0.8
        else:
            assert result["llm.temperature"] == 0.8

    def test_max_search_results_kwarg(self):
        """max_search_results kwarg sets search.max_results."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        result = create_settings_snapshot(max_search_results=20)
        assert "search.max_results" in result
        if isinstance(result["search.max_results"], dict):
            assert result["search.max_results"]["value"] == 20
        else:
            assert result["search.max_results"] == 20

    def test_uses_provided_base_settings(self):
        """Uses provided base_settings instead of defaults."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        base = {"custom.base": {"value": "base_value"}}
        result = create_settings_snapshot(base_settings=base)
        assert "custom.base" in result
        assert result["custom.base"]["value"] == "base_value"

    def test_does_not_modify_base_settings(self):
        """Does not modify the provided base_settings."""
        from local_deep_research.api.settings_utils import (
            create_settings_snapshot,
        )

        base = {"setting": {"value": "original"}}
        create_settings_snapshot(
            base_settings=base, overrides={"setting": "modified"}
        )
        # Original should be unchanged
        assert base["setting"]["value"] == "original"


class TestGetDefaultSettingsSnapshot:
    """Tests for get_default_settings_snapshot function."""

    def test_returns_dict(self):
        """Returns a dictionary."""
        from local_deep_research.api.settings_utils import (
            get_default_settings_snapshot,
        )

        result = get_default_settings_snapshot()
        assert isinstance(result, dict)

    def test_contains_llm_settings(self):
        """Contains LLM-related settings."""
        from local_deep_research.api.settings_utils import (
            get_default_settings_snapshot,
        )

        result = get_default_settings_snapshot()
        # Should have some llm.* settings
        llm_keys = [k for k in result.keys() if k.startswith("llm.")]
        assert len(llm_keys) > 0

    def test_contains_search_settings(self):
        """Contains search-related settings."""
        from local_deep_research.api.settings_utils import (
            get_default_settings_snapshot,
        )

        result = get_default_settings_snapshot()
        # Should have some search.* settings
        search_keys = [k for k in result.keys() if k.startswith("search.")]
        assert len(search_keys) > 0

    def test_settings_have_value_key(self):
        """Settings have 'value' key."""
        from local_deep_research.api.settings_utils import (
            get_default_settings_snapshot,
        )

        result = get_default_settings_snapshot()
        # Check a few settings
        for key, setting in list(result.items())[:5]:
            if isinstance(setting, dict):
                assert "value" in setting


class TestInMemorySettingsManager:
    """Tests for InMemorySettingsManager class."""

    def test_can_instantiate(self):
        """Can instantiate InMemorySettingsManager."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        assert manager is not None

    def test_get_setting_returns_value(self):
        """get_setting returns setting value."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        # Get a setting that should exist
        all_settings = manager.get_all_settings()
        if all_settings:
            first_key = next(iter(all_settings.keys()))
            result = manager.get_setting(first_key)
            # Should return something (not None if the setting exists)
            assert result is not None or first_key in all_settings

    def test_get_setting_returns_default_for_missing(self):
        """get_setting returns default for missing key."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        result = manager.get_setting("nonexistent.key", default="fallback")
        assert result == "fallback"

    def test_set_setting_updates_value(self):
        """set_setting updates an existing setting value."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        # Get any existing setting
        all_settings = manager.get_all_settings()
        if all_settings:
            first_key = next(iter(all_settings.keys()))
            manager.set_setting(first_key, "new_value")
            # Value should be updated
            new_value = manager.get_setting(first_key)
            # Either it's "new_value" or type-converted
            assert new_value is not None

    def test_set_setting_returns_false_for_unknown_key(self):
        """set_setting returns False for unknown key."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        result = manager.set_setting("nonexistent.key", "value")
        assert result is False

    def test_get_all_settings_returns_dict(self):
        """get_all_settings returns a dictionary."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        result = manager.get_all_settings()
        assert isinstance(result, dict)

    def test_get_all_settings_returns_copy(self):
        """get_all_settings returns a deep copy."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        result1 = manager.get_all_settings()
        result2 = manager.get_all_settings()
        # Should be equal but not the same object
        assert result1 == result2
        assert result1 is not result2

    def test_delete_setting_removes_key(self):
        """delete_setting removes a setting."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        # Add a custom setting first
        manager.create_or_update_setting({"key": "test.delete", "value": "val"})
        assert manager.delete_setting("test.delete") is True
        assert manager.get_setting("test.delete") is None

    def test_delete_setting_returns_false_for_unknown(self):
        """delete_setting returns False for unknown key."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        result = manager.delete_setting("nonexistent.key")
        assert result is False

    def test_create_or_update_setting(self):
        """create_or_update_setting adds or updates a setting."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        setting = {
            "key": "test.new",
            "value": "new_value",
            "ui_element": "text",
        }
        result = manager.create_or_update_setting(setting)
        assert result is not None
        assert manager.get_setting("test.new") == "new_value"

    def test_import_settings_with_overwrite(self):
        """import_settings overwrites existing settings."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        manager.create_or_update_setting({"key": "test.import", "value": "old"})
        manager.import_settings(
            {"test.import": {"value": "new", "ui_element": "text"}},
            overwrite=True,
        )
        assert manager.get_setting("test.import") == "new"

    def test_import_settings_without_overwrite(self):
        """import_settings respects overwrite=False."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        manager.create_or_update_setting(
            {"key": "test.keep", "value": "original"}
        )
        manager.import_settings(
            {"test.keep": {"value": "new", "ui_element": "text"}},
            overwrite=False,
        )
        assert manager.get_setting("test.keep") == "original"

    def test_import_settings_delete_extra(self):
        """import_settings with delete_extra clears existing."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        manager.import_settings(
            {"only.setting": {"value": "val", "ui_element": "text"}},
            delete_extra=True,
        )
        all_settings = manager.get_all_settings()
        assert "only.setting" in all_settings


class TestUIElementTypeConversion:
    """Tests for UI element type conversion in InMemorySettingsManager."""

    def test_checkbox_to_bool(self):
        """Checkbox ui_element converts to bool."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        manager.create_or_update_setting(
            {"key": "test.bool", "value": "true", "ui_element": "checkbox"}
        )
        result = manager.get_setting("test.bool")
        assert result is True

    def test_number_to_float(self):
        """Number ui_element converts to float."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        manager.create_or_update_setting(
            {"key": "test.num", "value": "42", "ui_element": "number"}
        )
        result = manager.get_setting("test.num")
        assert result == 42.0

    def test_text_to_str(self):
        """Text ui_element stays as string."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        manager.create_or_update_setting(
            {"key": "test.str", "value": "hello", "ui_element": "text"}
        )
        result = manager.get_setting("test.str")
        assert result == "hello"

    def test_checkbox_string_false(self):
        """Checkbox ui_element handles 'false' string."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        manager.create_or_update_setting(
            {"key": "test.false", "value": "false", "ui_element": "checkbox"}
        )
        result = manager.get_setting("test.false")
        assert result is False

    def test_checkbox_string_0(self):
        """Checkbox ui_element handles '0' string."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        manager.create_or_update_setting(
            {"key": "test.zero", "value": "0", "ui_element": "checkbox"}
        )
        result = manager.get_setting("test.zero")
        assert result is False

    def test_checkbox_string_yes(self):
        """Checkbox ui_element handles 'yes' string."""
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        manager = InMemorySettingsManager()
        manager.create_or_update_setting(
            {"key": "test.yes", "value": "yes", "ui_element": "checkbox"}
        )
        result = manager.get_setting("test.yes")
        assert result is True
