"""
Tests for InMemorySettingsManager.get_settings_snapshot() and import_settings()
in api/settings_utils.py.

Tests cover:
- get_settings_snapshot: full format extraction, simplified format passthrough, mixed
- import_settings: overwrite=True, overwrite=False, delete_extra, type handling, empty
"""

from unittest.mock import patch, MagicMock


def _make_manager_with_settings(settings_dict):
    """Create an InMemorySettingsManager with pre-loaded settings (no disk I/O)."""
    with patch(
        "local_deep_research.api.settings_utils.InMemorySettingsManager.__init__",
        lambda self: None,
    ):
        from local_deep_research.api.settings_utils import (
            InMemorySettingsManager,
        )

        mgr = InMemorySettingsManager()
        mgr._settings = settings_dict.copy()
        mgr._base_manager = MagicMock()
        return mgr


class TestGetSettingsSnapshot:
    """Tests for get_settings_snapshot()."""

    def test_full_format_extracts_value(self):
        """Dict-with-value entries → snapshot has just the value."""
        mgr = _make_manager_with_settings(
            {"key1": {"value": 42, "ui_element": "number"}}
        )
        snapshot = mgr.get_settings_snapshot()
        assert snapshot["key1"] == 42

    def test_simplified_format_passthrough(self):
        """Non-dict or dict-without-value entries pass through as-is."""
        mgr = _make_manager_with_settings({"key1": "simple_value"})
        snapshot = mgr.get_settings_snapshot()
        assert snapshot["key1"] == "simple_value"

    def test_mixed_formats(self):
        """Mix of full and simplified formats in one snapshot."""
        mgr = _make_manager_with_settings(
            {
                "full_key": {"value": True, "ui_element": "checkbox"},
                "simple_key": 100,
                "dict_no_value": {"other": "data"},
            }
        )
        snapshot = mgr.get_settings_snapshot()
        assert snapshot["full_key"] is True
        assert snapshot["simple_key"] == 100
        assert snapshot["dict_no_value"] == {"other": "data"}

    def test_empty_settings(self):
        """Empty settings → empty snapshot."""
        mgr = _make_manager_with_settings({})
        assert mgr.get_settings_snapshot() == {}

    def test_none_value_in_full_format(self):
        """Full format with value=None → snapshot has None."""
        mgr = _make_manager_with_settings(
            {"key": {"value": None, "ui_element": "text"}}
        )
        snapshot = mgr.get_settings_snapshot()
        assert snapshot["key"] is None

    def test_snapshot_is_independent_copy(self):
        """Modifying snapshot doesn't affect internal settings."""
        mgr = _make_manager_with_settings(
            {"key": {"value": "original", "ui_element": "text"}}
        )
        snapshot = mgr.get_settings_snapshot()
        snapshot["key"] = "modified"
        # Internal still has original value
        assert mgr._settings["key"]["value"] == "original"

    def test_list_value(self):
        """Full format with list value → snapshot has the list."""
        mgr = _make_manager_with_settings(
            {"key": {"value": [1, 2, 3], "ui_element": "text"}}
        )
        snapshot = mgr.get_settings_snapshot()
        assert snapshot["key"] == [1, 2, 3]


class TestImportSettings:
    """Tests for import_settings()."""

    def test_import_overwrites_existing(self):
        """overwrite=True replaces existing settings."""
        mgr = _make_manager_with_settings({"key1": "old_value"})
        mgr.import_settings({"key1": "new_value"}, overwrite=True)
        assert mgr._settings["key1"] == "new_value"

    def test_import_no_overwrite_skips_existing(self):
        """overwrite=False skips keys that already exist."""
        mgr = _make_manager_with_settings({"key1": "original"})
        mgr.import_settings({"key1": "ignored", "key2": "new"}, overwrite=False)
        assert mgr._settings["key1"] == "original"
        assert mgr._settings["key2"] == "new"

    def test_import_adds_new_keys(self):
        """New keys are always added regardless of overwrite flag."""
        mgr = _make_manager_with_settings({})
        mgr.import_settings({"new_key": "value"}, overwrite=False)
        assert mgr._settings["new_key"] == "value"

    def test_delete_extra_clears_first(self):
        """delete_extra=True clears existing settings before importing."""
        mgr = _make_manager_with_settings({"old_key": "old_value"})
        mgr.import_settings({"new_key": "new_value"}, delete_extra=True)
        assert "old_key" not in mgr._settings
        assert mgr._settings["new_key"] == "new_value"

    def test_delete_extra_false_preserves(self):
        """delete_extra=False preserves existing settings."""
        mgr = _make_manager_with_settings({"old_key": "old_value"})
        mgr.import_settings({"new_key": "new_value"}, delete_extra=False)
        assert "old_key" in mgr._settings
        assert "new_key" in mgr._settings

    def test_import_full_format_with_type_conversion(self):
        """Full format dicts get _get_typed_value applied."""
        mgr = _make_manager_with_settings({})
        mgr._get_typed_value = MagicMock(return_value=42)
        mgr.import_settings(
            {"key": {"value": "42", "ui_element": "number"}}, overwrite=True
        )
        mgr._get_typed_value.assert_called()
        # Value should be the typed result
        assert mgr._settings["key"]["value"] == 42

    def test_import_simple_value_no_type_conversion(self):
        """Simple (non-dict) values are stored as-is without type conversion."""
        mgr = _make_manager_with_settings({})
        mgr._get_typed_value = MagicMock()
        mgr.import_settings({"key": "plain_string"}, overwrite=True)
        mgr._get_typed_value.assert_not_called()
        assert mgr._settings["key"] == "plain_string"

    def test_import_empty_dict(self):
        """Importing empty dict changes nothing."""
        mgr = _make_manager_with_settings({"existing": "value"})
        mgr.import_settings({})
        assert mgr._settings["existing"] == "value"
