from fastapi.testclient import TestClient

import backend.models as models
from backend import config
from backend.main import app

_PAYLOAD = {
    "data": [
        {
            "id": "openai/gpt-4o",
            "name": "GPT-4o",
            "pricing": {"prompt": "0.0000025", "completion": "0.00001"},
            "context_length": 128000,
            "architecture": {"input_modalities": ["text", "image"],
                             "output_modalities": ["text"]},
        },
        {
            "id": "google/gemini-2.5-pro",
            "name": "Gemini 2.5 Pro",
            "pricing": {"prompt": "0.00000125", "completion": "0.00001"},
            "context_length": 1000000,
            "architecture": {"modality": "text+image->text"},
        },
        {
            "id": "meta-llama/llama-3.1-70b-instruct",
            "name": "Llama 3.1 70B Instruct",
            "pricing": {"prompt": "0.0000005", "completion": "0.0000008"},
            "context_length": 131072,
            "architecture": {"input_modalities": ["text"],
                             "output_modalities": ["text"]},
        },
    ]
}


def _reset_cache():
    models._cache["models"] = None
    models._cache["at"] = 0.0


def test_models_endpoint_normalizes_pricing(monkeypatch):
    _reset_cache()
    monkeypatch.setattr(models, "_fetch_openrouter_models", lambda: _PAYLOAD["data"])
    client = TestClient(app)
    response = client.get("/models")
    assert response.status_code == 200
    body = response.json()
    assert body["defaults"] == {"vision": config.MODEL, "text": config.TEXT_MODEL}
    by_id = {m["id"]: m for m in body["text"]}
    assert by_id["openai/gpt-4o"]["prompt_usd_per_mtok"] == 2.5
    assert by_id["openai/gpt-4o"]["completion_usd_per_mtok"] == 10.0
    assert by_id["openai/gpt-4o"]["context_length"] == 128000


def test_models_endpoint_splits_vision_and_text(monkeypatch):
    _reset_cache()
    monkeypatch.setattr(models, "_fetch_openrouter_models", lambda: _PAYLOAD["data"])
    client = TestClient(app)
    body = client.get("/models").json()
    vision_ids = {m["id"] for m in body["vision"]}
    text_ids = {m["id"] for m in body["text"]}
    # Both modality shapes (structured and legacy string) are recognized.
    assert vision_ids == {"openai/gpt-4o", "google/gemini-2.5-pro"}
    # Text list is the full catalog; vision models appear in both.
    assert text_ids == {"openai/gpt-4o", "google/gemini-2.5-pro",
                        "meta-llama/llama-3.1-70b-instruct"}


def test_models_endpoint_caches(monkeypatch):
    _reset_cache()
    calls = []

    def fake_fetch():
        calls.append(1)
        return _PAYLOAD["data"]

    monkeypatch.setattr(models, "_fetch_openrouter_models", fake_fetch)
    client = TestClient(app)
    assert client.get("/models").status_code == 200
    assert client.get("/models").status_code == 200
    assert len(calls) == 1


def test_models_endpoint_502_on_fetch_failure(monkeypatch):
    _reset_cache()
    monkeypatch.setattr(models, "_fetch_openrouter_models", lambda: None)
    client = TestClient(app)
    assert client.get("/models").status_code == 502
