"""Unit tests for AirLLM backend graceful degradation.

Verifies that setting TIMMY_MODEL_BACKEND=airllm on non-Apple-Silicon hardware
(Intel Mac, Linux, Windows) or when the airllm package is not installed
falls back to the Ollama backend without crashing.

Refs #1284
"""

from unittest.mock import MagicMock, patch

import pytest

pytestmark = pytest.mark.unit


class TestIsAppleSilicon:
    """is_apple_silicon() correctly identifies the host platform."""

    def test_returns_true_on_arm64_darwin(self):
        from timmy.backends import is_apple_silicon

        with (
            patch("platform.system", return_value="Darwin"),
            patch("platform.machine", return_value="arm64"),
        ):
            assert is_apple_silicon() is True

    def test_returns_false_on_intel_mac(self):
        from timmy.backends import is_apple_silicon

        with (
            patch("platform.system", return_value="Darwin"),
            patch("platform.machine", return_value="x86_64"),
        ):
            assert is_apple_silicon() is False

    def test_returns_false_on_linux(self):
        from timmy.backends import is_apple_silicon

        with (
            patch("platform.system", return_value="Linux"),
            patch("platform.machine", return_value="x86_64"),
        ):
            assert is_apple_silicon() is False

    def test_returns_false_on_windows(self):
        from timmy.backends import is_apple_silicon

        with (
            patch("platform.system", return_value="Windows"),
            patch("platform.machine", return_value="AMD64"),
        ):
            assert is_apple_silicon() is False


class TestAirLLMGracefulDegradation:
    """create_timmy(backend='airllm') falls back to Ollama on unsupported platforms."""

    def _make_fake_ollama_agent(self):
        """Return a lightweight stub that satisfies the Agno Agent interface."""
        agent = MagicMock()
        agent.run = MagicMock(return_value=MagicMock(content="ok"))
        return agent

    def test_falls_back_to_ollama_on_non_apple_silicon(self, caplog):
        """On Intel/Linux, airllm backend logs a warning and creates an Ollama agent."""
        import logging

        from timmy.agent import create_timmy

        fake_agent = self._make_fake_ollama_agent()

        with (
            patch("timmy.backends.is_apple_silicon", return_value=False),
            patch("timmy.agent._create_ollama_agent", return_value=fake_agent) as mock_create,
            patch("timmy.agent._resolve_model_with_fallback", return_value=("qwen3:8b", False)),
            patch("timmy.agent._check_model_available", return_value=True),
            patch("timmy.agent._build_tools_list", return_value=[]),
            patch("timmy.agent._build_prompt", return_value="test prompt"),
            caplog.at_level(logging.WARNING, logger="timmy.agent"),
        ):
            result = create_timmy(backend="airllm")

        assert result is fake_agent
        mock_create.assert_called_once()
        assert "Apple Silicon" in caplog.text

    def test_falls_back_to_ollama_when_airllm_not_installed(self, caplog):
        """When the airllm package is missing, log a warning and use Ollama."""
        import logging

        from timmy.agent import create_timmy

        fake_agent = self._make_fake_ollama_agent()

        # Simulate Apple Silicon + missing airllm package
        def _import_side_effect(name, *args, **kwargs):
            if name == "airllm":
                raise ImportError("No module named 'airllm'")
            return original_import(name, *args, **kwargs)

        original_import = (
            __builtins__["__import__"] if isinstance(__builtins__, dict) else __import__
        )

        with (
            patch("timmy.backends.is_apple_silicon", return_value=True),
            patch("builtins.__import__", side_effect=_import_side_effect),
            patch("timmy.agent._create_ollama_agent", return_value=fake_agent) as mock_create,
            patch("timmy.agent._resolve_model_with_fallback", return_value=("qwen3:8b", False)),
            patch("timmy.agent._check_model_available", return_value=True),
            patch("timmy.agent._build_tools_list", return_value=[]),
            patch("timmy.agent._build_prompt", return_value="test prompt"),
            caplog.at_level(logging.WARNING, logger="timmy.agent"),
        ):
            result = create_timmy(backend="airllm")

        assert result is fake_agent
        mock_create.assert_called_once()
        assert "airllm" in caplog.text.lower() or "AirLLM" in caplog.text

    def test_airllm_backend_does_not_raise(self):
        """create_timmy(backend='airllm') never raises — it degrades gracefully."""
        from timmy.agent import create_timmy

        fake_agent = self._make_fake_ollama_agent()

        with (
            patch("timmy.backends.is_apple_silicon", return_value=False),
            patch("timmy.agent._create_ollama_agent", return_value=fake_agent),
            patch("timmy.agent._resolve_model_with_fallback", return_value=("qwen3:8b", False)),
            patch("timmy.agent._check_model_available", return_value=True),
            patch("timmy.agent._build_tools_list", return_value=[]),
            patch("timmy.agent._build_prompt", return_value="test prompt"),
        ):
            # Should not raise under any circumstances
            result = create_timmy(backend="airllm")

        assert result is not None
