from __future__ import annotations

"""Tests for lab health query helpers and route payloads."""

import json
from urllib.error import URLError

from atlas_portal.app_factory import create_app
from atlas_portal.routes import lab


class DummyUrlResponse:
    """Small context-manager response for urlopen tests."""

    def __init__(self, payload: dict | str, *, status: int = 200) -> None:
        self.payload = payload
        self.status = status

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc, tb):
        return False

    def read(self, size: int | None = None) -> bytes:
        """Return JSON or string content as response bytes."""

        if isinstance(self.payload, str):
            return self.payload.encode("utf-8")
        return json.dumps(self.payload).encode("utf-8")


def test_vm_query_success_and_empty_paths(monkeypatch) -> None:
    payloads = [
        {"status": "success", "data": {"result": [{"value": [0, "2"]}, {"value": [0, "5"]}]}},
        {"status": "error"},
        {"status": "success", "data": {"result": []}},
        {"status": "success", "data": {"result": [{"bad": []}]}},
    ]

    def fake_urlopen(url, timeout):
        return DummyUrlResponse(payloads.pop(0))

    monkeypatch.setattr(lab, "urlopen", fake_urlopen)

    assert lab._vm_query("up") == 5.0
    assert lab._vm_query("up") is None
    assert lab._vm_query("up") is None
    assert lab._vm_query("up") is None


def test_vm_query_vector_filters_bad_samples(monkeypatch) -> None:
    payload = {
        "status": "success",
        "data": {
            "result": [
                {"metric": {"service": "nextcloud"}, "value": [0, "12"]},
                {"metric": {"service": "broken"}, "value": []},
            ],
        },
    }

    monkeypatch.setattr(lab, "urlopen", lambda url, timeout: DummyUrlResponse(payload))

    assert lab._vm_query_vector("topk(1, up)") == [{"metric": {"service": "nextcloud"}, "value": 12.0}]


def test_public_active_service_uses_external_ai_chat_url(monkeypatch) -> None:
    monkeypatch.setattr(lab.settings, "LAB_ACTIVE_SERVICE_QUERY", "topk(1, fake)")
    monkeypatch.setattr(
        lab,
        "_vm_query_vector",
        lambda expr: [{"metric": {"service": "atlas-ai-chat"}, "value": 9.0}],
    )

    assert lab._public_active_service() == {
        "known": True,
        "label": "AI Chat",
        "url": "https://bstein.dev/ai/chat",
        "window": lab.settings.LAB_ACTIVE_SERVICE_WINDOW,
    }


def test_http_ok_status_substring_and_errors(monkeypatch) -> None:
    responses = [
        DummyUrlResponse("service ok"),
        DummyUrlResponse("wrong body"),
        DummyUrlResponse("bad", status=503),
    ]

    def fake_urlopen(url, timeout):
        item = responses.pop(0)
        if item == "raise":
            raise URLError("offline")
        return item

    monkeypatch.setattr(lab, "urlopen", fake_urlopen)

    assert lab._http_ok("https://grafana", expect_substring="ok")
    assert not lab._http_ok("https://grafana", expect_substring="ok")
    assert not lab._http_ok("https://grafana")
    responses.append("raise")
    assert not lab._http_ok("https://grafana")


def test_lab_status_uses_cache_and_probe_fallbacks(monkeypatch) -> None:
    app = create_app()
    client = app.test_client()
    lab._LAB_STATUS_CACHE["ts"] = 0.0
    lab._LAB_STATUS_CACHE["value"] = None
    monkeypatch.setattr(lab.settings, "ATLAS_DB_HOST_HEALTH_URL", "https://db.example.dev/health")
    monkeypatch.setattr(lab.settings, "ATLAS_JUMPHOST_HEALTH_URL", "https://jump.example.dev/health")

    calls: list[str] = []

    def fake_http_ok(url, expect_substring=None):
        calls.append(url)
        return "grafana" in url or "db" in url or "jump" in url

    monkeypatch.setattr(lab, "_http_ok", fake_http_ok)
    monkeypatch.setattr(lab, "_vm_query", lambda expr: 1.0)
    monkeypatch.setattr(
        lab,
        "_vm_query_vector",
        lambda expr: [{"metric": {"service": "nextcloud-web"}, "value": 8.0}],
    )

    response = client.get("/api/lab/status")
    payload = response.get_json()

    assert response.status_code == 200
    assert response.headers["Cache-Control"] == "no-store, max-age=0"
    assert response.headers["Pragma"] == "no-cache"
    assert payload["connected"] is True
    assert payload["atlas"]["source"] == "grafana"
    assert payload["dedicated_hosts"]["up"] is True
    assert payload["dedicated_hosts"]["up_count"] == 2
    assert payload["dedicated_hosts"]["hosts"][0]["label"] == "Database node"
    assert payload["active_service"] == {
        "known": True,
        "label": "Nextcloud",
        "url": "https://cloud.bstein.dev",
        "window": lab.settings.LAB_ACTIVE_SERVICE_WINDOW,
    }
    assert payload["oceanus"]["source"] == "atlas-member"

    second = client.get("/api/lab/status")
    assert second.get_json() == payload
    assert second.headers["Cache-Control"] == "no-store, max-age=0"

    lab._LAB_STATUS_CACHE["ts"] = 0.0
    lab._LAB_STATUS_CACHE["value"] = None
    monkeypatch.setattr(lab.settings, "ATLAS_DB_HOST_HEALTH_URL", "")
    monkeypatch.setattr(lab.settings, "ATLAS_JUMPHOST_HEALTH_URL", "")
    monkeypatch.setattr(lab, "_http_ok", lambda *a, **k: False)
    monkeypatch.setattr(lab, "_vm_query", lambda expr: 0.0)
    monkeypatch.setattr(lab, "_vm_query_vector", lambda expr: [])

    response = client.get("/api/lab/status")
    payload = response.get_json()

    assert payload["atlas"]["source"] == "victoria-metrics"
    assert payload["atlas"]["up"] is False
    assert payload["dedicated_hosts"]["known"] is True
    assert payload["dedicated_hosts"]["up"] is False
    assert payload["active_service"]["known"] is False


def test_lab_status_handles_probe_exceptions(monkeypatch) -> None:
    app = create_app()
    client = app.test_client()
    lab._LAB_STATUS_CACHE["ts"] = 0.0
    lab._LAB_STATUS_CACHE["value"] = None

    def boom(*args, **kwargs):
        raise RuntimeError("offline")

    monkeypatch.setattr(lab, "_http_ok", boom)
    monkeypatch.setattr(lab, "_vm_query", boom)
    monkeypatch.setattr(lab, "_vm_query_vector", boom)

    response = client.get("/api/lab/status")
    payload = response.get_json()

    assert response.status_code == 200
    assert payload["connected"] is False
    assert payload["atlas"]["known"] is False
    assert payload["dedicated_hosts"]["known"] is False
    assert payload["active_service"]["known"] is False
