"""Backend tests for new geo endpoint + regression on public endpoints + auth login.

Covers review_request:
  - GET /api/public/geo            (new)
  - GET /api/public/ad-config      (regression)
  - GET /api/public/app-info       (regression)
  - GET /api/public/playback-mode  (regression)
  - POST /api/auth/login           (admin/admin123 seeded)
"""
import os
import requests
import pytest

BASE_URL = os.environ.get("REACT_APP_BACKEND_URL")
if not BASE_URL:
    # fall back to the value present in /app/frontend/.env
    try:
        with open("/app/frontend/.env", "r") as f:
            for line in f:
                if line.startswith("REACT_APP_BACKEND_URL="):
                    BASE_URL = line.split("=", 1)[1].strip()
                    break
    except Exception:
        pass
BASE_URL = (BASE_URL or "").rstrip("/")


@pytest.fixture(scope="module")
def session():
    s = requests.Session()
    s.headers.update({"Content-Type": "application/json"})
    return s


# --- Public geo endpoint (NEW) ---
class TestPublicGeo:
    def test_geo_returns_expected_shape(self, session):
        r = session.get(f"{BASE_URL}/api/public/geo", timeout=15)
        assert r.status_code == 200, r.text
        data = r.json()
        # Required keys must exist
        for key in ("city", "country", "country_code", "source"):
            assert key in data, f"missing key {key} in {data}"
        # source should be one of the proxies (preferably ip-api)
        assert data["source"] in ("ip-api", "ipwho", "none"), data["source"]
        # types
        assert isinstance(data["city"], str)
        assert isinstance(data["country"], str)
        assert isinstance(data["country_code"], str)

    def test_geo_resolves_real_location(self, session):
        """ip-api.com (or fallback) should return at least country for the
        cluster IP. Allow `none` only with a clear warning, but assert that
        we don't hand back an empty payload silently."""
        r = session.get(f"{BASE_URL}/api/public/geo", timeout=15)
        data = r.json()
        if data["source"] == "none":
            pytest.fail(
                f"Geo lookup failed both ip-api and ipwho: {data}. "
                "InfoBar will show '—' to users."
            )
        # When source != none we expect at minimum a country
        assert data["country"], f"Empty country in successful geo response: {data}"


# --- Public ad-config / app-info / playback-mode regression ---
class TestPublicRegression:
    def test_ad_config(self, session):
        r = session.get(f"{BASE_URL}/api/public/ad-config", timeout=10)
        assert r.status_code == 200, r.text
        d = r.json()
        for k in ("enabled", "testing", "app_id", "banner_id", "interstitial_id", "interstitial_every"):
            assert k in d
        # In testing mode banner/interstitial should equal Google's universal test IDs
        if d["testing"]:
            assert d["banner_id"] == "ca-app-pub-3940256099942544/6300978111"
            assert d["interstitial_id"] == "ca-app-pub-3940256099942544/1033173712"

    def test_app_info(self, session):
        r = session.get(f"{BASE_URL}/api/public/app-info", timeout=10)
        assert r.status_code == 200, r.text
        d = r.json()
        for k in ("update", "creator", "support", "flags"):
            assert k in d
        assert "latest_version" in d["update"]
        assert "inline_preview_enabled" in d["flags"]

    def test_playback_mode(self, session):
        r = session.get(f"{BASE_URL}/api/public/playback-mode", timeout=10)
        assert r.status_code == 200, r.text
        d = r.json()
        for k in ("external_player_enabled", "player_notice_enabled", "inline_preview_enabled"):
            assert k in d
            assert isinstance(d[k], bool)


# --- Auth login (seeded admin) ---
class TestAuthLogin:
    def test_login_success(self, session):
        r = session.post(
            f"{BASE_URL}/api/auth/login",
            json={"username": "admin", "password": "admin123"},
            timeout=10,
        )
        assert r.status_code == 200, r.text
        d = r.json()
        # Token can live under access_token / token / jwt depending on impl
        token_key = next((k for k in ("access_token", "token", "jwt") if k in d), None)
        assert token_key, f"No token key in {d}"
        assert isinstance(d[token_key], str) and len(d[token_key]) > 10

    def test_login_invalid(self, session):
        r = session.post(
            f"{BASE_URL}/api/auth/login",
            json={"username": "admin", "password": "wrong"},
            timeout=10,
        )
        assert r.status_code in (400, 401, 403), r.text
