from __future__ import annotations

from pathlib import Path
from types import SimpleNamespace
from typing import Any

import pytest

from src.services import chat_manager as chat_module
from src.services.chat_manager import ChatManager


class _FakeResponse:
    def __init__(self, content: str = "老闆，系統目前穩定。") -> None:
        self._content = content

    def raise_for_status(self) -> None:
        return None

    def json(self) -> dict[str, Any]:
        return {
            "message": {"content": self._content},
            "prompt_eval_count": 11,
            "eval_count": 13,
        }


class _FakeAsyncClient:
    posted: list[tuple[str, dict[str, Any]]] = []

    def __init__(self, *args: Any, **kwargs: Any) -> None:
        self.args = args
        self.kwargs = kwargs

    async def __aenter__(self) -> _FakeAsyncClient:
        return self

    async def __aexit__(self, *args: Any) -> None:
        return None

    async def post(self, url: str, *, json: dict[str, Any]) -> _FakeResponse:
        self.posted.append((url, json))
        return _FakeResponse()


def _settings() -> SimpleNamespace:
    return SimpleNamespace(OPENCLAW_DEFAULT_MODEL="qwen3:14b")


def _fake_ollama_order(_workload_type: str) -> tuple[SimpleNamespace, ...]:
    return (
        SimpleNamespace(url="http://gcp-a:11435", provider_name="ollama_gcp_a"),
        SimpleNamespace(url="http://gcp-b:11436", provider_name="ollama_gcp_b"),
        SimpleNamespace(url="http://local-111:11434", provider_name="ollama_local"),
    )


@pytest.fixture(autouse=True)
def _reset_fake_client() -> None:
    _FakeAsyncClient.posted = []


@pytest.mark.asyncio
async def test_openclaw_chat_uses_ollama_interactive_lane(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    monkeypatch.setattr(chat_module.httpx, "AsyncClient", _FakeAsyncClient)
    monkeypatch.setattr(chat_module, "get_settings", _settings)
    monkeypatch.setattr(
        chat_module,
        "resolve_ollama_order",
        _fake_ollama_order,
    )

    result = await ChatManager()._call_openclaw("system context", "幫我看狀態")

    assert result is not None
    assert "qwen3:14b" in result
    assert "免費" in result

    assert len(_FakeAsyncClient.posted) == 1
    url, payload = _FakeAsyncClient.posted[0]
    assert url == "http://gcp-a:11435/api/chat"
    assert payload["model"] == "qwen3:14b"
    assert payload["messages"][0]["role"] == "system"
    assert payload["messages"][1] == {"role": "user", "content": "幫我看狀態"}


@pytest.mark.asyncio
async def test_nemoclaw_chat_uses_resolved_interactive_lane(
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    monkeypatch.setattr(chat_module.httpx, "AsyncClient", _FakeAsyncClient)
    monkeypatch.setattr(
        chat_module,
        "resolve_ollama_order",
        _fake_ollama_order,
    )

    result = await ChatManager()._call_nemotron("system context", "補充觀點")

    assert result is not None
    url, payload = _FakeAsyncClient.posted[0]
    assert url == "http://gcp-a:11435/api/chat"
    assert payload["model"] == "deepseek-r1:14b"
    assert payload["think"] is False


def test_chat_manager_has_no_direct_gemini_generation_path() -> None:
    source_path = Path(chat_module.__file__).resolve()
    source = source_path.read_text(encoding="utf-8")

    assert "generativelanguage.googleapis.com" not in source
    assert "GEMINI_API_KEY" not in source
