"""Tests for the programmatic API settings functionality."""

from unittest.mock import patch, MagicMock

from local_deep_research.api.settings_utils import (
    InMemorySettingsManager,
    get_default_settings_snapshot,
    create_settings_snapshot,
    extract_setting_value,
)


class TestInMemorySettingsManager:
    """Test the InMemorySettingsManager class."""

    def test_initialization(self):
        """Test that the manager initializes with default settings."""
        manager = InMemorySettingsManager()
        settings = manager.get_all_settings()

        # Should have loaded default settings
        assert len(settings) > 0
        assert "llm.provider" in settings
        assert "llm.temperature" in settings

    def test_get_setting(self):
        """Test getting individual settings."""
        manager = InMemorySettingsManager()

        # Get existing setting
        provider = manager.get_setting("llm.provider")
        assert provider is not None

        # Get non-existent setting with default
        missing = manager.get_setting("non.existent", "default_value")
        assert missing == "default_value"

    def test_set_setting(self):
        """Test setting values."""
        manager = InMemorySettingsManager()

        # Set existing setting
        result = manager.set_setting("llm.temperature", 0.5)
        assert result is True
        assert manager.get_setting("llm.temperature") == 0.5

        # Try to set non-existent setting
        result = manager.set_setting("non.existent", "value")
        assert result is False

    def test_environment_override(self, monkeypatch):
        """Test that environment variables override defaults."""
        # Set environment variables
        monkeypatch.setenv("LDR_LLM_PROVIDER", "anthropic")
        monkeypatch.setenv("LDR_LLM_TEMPERATURE", "0.3")

        manager = InMemorySettingsManager()

        assert manager.get_setting("llm.provider") == "anthropic"
        assert manager.get_setting("llm.temperature") == 0.3


class TestSettingsSnapshot:
    """Test settings snapshot creation and manipulation."""

    def test_get_default_settings_snapshot(self):
        """Test getting the default settings snapshot."""
        snapshot = get_default_settings_snapshot()

        assert isinstance(snapshot, dict)
        assert len(snapshot) > 0

        # Check structure
        assert "llm.provider" in snapshot
        provider_setting = snapshot["llm.provider"]
        assert "value" in provider_setting
        assert "type" in provider_setting
        assert "description" in provider_setting

    def test_create_settings_snapshot_with_defaults(self):
        """Test creating a snapshot with default settings."""
        snapshot = create_settings_snapshot()

        assert isinstance(snapshot, dict)
        assert len(snapshot) > 0

    def test_create_settings_snapshot_with_kwargs(self):
        """Test creating a snapshot with keyword arguments."""
        snapshot = create_settings_snapshot(
            provider="openai",
            api_key="test-key-123",
            temperature=0.2,
            max_search_results=10,
        )

        # Check provider was set
        assert snapshot["llm.provider"]["value"] == "openai"

        # Check API key was set for the right provider
        assert snapshot["llm.openai.api_key"]["value"] == "test-key-123"

        # Check temperature was set
        assert snapshot["llm.temperature"]["value"] == 0.2

        # Check search results was set
        assert snapshot["search.max_results"]["value"] == 10

    def test_create_settings_snapshot_with_overrides(self):
        """Test creating a snapshot with settings overrides."""
        snapshot = create_settings_snapshot(
            overrides={
                "llm.max_tokens": 2000,
                "search.max_results": 5,
                "new.setting": "custom_value",
            }
        )

        # Check existing settings were overridden
        assert snapshot["llm.max_tokens"]["value"] == 2000
        assert snapshot["search.max_results"]["value"] == 5

        # Check new setting was added
        assert "new.setting" in snapshot
        assert snapshot["new.setting"]["value"] == "custom_value"

    def test_create_settings_snapshot_with_base_settings(self):
        """Test creating a snapshot with custom base settings."""
        base = {"custom.setting": {"value": "base_value", "type": "CUSTOM"}}

        snapshot = create_settings_snapshot(
            base_settings=base, overrides={"custom.setting": "override_value"}
        )

        # Should have the base setting with override
        assert snapshot["custom.setting"]["value"] == "override_value"
        assert snapshot["custom.setting"]["type"] == "CUSTOM"

    def test_extract_setting_value(self):
        """Test extracting values from settings snapshot."""
        snapshot = {
            "setting1": {"value": "test1"},
            "setting2": "direct_value",
            "setting3": {"other": "data"},
        }

        # Extract from dict with value key
        assert extract_setting_value(snapshot, "setting1") == "test1"

        # Extract direct value
        assert extract_setting_value(snapshot, "setting2") == "direct_value"

        # Extract dict without value key
        assert extract_setting_value(snapshot, "setting3") == {"other": "data"}

        # Extract with default
        assert (
            extract_setting_value(snapshot, "missing", "default") == "default"
        )


class TestProgrammaticAPIIntegration:
    """Test integration with the programmatic API functions."""

    @patch("local_deep_research.api.research_functions._init_search_system")
    def test_quick_summary_creates_snapshot(self, mock_init):
        """Test that quick_summary creates a settings snapshot when not provided."""
        from local_deep_research.api import quick_summary

        # Configure mock
        mock_system = MagicMock()
        mock_system.analyze_topic.return_value = {
            "current_knowledge": "Test summary",
            "findings": [],
            "iterations": 1,
            "questions": {},
            "formatted_findings": "Test findings",
            "all_links_of_system": [],
        }
        mock_init.return_value = mock_system

        # Call without settings_snapshot
        _ = quick_summary(
            "Test query",
            provider="anthropic",
            api_key="test-key",
            temperature=0.5,
        )

        # Check that settings_snapshot was created and passed
        call_kwargs = mock_init.call_args[1]
        assert "settings_snapshot" in call_kwargs
        snapshot = call_kwargs["settings_snapshot"]

        # Verify snapshot contains our settings
        assert snapshot["llm.provider"]["value"] == "anthropic"
        assert snapshot["llm.anthropic.api_key"]["value"] == "test-key"
        assert snapshot["llm.temperature"]["value"] == 0.5

    @patch("local_deep_research.api.research_functions._init_search_system")
    def test_quick_summary_uses_provided_snapshot(self, mock_init):
        """Test that quick_summary uses provided settings_snapshot."""
        from local_deep_research.api import quick_summary

        # Configure mock
        mock_system = MagicMock()
        mock_system.analyze_topic.return_value = {
            "current_knowledge": "Test summary",
            "findings": [],
            "iterations": 1,
            "questions": {},
            "formatted_findings": "Test findings",
            "all_links_of_system": [],
        }
        mock_init.return_value = mock_system

        # Create custom snapshot
        custom_snapshot = {"test": "snapshot"}

        # Call with settings_snapshot
        _ = quick_summary("Test query", settings_snapshot=custom_snapshot)

        # Check that our snapshot was passed through
        call_kwargs = mock_init.call_args[1]
        assert call_kwargs["settings_snapshot"] == custom_snapshot
