import pytest
from fastapi.testclient import TestClient

import app.dependencies as deps
from app.config import settings
from app.main import app

client = TestClient(app)

HEADER = "X-Remote-User"
# Starlette-TestClient meldet sich als Host "testclient" -> als vertrauten Proxy setzen.
TRUSTED = "testclient"


@pytest.fixture
def forward_auth(monkeypatch):
    monkeypatch.setattr(settings, "trusted_auth_header", HEADER)
    monkeypatch.setattr(settings, "trusted_proxy_ips", TRUSTED)
    monkeypatch.setattr(settings, "admin_users", "atoor,dieterschlueter,dschlueter")
    monkeypatch.setattr(settings, "auth_enabled", True)


def test_forward_auth_provisions_user(forward_auth):
    r = client.get("/api/me", headers={HEADER: "lieschen"})
    assert r.status_code == 200
    body = r.json()
    assert body["external_id"] == "lieschen"
    assert body["is_admin"] is False
    # Nutzer wurde im Store angelegt.
    assert deps.get_store().get_user_by_external_id("lieschen") is not None


def test_admin_users_flagged(forward_auth):
    for name in ("atoor", "dieterschlueter", "dschlueter"):
        r = client.get("/api/me", headers={HEADER: name})
        assert r.status_code == 200
        assert r.json()["is_admin"] is True, name


def test_untrusted_ip_ignores_header(monkeypatch):
    # Proxy-IP passt NICHT zur TestClient-Quelle -> Header wird ignoriert.
    monkeypatch.setattr(settings, "trusted_auth_header", HEADER)
    monkeypatch.setattr(settings, "trusted_proxy_ips", "10.9.9.9")
    monkeypatch.setattr(settings, "auth_enabled", False)  # Fallback -> anonym
    r = client.get("/api/me", headers={HEADER: "angreifer"})
    assert r.status_code == 200
    assert r.json()["external_id"] is None  # nicht als 'angreifer' uebernommen


def test_missing_header_from_trusted_proxy_401(forward_auth):
    r = client.get("/api/me")  # vertrauter Proxy, aber kein Identitaets-Header
    assert r.status_code == 401


def test_get_or_create_idempotent(forward_auth):
    r1 = client.get("/api/me", headers={HEADER: "wiederkehr"})
    r2 = client.get("/api/me", headers={HEADER: "wiederkehr"})
    assert r1.json()["user_id"] == r2.json()["user_id"]
    users = [u for u in deps.get_store().list_users() if u.external_id == "wiederkehr"]
    assert len(users) == 1


def test_admin_users_endpoint_gated(forward_auth):
    # Admin darf die Liste sehen.
    client.get("/api/me", headers={HEADER: "lieschen"})  # einen Nutzer anlegen
    r_admin = client.get("/api/admin/users", headers={HEADER: "dschlueter"})
    assert r_admin.status_code == 200
    assert any(u["external_id"] == "lieschen" for u in r_admin.json())
    # Nicht-Admin wird abgewiesen.
    r_user = client.get("/api/admin/users", headers={HEADER: "lieschen"})
    assert r_user.status_code == 403


def test_static_index_served():
    # Auth aus (LAN-Dev) -> anonymer Nutzer -> Seite wird ausgeliefert.
    r = client.get("/")
    assert r.status_code == 200
    assert "Voice Assistant" in r.text


def test_static_index_gated_without_auth(monkeypatch):
    # Auth an, keine Identitaet -> Seite ist gesperrt (kein Login-URL -> 401).
    monkeypatch.setattr(settings, "auth_enabled", True)
    monkeypatch.setattr(settings, "trusted_auth_header", "")
    monkeypatch.setattr(settings, "trusted_auth_cookie", "")
    monkeypatch.setattr(settings, "sso_login_url", "")
    r = client.get("/", follow_redirects=False)
    assert r.status_code == 401


def test_static_index_redirects_to_sso(monkeypatch):
    # Auth an, keine Identitaet, Login-URL gesetzt -> Redirect zum SSO-Portal.
    monkeypatch.setattr(settings, "auth_enabled", True)
    monkeypatch.setattr(settings, "trusted_auth_header", "")
    monkeypatch.setattr(settings, "trusted_auth_cookie", "")
    monkeypatch.setattr(settings, "sso_login_url", "https://linix.de/yunohost/sso/")
    r = client.get("/", follow_redirects=False)
    assert r.status_code == 302
    assert r.headers["location"].startswith("https://linix.de/yunohost/sso/")


def test_health_open_without_auth(monkeypatch):
    # Health-Check bleibt auch bei aktiver Auth ohne Identitaet erreichbar.
    monkeypatch.setattr(settings, "auth_enabled", True)
    monkeypatch.setattr(settings, "trusted_auth_header", "")
    monkeypatch.setattr(settings, "trusted_auth_cookie", "")
    r = client.get("/health")
    assert r.status_code == 200
