"""
Smoke test: llm-connect integration in state-hub (S3.1).

Verifies that the package is importable from the state-hub venv and that
the core types and mock adapter work correctly.  Does NOT call any live
LLM endpoint — CI-safe and offline-safe.
"""
import llm_connect
from llm_connect import (
    MockLLMAdapter,
    RunConfig,
    LLMResponse,
    LLMError,
    create_adapter,
)


def test_package_version():
    assert hasattr(llm_connect, "__version__") or True  # version attr optional


def test_public_symbols_importable():
    """All expected public symbols are present in llm_connect namespace."""
    expected = [
        "RunConfig", "LLMResponse",
        "LLMAdapter", "MockLLMAdapter", "ErrorLLMAdapter",
        "OpenRouterAdapter", "GeminiAdapter", "OpenAIAdapter", "ClaudeCodeAdapter",
        "create_adapter",
        "LLMError", "LLMConfigurationError", "LLMAPIError",
        "LLMRateLimitError", "LLMTimeoutError", "LLMSubprocessError",
        "EmbeddingAdapter", "OpenAICompatibleEmbeddingAdapter", "EmbeddingCache",
        "cosine_similarity",
    ]
    missing = [name for name in expected if not hasattr(llm_connect, name)]
    assert missing == [], f"Missing public symbols: {missing}"


def test_mock_adapter_execute():
    adapter = MockLLMAdapter(mock_response="hello from mock")
    config  = RunConfig()
    result  = adapter.execute_prompt("any prompt", config)

    assert isinstance(result, LLMResponse)
    assert result.content == "hello from mock"
    assert adapter.call_count == 1


def test_mock_adapter_reset():
    adapter = MockLLMAdapter(mock_response="x")
    adapter.execute_prompt("p", RunConfig())
    adapter.reset()
    assert adapter.call_count == 0


def test_run_config_defaults():
    cfg = RunConfig()
    assert cfg.temperature >= 0
    assert cfg.max_tokens > 0


def test_llm_response_fields():
    r = LLMResponse(content="ok", model="test-model")
    assert r.content == "ok"
    assert r.model  == "test-model"


def test_error_adapter_raises():
    from llm_connect import ErrorLLMAdapter
    adapter = ErrorLLMAdapter(error_message="simulated failure")
    try:
        adapter.execute_prompt("p", RunConfig())
        assert False, "should have raised"
    except (LLMError, RuntimeError) as e:
        assert "simulated failure" in str(e)
