from __future__ import annotations

from types import SimpleNamespace

import pytest

from agentbyte.presets import clients as preset_clients


class DummyOpenAIClient:
    @classmethod
    def from_api_key(cls, model, config=None):  # noqa: ANN001
        return SimpleNamespace(provider="openai", model=model, config=config)


class DummyAzureClient:
    @classmethod
    def from_certificate(cls, model=None, config=None):  # noqa: ANN001
        return SimpleNamespace(
            provider="azure-openai",
            auth="certificate",
            model=model,
            config=config,
        )

    @classmethod
    def from_api_key(cls, model=None, config=None):  # noqa: ANN001
        return SimpleNamespace(
            provider="azure-openai",
            auth="api-key",
            model=model,
            config=config,
        )

    @classmethod
    def from_default_credential(cls, model=None, config=None):  # noqa: ANN001
        return SimpleNamespace(
            provider="azure-openai",
            auth="default-credential",
            model=model,
            config=config,
        )


def test_build_chat_client_explicit_openai(monkeypatch):
    monkeypatch.setattr(preset_clients, "OpenAIChatCompletionClient", DummyOpenAIClient)

    client = preset_clients.build_chat_client(provider="openai", model="gpt-test")

    assert client.provider == "openai"
    assert client.model == "gpt-test"
    assert client.config == {"temperature": 0.2}


def test_build_chat_client_explicit_azure_with_api_key(monkeypatch):
    monkeypatch.setattr(
        preset_clients, "AzureOpenAIChatCompletionClient", DummyAzureClient
    )
    monkeypatch.setenv("AZURE_OPENAI_API_KEY", "secret")

    client = preset_clients.build_chat_client(
        provider="azure-openai",
        model="azure-model",
    )

    assert client.provider == "azure-openai"
    assert client.auth == "api-key"
    assert client.model == "azure-model"


def test_build_chat_client_prefers_azure_certificate_over_api_key(monkeypatch):
    monkeypatch.setattr(
        preset_clients, "AzureOpenAIChatCompletionClient", DummyAzureClient
    )
    monkeypatch.setenv("AZURE_OPENAI_ENDPOINT", "https://example.openai.azure.com/")
    monkeypatch.setenv("AZURE_OPENAI_API_KEY", "secret")
    monkeypatch.setenv("AZURE_TENANT_ID", "tenant")

    client = preset_clients.build_chat_client(provider="azure-openai")

    assert client.provider == "azure-openai"
    assert client.auth == "certificate"


def test_build_chat_client_uses_azure_env_model_name_when_present(monkeypatch):
    monkeypatch.setattr(
        preset_clients, "AzureOpenAIChatCompletionClient", DummyAzureClient
    )
    monkeypatch.delenv("OPENAI_API_KEY", raising=False)
    monkeypatch.delenv("AZURE_OPENAI_API_KEY", raising=False)
    monkeypatch.setenv("AZURE_OPENAI_ENDPOINT", "https://example.openai.azure.com/")
    monkeypatch.setenv("AZURE_OPENAI_CHAT_DEPLOYMENT_NAME", "azure-chat-deployment")

    client = preset_clients.build_chat_client(provider="azure-openai")

    assert client.provider == "azure-openai"
    assert client.model == "azure-chat-deployment"


def test_build_chat_client_infers_openai_from_env(monkeypatch):
    monkeypatch.setattr(preset_clients, "OpenAIChatCompletionClient", DummyOpenAIClient)
    monkeypatch.setenv("OPENAI_API_KEY", "secret")

    client = preset_clients.build_chat_client()

    assert client.provider == "openai"
    assert client.model == "gpt-4.1-mini"


def test_build_chat_client_uses_azure_default_credential_when_no_key(monkeypatch):
    monkeypatch.setattr(
        preset_clients, "AzureOpenAIChatCompletionClient", DummyAzureClient
    )
    monkeypatch.delenv("OPENAI_API_KEY", raising=False)
    monkeypatch.delenv("AZURE_OPENAI_API_KEY", raising=False)
    monkeypatch.setenv("AZURE_OPENAI_ENDPOINT", "https://example.openai.azure.com/")

    client = preset_clients.build_chat_client(provider="azure-openai")

    assert client.provider == "azure-openai"
    assert client.auth == "default-credential"


def test_build_chat_client_raises_when_provider_cannot_be_resolved(monkeypatch):
    monkeypatch.delenv("OPENAI_API_KEY", raising=False)
    monkeypatch.delenv("AZURE_OPENAI_API_KEY", raising=False)
    monkeypatch.delenv("AZURE_OPENAI_ENDPOINT", raising=False)

    with pytest.raises(ValueError, match="Could not infer chat provider"):
        preset_clients.build_chat_client()
