"""Tests for unified model config — env var interpolation and credential handling."""

from __future__ import annotations

from pathlib import Path
from unittest.mock import patch

import pytest
from icarus.config.model_config import ModelConfig, clear_caches


@pytest.fixture(autouse=True)
def _clear_model_caches():
    """Clear module-level caches before each test."""
    clear_caches()
    yield
    clear_caches()


# --- ModelConfig.load() ---


def test_load_missing_file(tmp_path: Path):
    """ModelConfig.load returns empty config when file doesn't exist."""
    config = ModelConfig.load(tmp_path / "nonexistent.toml")
    assert config.default_model is None
    assert config.providers == {}


def test_load_parses_providers(tmp_path: Path):
    """ModelConfig.load reads providers from config.toml."""
    config_file = tmp_path / "config.toml"
    config_file.write_text("""
[models]
default = "azure_ai:Kimi-K2.5"

[models.providers.azure_ai]
class_path = "langchain_azure_ai.chat_models:AzureAIChatCompletionsModel"
api_key_env = "AZURE_INFERENCE_CREDENTIAL"
models = ["Kimi-K2.5"]

[models.providers.azure_ai.params]
endpoint = "$AZURE_INFERENCE_ENDPOINT"
credential = "$AZURE_INFERENCE_CREDENTIAL"
""")

    config = ModelConfig.load(config_file)

    assert config.default_model == "azure_ai:Kimi-K2.5"
    assert "azure_ai" in config.providers
    assert config.providers["azure_ai"]["models"] == ["Kimi-K2.5"]
    expected = "langchain_azure_ai.chat_models:AzureAIChatCompletionsModel"
    assert config.providers["azure_ai"]["class_path"] == expected


def test_load_invalid_toml(tmp_path: Path):
    """ModelConfig.load handles invalid TOML gracefully."""
    config_file = tmp_path / "config.toml"
    config_file.write_text("this is not valid toml [[[")

    config = ModelConfig.load(config_file)
    assert config.default_model is None
    assert config.providers == {}


# --- Env var interpolation ---


def test_env_var_interpolation(monkeypatch: pytest.MonkeyPatch):
    """$VAR_NAME in params resolved from os.environ."""
    from icarus.config.app_config import _resolve_env_vars

    monkeypatch.setenv("MY_ENDPOINT", "https://example.com")
    monkeypatch.setenv("MY_KEY", "secret-123")

    params = {
        "endpoint": "$MY_ENDPOINT",
        "credential": "$MY_KEY",
        "temperature": 0.7,
    }

    resolved = _resolve_env_vars(params)

    assert resolved["endpoint"] == "https://example.com"
    assert resolved["credential"] == "secret-123"
    assert resolved["temperature"] == 0.7


def test_env_var_interpolation_missing_var():
    """Missing env vars leave the $VAR_NAME string as-is."""
    from icarus.config.app_config import _resolve_env_vars

    params = {"endpoint": "$NONEXISTENT_VAR_12345"}
    resolved = _resolve_env_vars(params)
    assert resolved["endpoint"] == "$NONEXISTENT_VAR_12345"


# --- Credential handling for class_path providers ---


def test_class_path_provider_skips_api_key_injection(
    tmp_path: Path, monkeypatch: pytest.MonkeyPatch
):
    """Providers with class_path don't get api_key auto-injected."""
    from icarus.config.app_config import _get_provider_kwargs

    monkeypatch.setenv("MY_API_KEY", "should-not-appear")

    config_file = tmp_path / "config.toml"
    config_file.write_text("""
[models.providers.custom]
class_path = "some.module:CustomModel"
api_key_env = "MY_API_KEY"
models = ["my-model"]
""")

    config = ModelConfig.load(config_file)
    with patch("icarus.config.app_config.ModelConfig.load", return_value=config):
        kwargs, _ = _get_provider_kwargs("custom", model_name="my-model")

    assert "api_key" not in kwargs


def test_standard_provider_gets_api_key_injection(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
    """Standard providers (no class_path) get api_key from api_key_env."""
    from icarus.config.app_config import _get_provider_kwargs

    monkeypatch.setenv("MY_API_KEY", "secret-key")

    config_file = tmp_path / "config.toml"
    config_file.write_text("""
[models.providers.mycloud]
api_key_env = "MY_API_KEY"
models = ["model-a"]
""")

    config = ModelConfig.load(config_file)
    with patch("icarus.config.app_config.ModelConfig.load", return_value=config):
        kwargs, _ = _get_provider_kwargs("mycloud", model_name="model-a")

    assert kwargs["api_key"] == "secret-key"


# --- Azure AI endpoint resolution + config ---


@pytest.mark.parametrize(
    "raw,expected_url,expected_class_fragment",
    [
        # Full chat/completions path → AI Inference, stripped to /models
        (
            "https://res.services.ai.azure.com/models/chat/completions?api-version=2024-05-01-preview",
            "https://res.services.ai.azure.com/models",
            "AzureAIChatCompletionsModel",
        ),
        # Anthropic path → ChatAnthropic, stripped to /anthropic
        (
            "https://res.services.ai.azure.com/anthropic/v1/messages",
            "https://res.services.ai.azure.com/anthropic",
            "ChatAnthropic",
        ),
        # Already correct AI Inference
        (
            "https://res.services.ai.azure.com/models",
            "https://res.services.ai.azure.com/models",
            "AzureAIChatCompletionsModel",
        ),
        # Bare domain → AI Inference, /models appended
        (
            "https://res.services.ai.azure.com",
            "https://res.services.ai.azure.com/models",
            "AzureAIChatCompletionsModel",
        ),
        # Trailing quote (copy-paste artifact)
        (
            "https://res.services.ai.azure.com/models'",
            "https://res.services.ai.azure.com/models",
            "AzureAIChatCompletionsModel",
        ),
        # Serverless endpoint — AI Inference, no /models added
        (
            "https://res.inference.ai.azure.com",
            "https://res.inference.ai.azure.com",
            "AzureAIChatCompletionsModel",
        ),
    ],
)
def test_resolve_azure_endpoint(raw: str, expected_url: str, expected_class_fragment: str):
    """Azure endpoint URLs are classified and normalized."""
    from icarus.config.app_config import _resolve_azure_endpoint

    url, class_path = _resolve_azure_endpoint(raw)
    assert url == expected_url
    assert expected_class_fragment in class_path


def test_save_provider_config_with_endpoints(tmp_path: Path):
    """save_provider_config writes per-model endpoint overrides."""
    from icarus.config.model_config import save_provider_config

    config_file = tmp_path / "config.toml"
    save_provider_config(
        "azure_ai",
        models=["Kimi-K2.5", "claude-sonnet-4"],
        endpoints={
            "Kimi-K2.5": "https://ep1.azure.com",
            "claude-sonnet-4": "https://ep2.azure.com",
        },
        config_path=config_file,
    )

    config = ModelConfig.load(config_file)
    assert config.providers["azure_ai"]["models"] == ["Kimi-K2.5", "claude-sonnet-4"]
    params = config.providers["azure_ai"]["params"]
    assert params["Kimi-K2.5"]["endpoint"] == "https://ep1.azure.com"
    assert params["claude-sonnet-4"]["endpoint"] == "https://ep2.azure.com"
