from fastapi.testclient import TestClient

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

client = TestClient(app)

ADMIN = "admin-secret"


def _enable_auth(monkeypatch):
    monkeypatch.setattr(settings, "auth_enabled", True)
    monkeypatch.setattr(settings, "admin_api_key", ADMIN)


def _create_user(name: str) -> str:
    resp = client.post(
        "/api/admin/users", headers={"X-Admin-Key": ADMIN}, json={"display_name": name}
    )
    assert resp.status_code == 200
    return resp.json()["token"]


def test_protected_endpoint_requires_token(monkeypatch):
    _enable_auth(monkeypatch)
    resp = client.post("/api/speak", json={"text": "x", "tts_provider": "piper"})
    assert resp.status_code == 401


def test_admin_requires_key(monkeypatch):
    _enable_auth(monkeypatch)
    resp = client.post("/api/admin/users", json={"display_name": "Anna"})
    assert resp.status_code == 401


def test_create_user_and_call_me(monkeypatch):
    _enable_auth(monkeypatch)
    token = _create_user("Anna")
    auth = {"Authorization": f"Bearer {token}"}

    me = client.get("/api/me", headers=auth)
    assert me.status_code == 200
    assert me.json()["display_name"] == "Anna"

    bad = client.get("/api/me", headers={"Authorization": "Bearer nope"})
    assert bad.status_code == 401


def test_tenant_isolation_returns_403(monkeypatch):
    _enable_auth(monkeypatch)
    token_a = _create_user("A")
    token_b = _create_user("B")

    client.post(
        "/api/sessions/shared/route",
        headers={"Authorization": f"Bearer {token_a}"},
        json={"tts_provider": "piper"},
    )
    # B versucht die Session von A zu nutzen.
    resp = client.post(
        "/api/speak?session_id=shared",
        headers={"Authorization": f"Bearer {token_b}"},
        json={"text": "x"},
    )
    assert resp.status_code == 403


def test_user_prefs_applied_to_route(monkeypatch):
    _enable_auth(monkeypatch)

    class StubTTS:
        async def synthesize(self, text, voice=None, audio_format="pcm", language=None):
            return b""
    monkeypatch.setitem(deps.TTS_REGISTRY, "stub-tts", lambda s: StubTTS())

    token = _create_user("Pref")
    auth = {"Authorization": f"Bearer {token}"}

    client.put(
        "/api/me/prefs",
        headers=auth,
        json={"tts_provider": "stub-tts", "output_endpoint": "loopback"},
    )
    resp = client.post("/api/speak", headers=auth, json={"text": "hallo"})
    assert resp.status_code == 200
    assert resp.headers["X-TTS-Provider"] == "stub-tts"
    assert resp.headers["X-Output-Endpoint"] == "loopback"


def test_memories_crud(monkeypatch):
    _enable_auth(monkeypatch)
    auth = {"Authorization": f"Bearer {_create_user('Mem')}"}

    assert client.get("/api/me/memories", headers=auth).json() == []

    created = client.post("/api/me/memories", headers=auth, json={"content": "mag Tee"})
    assert created.status_code == 200
    mid = created.json()["id"]

    listed = client.get("/api/me/memories", headers=auth).json()
    assert len(listed) == 1 and listed[0]["content"] == "mag Tee"

    assert client.delete(f"/api/me/memories/{mid}", headers=auth).status_code == 200
    assert client.get("/api/me/memories", headers=auth).json() == []
    assert client.delete("/api/me/memories/9999", headers=auth).status_code == 404


def test_memories_are_per_user(monkeypatch):
    _enable_auth(monkeypatch)
    auth_a = {"Authorization": f"Bearer {_create_user('A')}"}
    auth_b = {"Authorization": f"Bearer {_create_user('B')}"}
    client.post("/api/me/memories", headers=auth_a, json={"content": "geheim A"})
    assert client.get("/api/me/memories", headers=auth_b).json() == []


def test_admin_unconfigured_returns_503(monkeypatch):
    # Auth an, aber kein Admin-Key gesetzt.
    monkeypatch.setattr(settings, "auth_enabled", True)
    monkeypatch.setattr(settings, "admin_api_key", "")
    resp = client.post(
        "/api/admin/users", headers={"X-Admin-Key": "irgendwas"}, json={"display_name": "X"}
    )
    assert resp.status_code == 503
