"""
Tests for the openai_endpoint API key UX fix (issue #3875).

Validates that the openai_endpoint API key setting has the correct type
and a user-friendly description that makes clear it can be optional.
"""

import json
import os
from pathlib import Path

import pytest

from local_deep_research.settings.manager import SettingsManager

DEFAULTS_PATH = (
    Path(__file__).parent.parent
    / "src"
    / "local_deep_research"
    / "defaults"
    / "default_settings.json"
)


@pytest.fixture(autouse=True)
def clean_env():
    """Save/clear/restore LDR_* env vars to prevent pollution across tests."""
    original_env = {k: v for k, v in os.environ.items() if k.startswith("LDR_")}
    for key in list(os.environ.keys()):
        if key.startswith("LDR_"):
            os.environ.pop(key, None)
    yield
    for key in list(os.environ.keys()):
        if key.startswith("LDR_"):
            os.environ.pop(key, None)
    for key, value in original_env.items():
        os.environ[key] = value


@pytest.fixture(scope="module")
def defaults():
    """Load all default settings."""
    manager = SettingsManager(db_session=None)
    return manager.default_settings


@pytest.fixture(scope="module")
def raw_json():
    """Load the raw default_settings.json file."""
    with open(DEFAULTS_PATH, encoding="utf-8") as f:
        return json.load(f)


class TestOpenAIEndpointApiKeyType:
    """Test that openai_endpoint API key has correct type 'LLM'."""

    def test_openai_endpoint_api_key_type_is_llm(self, defaults):
        """The openai_endpoint api_key should have type 'LLM', not 'SEARCH'."""
        setting = defaults["llm.openai_endpoint.api_key"]
        assert setting["type"] == "LLM", (
            f"Expected type 'LLM' but got '{setting['type']}'. "
            f"API keys for LLM providers should be categorized as 'LLM'."
        )


class TestOpenAIEndpointApiKeyDescription:
    """Test that the description clarifies the key is optional for local servers."""

    def test_description_mentions_optional(self, defaults):
        """The description should mention that the key is optional / can be left empty."""
        setting = defaults["llm.openai_endpoint.api_key"]
        description = setting["description"].lower()
        assert (
            "optional" in description
            or "leave empty" in description
            or "leave this blank" in description
            or "leave blank" in description
        ), (
            f"Description should mention 'optional', 'leave empty', or 'leave (this) blank'. "
            f"Got: {setting['description']!r}"
        )

    def test_description_no_longer_says_not_needed(self, defaults):
        """The description should NOT say 'use any non-empty value like not-needed'."""
        setting = defaults["llm.openai_endpoint.api_key"]
        description = setting["description"].lower()
        assert "not-needed" not in description, (
            f"Description should not suggest using 'not-needed' as a placeholder. "
            f"Got: {setting['description']!r}"
        )


class TestAllLlmApiKeyTypes:
    """Test that llm.*.api_key settings used for optional endpoints have type 'LLM'."""

    def test_local_llm_api_keys_have_type_llm(self, defaults):
        """API keys for local/optional LLM providers must be categorized as 'LLM'.

        Cloud-only providers (google, openrouter, ionos, anthropic, openai,
        deepseek, xai) legitimately use SEARCH type since a key is always
        required.  But providers that support local servers (openai_endpoint,
        ollama, llamacpp, lmstudio) should use LLM type.
        """
        optional_providers = {
            "llm.openai_endpoint.api_key",
            "llm.ollama.api_key",
            "llm.llamacpp.api_key",
            "llm.lmstudio.api_key",
        }
        errors = []
        for key, setting in defaults.items():
            if key in optional_providers:
                if setting["type"] != "LLM":
                    errors.append(
                        f"{key}: expected type 'LLM', got '{setting['type']}'"
                    )

        assert not errors, (
            f"{len(errors)} optional-provider api_key setting(s) have wrong type:\n"
            + "\n".join(f"  {e}" for e in errors)
        )
