"""Shared SSR test setup — self-contained, NO backend checkout.

Replaces the old sibling-`backend/` coupling. Two tiers:
  * unit (tests/unit/)        — hermetic. The `client` fixture serves the SSR app with
    `api_client` monkeypatched to return committed fixtures (tests/fixtures/, refreshed
    by scripts/capture-fixtures.sh). No backend, no Docker.
  * integration (tests/integration/) — the `live_client` fixture serves the SSR app with
    `api_client` pointed at a REAL backend container (scripts/backend-for-tests.sh pulls
    + runs it). Skips automatically when Docker/the image isn't available.
"""
import json
import os
import subprocess
import sys

import httpx
import pytest

_HERE = os.path.dirname(os.path.abspath(__file__))
REPO = os.path.dirname(_HERE)
if REPO not in sys.path:
    sys.path.insert(0, REPO)   # SSR modules (content.py, app.py, api_client.py) live at repo root

# api_client raises at import if this is unset. Unit tests monkeypatch api_client so it is
# never used; the integration fixture overrides it to the live backend.
os.environ.setdefault("THERMOGRAPH_API_BASE_INTERNAL", "http://backend.invalid")
os.environ.setdefault("THERMOGRAPH_BASE", "/thermograph")

import content  # noqa: E402  — imports api_client under the env set above

B = content.BASE                     # "/thermograph"
SLUG = "london-england-gb"           # captured into tests/fixtures/ (GB -> Celsius)
MONTH = "july"
FAKE_INDEXNOW_KEY = "test0000indexnow0000key000000000"
_FIXTURE_NAMES = ("home", "sitemap", "hub", "city", "month", "records")

_HARNESS = os.path.join(REPO, "scripts", "backend-for-tests.sh")


def load_fixture(name: str):
    with open(os.path.join(_HERE, "fixtures", f"{name}.json"), encoding="utf-8") as fh:
        return json.load(fh)


def _not_found(detail: str) -> httpx.HTTPStatusError:
    req = httpx.Request("GET", "http://backend.invalid/x")
    resp = httpx.Response(404, request=req, json={"detail": detail})
    return httpx.HTTPStatusError(detail, request=req, response=resp)


# --- unit tier ---------------------------------------------------------------
@pytest.fixture
def client(monkeypatch):
    """TestClient over the SSR app with api_client replaced by the committed fixtures.
    Exercises the rendering layer (content.py + format.py) with zero backend."""
    from fastapi.testclient import TestClient
    import api_client
    import app as ssr_app

    fx = {n: load_fixture(n) for n in _FIXTURE_NAMES}
    monkeypatch.setattr(api_client, "home", lambda: fx["home"])
    monkeypatch.setattr(api_client, "sitemap", lambda: fx["sitemap"])
    monkeypatch.setattr(api_client, "hub", lambda: fx["hub"])
    monkeypatch.setattr(api_client, "indexnow_key", lambda: FAKE_INDEXNOW_KEY)

    def _city(slug, *, origin=None):
        if slug != SLUG:
            raise _not_found("Unknown city.")
        return fx["city"]

    def _month(slug, month):
        if slug != SLUG or month != MONTH:
            raise _not_found("Unknown month.")
        return fx["month"]

    def _records(slug, *, origin=None):
        if slug != SLUG:
            raise _not_found("Unknown city.")
        return fx["records"]

    monkeypatch.setattr(api_client, "city", _city)
    monkeypatch.setattr(api_client, "city_month", _month)
    monkeypatch.setattr(api_client, "city_records", _records)
    return TestClient(ssr_app.app)


# --- integration tier --------------------------------------------------------
def _docker_ok() -> bool:
    try:
        return subprocess.run(["docker", "info"], capture_output=True, timeout=15).returncode == 0
    except Exception:
        return False


@pytest.fixture(scope="session")
def backend_service():
    """Pull + run a real backend container; yield its base URL. Skips if Docker isn't
    available or the image can't be pulled/started, so the unit tier still runs anywhere."""
    if not _docker_ok():
        pytest.skip("Docker not available — skipping integration tier")
    try:
        url = subprocess.run([_HARNESS, "up"], capture_output=True, text=True, timeout=300, check=True).stdout.strip()
    except subprocess.CalledProcessError as e:
        pytest.skip(f"backend harness failed to start (image unavailable?): {e.stderr[-300:]}")
    try:
        yield url
    finally:
        subprocess.run([_HARNESS, "down"], capture_output=True, timeout=60)


@pytest.fixture
def live_client(backend_service, monkeypatch):
    """TestClient over the SSR app with api_client making REAL HTTP to the live backend
    (which runs THERMOGRAPH_BASE=/, so the API is at /api/v{N}, no prefix)."""
    from fastapi.testclient import TestClient
    import api_client
    import app as ssr_app

    monkeypatch.setattr(api_client, "API_BASE", backend_service)
    monkeypatch.setattr(api_client, "_BASE_PREFIX", "")
    api_client._cache.clear()
    return TestClient(ssr_app.app)
