"""HTTP-layer coverage for POST /recommendations/event.

`decide()` itself is unit-tested in test_recommendations.py against no
database. This file covers what only exists at the endpoint: request
validation, the response envelope, and the guarantee that a `decide()`
failure surfaces as HTTP 200 with `recommend: false` rather than a 500 -- a
suggestion nobody asked for must never appear as an error in a visitor's
browser.
"""
from unittest.mock import patch

from fastapi.testclient import TestClient

from app.main import app

client = TestClient(app)

VALID_PAYLOAD = {
    "tenant_id": "org_x",
    "visitor_id": "v_test",
    "event": "dwell",
    "page": {"url": "https://s.com/p/1", "dwell_seconds": 60},
}


def test_a_valid_payload_returns_the_envelope_the_frontend_expects():
    with patch("app.api.endpoints.decide",
               return_value={"recommend": True, "message": "Hi",
                             "products": [{"product_id": "sku:1"}]}):
        resp = client.post("/recommendations/event", json=VALID_PAYLOAD)
    assert resp.status_code == 200
    body = resp.json()
    assert body["status"] == "success"
    assert body["recommend"] is True
    assert body["message"] == "Hi"
    assert body["products"] == [{"product_id": "sku:1"}]
    assert body["recommendation_id"].startswith("rec_")


def test_a_negative_decision_returns_the_envelope_without_a_recommendation_id():
    with patch("app.api.endpoints.decide", return_value={"recommend": False, "reason": "no_match"}):
        resp = client.post("/recommendations/event", json=VALID_PAYLOAD)
    assert resp.status_code == 200
    body = resp.json()
    assert body == {"status": "success", "recommend": False, "reason": "no_match"}


def test_missing_tenant_id_is_rejected():
    payload = dict(VALID_PAYLOAD)
    del payload["tenant_id"]
    resp = client.post("/recommendations/event", json=payload)
    assert resp.status_code == 400


def test_missing_visitor_id_is_rejected():
    payload = dict(VALID_PAYLOAD)
    del payload["visitor_id"]
    resp = client.post("/recommendations/event", json=payload)
    assert resp.status_code == 400


def test_missing_page_url_is_rejected():
    payload = dict(VALID_PAYLOAD, page={"dwell_seconds": 60})
    resp = client.post("/recommendations/event", json=payload)
    assert resp.status_code == 400


def test_exit_intent_is_rejected():
    payload = dict(VALID_PAYLOAD, event="exit_intent")
    resp = client.post("/recommendations/event", json=payload)
    assert resp.status_code == 400


def test_decide_raising_never_surfaces_as_a_server_error():
    """A suggestion nobody asked for must never appear as an error in the browser."""
    with patch("app.api.endpoints.decide", side_effect=RuntimeError("db down")):
        resp = client.post("/recommendations/event", json=VALID_PAYLOAD)
    assert resp.status_code == 200
    assert resp.json()["recommend"] is False
