"""Walking-skeleton + API smoke tests — no CLAP/torch required.

Cover the seams that must hold: the app boots, /v1/healthz answers, /me echoes
identity, and auth fails closed / opens with a valid token. The actual emotion
inference is exercised separately (slow, needs CLAP) — here we only assert the
route is wired & guarded, by monkeypatching the engine call. Env/DB/path setup
is in conftest.py.

    cd armada/api && ~/.virtualenvs/douanier/bin/python -m pytest tests/ -q
"""
from fastapi.testclient import TestClient

import app as APP
from engines import ears

client = TestClient(APP.app)
AUTH = {"Authorization": "Bearer test-secret"}


def test_healthz_ok():
    r = client.get("/v1/healthz")
    assert r.status_code == 200
    body = r.json()
    assert body["service"] == "douanier" and body["version"] == "v1"
    assert "emotion" in body["engines"]


def test_me_echoes_identity():
    r = client.get("/v1/me", headers=AUTH)
    assert r.status_code == 200
    assert r.json()["account"] == "dev"


def test_me_requires_token():
    assert client.get("/v1/me").status_code == 401


def test_emotion_requires_token():
    r = client.post("/v1/analyze/emotion", files={"file": ("c.wav", b"RIFF....", "audio/wav")})
    assert r.status_code == 401


def test_emotion_rejects_bad_token():
    r = client.post("/v1/analyze/emotion",
                    files={"file": ("c.wav", b"RIFF....", "audio/wav")},
                    headers={"Authorization": "Bearer nope"})
    assert r.status_code == 401


def test_emotion_happy_path_and_cache(monkeypatch):
    # Stub the heavy CLAP call — we're testing the route/contract + cache, not the model.
    fake = {"valence": 0.42, "arousal": -0.10, "top": [["warm", 0.5]], "confidence": 0.2}
    calls = {"n": 0}

    def _fake(_p):
        calls["n"] += 1
        return fake
    monkeypatch.setattr(ears, "emotion_of", _fake)

    payload = b"UNIQUE-cache-probe-bytes-9f3a"   # undecodable → raw_ content id
    files = {"file": ("c.wav", payload, "audio/wav")}

    r1 = client.post("/v1/analyze/emotion", files=files, headers=AUTH)
    assert r1.status_code == 200
    assert r1.headers["X-Douanier-Cache"] == "miss"
    assert r1.json()["emotion"]["valence"] == 0.42
    assert r1.json()["content_id"].startswith(("cid_", "raw_"))

    r2 = client.post("/v1/analyze/emotion", files=files, headers=AUTH)
    assert r2.headers["X-Douanier-Cache"] == "hit"
    assert calls["n"] == 1            # engine ran ONCE; 2nd served from cache


def test_emotion_too_large(monkeypatch):
    monkeypatch.setattr(APP.config, "MAX_UPLOAD_MB", 0)  # everything is too large
    r = client.post("/v1/analyze/emotion",
                    files={"file": ("c.wav", b"x" * 1024, "audio/wav")}, headers=AUTH)
    assert r.status_code == 413
