"""
Behavioral tests for web/models/settings module.

Tests the custom key prefix validators — the only real logic in this module.
Each setting subclass (LLMSetting, SearchSetting, ReportSetting, AppSetting)
has a @field_validator that auto-prefixes keys missing their category prefix.
"""

import pytest


class TestLLMSettingKeyValidator:
    """Tests for LLMSetting.validate_llm_key auto-prefix logic."""

    def test_adds_prefix_when_missing(self):
        from local_deep_research.web.models.settings import LLMSetting

        setting = LLMSetting(key="model", value="gpt-4", name="Model")
        assert setting.key == "llm.model"

    def test_preserves_existing_prefix(self):
        from local_deep_research.web.models.settings import LLMSetting

        setting = LLMSetting(key="llm.temperature", value=0.7, name="Temp")
        assert setting.key == "llm.temperature"

    def test_no_double_prefix(self):
        """Applying the validator twice should not produce 'llm.llm.key'."""
        from local_deep_research.web.models.settings import LLMSetting

        setting = LLMSetting(key="llm.model", value="gpt-4", name="Model")
        assert setting.key == "llm.model"
        assert not setting.key.startswith("llm.llm.")

    def test_prefix_substring_still_gets_prefixed(self):
        """Key starting with 'llm' but not 'llm.' should get prefixed.

        'llm_model' starts with 'llm' but not 'llm.' — the validator
        checks startswith('llm.') specifically, so it should be prefixed.
        """
        from local_deep_research.web.models.settings import LLMSetting

        setting = LLMSetting(key="llm_model", value="gpt-4", name="Model")
        assert setting.key == "llm.llm_model"

    def test_dotted_key_preserved(self):
        """Nested dotted keys after prefix are preserved."""
        from local_deep_research.web.models.settings import LLMSetting

        setting = LLMSetting(
            key="llm.openai.api_key", value="sk-xxx", name="API Key"
        )
        assert setting.key == "llm.openai.api_key"


class TestSearchSettingKeyValidator:
    """Tests for SearchSetting.validate_search_key auto-prefix logic."""

    def test_adds_prefix_when_missing(self):
        from local_deep_research.web.models.settings import SearchSetting

        setting = SearchSetting(key="engine", value="brave", name="Engine")
        assert setting.key == "search.engine"

    def test_preserves_existing_prefix(self):
        from local_deep_research.web.models.settings import SearchSetting

        setting = SearchSetting(key="search.max_results", value=10, name="Max")
        assert setting.key == "search.max_results"

    def test_prefix_substring_still_gets_prefixed(self):
        """'search_mode' starts with 'search' but not 'search.'."""
        from local_deep_research.web.models.settings import SearchSetting

        setting = SearchSetting(key="search_mode", value="all", name="Mode")
        assert setting.key == "search.search_mode"


class TestReportSettingKeyValidator:
    """Tests for ReportSetting.validate_report_key auto-prefix logic."""

    def test_adds_prefix_when_missing(self):
        from local_deep_research.web.models.settings import ReportSetting

        setting = ReportSetting(key="format", value="markdown", name="Format")
        assert setting.key == "report.format"

    def test_preserves_existing_prefix(self):
        from local_deep_research.web.models.settings import ReportSetting

        setting = ReportSetting(
            key="report.format", value="markdown", name="Format"
        )
        assert setting.key == "report.format"


class TestAppSettingKeyValidator:
    """Tests for AppSetting.validate_app_key auto-prefix logic."""

    def test_adds_prefix_when_missing(self):
        from local_deep_research.web.models.settings import AppSetting

        setting = AppSetting(key="theme", value="dark", name="Theme")
        assert setting.key == "app.theme"

    def test_preserves_existing_prefix(self):
        from local_deep_research.web.models.settings import AppSetting

        setting = AppSetting(key="app.theme", value="dark", name="Theme")
        assert setting.key == "app.theme"

    def test_prefix_substring_still_gets_prefixed(self):
        """'application_mode' starts with 'app' but not 'app.'."""
        from local_deep_research.web.models.settings import AppSetting

        setting = AppSetting(key="application_mode", value="dev", name="Mode")
        assert setting.key == "app.application_mode"


class TestAllValidatorsConsistentBehavior:
    """Cross-cutting tests verifying all 4 validators behave the same way."""

    def test_all_setting_types_auto_prefix(self):
        """Each setting subclass auto-prefixes its category."""
        from local_deep_research.web.models.settings import (
            AppSetting,
            LLMSetting,
            ReportSetting,
            SearchSetting,
        )

        cases = [
            (LLMSetting, "model", "llm.model"),
            (SearchSetting, "engine", "search.engine"),
            (ReportSetting, "format", "report.format"),
            (AppSetting, "theme", "app.theme"),
        ]
        for cls, raw_key, expected_key in cases:
            setting = cls(key=raw_key, value="v", name="n")
            assert setting.key == expected_key, (
                f"{cls.__name__} failed: {raw_key} -> {setting.key}"
            )

    def test_all_setting_types_preserve_prefix(self):
        """Each setting subclass preserves already-prefixed keys."""
        from local_deep_research.web.models.settings import (
            AppSetting,
            LLMSetting,
            ReportSetting,
            SearchSetting,
        )

        cases = [
            (LLMSetting, "llm.model"),
            (SearchSetting, "search.engine"),
            (ReportSetting, "report.format"),
            (AppSetting, "app.theme"),
        ]
        for cls, prefixed_key in cases:
            setting = cls(key=prefixed_key, value="v", name="n")
            assert setting.key == prefixed_key

    def test_missing_required_fields_raises(self):
        """BaseSetting requires key, value, type, and name."""
        from local_deep_research.web.models.settings import BaseSetting

        with pytest.raises(Exception):
            BaseSetting(key="test.key", value="v")  # missing type and name
