"""Tests for llmhosts_core — runs against REAL compiled Rust extension.

Skipped in CI when the Rust extension is not built (maturin develop required).
"""

from __future__ import annotations

import pytest

from llmhosts.inference.core import LLMHOSTS_CORE_AVAILABLE

requires_core = pytest.mark.skipif(
    not LLMHOSTS_CORE_AVAILABLE,
    reason="Rust extension _llmhosts_core not built (run: cd llmhosts_core && maturin develop)",
)


@pytest.mark.unit
class TestLLMHostsEngineReal:
    @requires_core
    def test_extension_is_available(self) -> None:
        assert LLMHOSTS_CORE_AVAILABLE is True

    def test_engine_creation(self) -> None:
        from llmhosts.inference.core import LLMHostsInferenceEngine

        engine = LLMHostsInferenceEngine()
        assert engine.is_loaded is False

    def test_load_nonexistent_model_raises(self) -> None:
        from llmhosts.inference.core import LLMHostsInferenceEngine

        engine = LLMHostsInferenceEngine()
        if not LLMHOSTS_CORE_AVAILABLE:
            with pytest.raises(RuntimeError, match="not available"):
                engine.load_model("/nonexistent/model.gguf")
        else:
            with pytest.raises((RuntimeError, FileNotFoundError, OSError)):
                engine.load_model("/nonexistent/model.gguf")

    def test_generate_without_model_raises(self) -> None:
        from llmhosts.inference.core import LLMHostsInferenceEngine

        engine = LLMHostsInferenceEngine()
        with pytest.raises(RuntimeError):
            engine.generate("Hello")

    def test_generate_tokens_without_model_raises(self) -> None:
        from llmhosts.inference.core import LLMHostsInferenceEngine

        engine = LLMHostsInferenceEngine()
        with pytest.raises(RuntimeError):
            engine.generate_tokens([1, 2, 3])

    @requires_core
    def test_load_and_generate_with_test_model(self, tmp_path) -> None:
        try:
            from _llmhosts import core as _llmhosts_core_mod
        except ImportError:
            import _llmhosts_core as _llmhosts_core_mod  # type: ignore[no-redef]

        from llmhosts.inference.core import LLMHostsInferenceEngine

        model_path = _llmhosts_core_mod.generate_test_model(str(tmp_path))
        engine = LLMHostsInferenceEngine()
        info = engine.load_model(model_path)
        assert info["architecture"] == "llama"
        assert engine.is_loaded

        tokens = engine.generate_tokens([1, 5, 10], max_tokens=5, temperature=0.0)
        assert isinstance(tokens, list)
        assert len(tokens) > 0
        assert all(isinstance(t, int) for t in tokens)

    def test_unload(self) -> None:
        from llmhosts.inference.core import LLMHostsInferenceEngine

        engine = LLMHostsInferenceEngine()
        engine.unload()  # should not crash even without model

    def test_status(self) -> None:
        from llmhosts.inference.core import LLMHostsInferenceEngine

        engine = LLMHostsInferenceEngine()
        status = engine.status()
        assert status["available"] is LLMHOSTS_CORE_AVAILABLE
        assert status["loaded"] is False
