"""Integration test for the GET /messages server-side pagination cap (H_TEST3).

The sibling black-box test ``test_chat_large_data.test_pagination_limits_enforced``
notes inline that it "can't directly test the limit was capped without having
100+ messages". This module closes that gap by seeding 100+ real messages for
an authenticated user and asserting the route clamps an oversized ``limit`` to
the 100-row maximum while reporting ``has_more``.

Seeding 100+ messages must go through the real send route (the per-user
encrypted chat DB only exists behind the authenticated client), but that route
is rate limited to 10/min. We therefore disable the shared limiter for the
seeding loop only and restore its prior state afterwards — which is why this
test lives in its own file rather than the ``no-sut-import`` black-box module.
"""

import json

import pytest

# NB: import via the non-``src`` package path — that is the module instance
# the running app (local_deep_research.web.app_factory) binds its routes to.
# The package is importable under both ``local_deep_research`` and
# ``src.local_deep_research``, which are DISTINCT module objects with separate
# ``limiter`` singletons; toggling the wrong one is a no-op against the app.
from local_deep_research.security.rate_limiter import limiter


@pytest.fixture
def _limiter_disabled():
    """Disable the global rate limiter for the duration of a test, restoring
    its previous ``enabled`` state afterwards."""
    previous = limiter.enabled
    limiter.enabled = False
    try:
        yield
    finally:
        limiter.enabled = previous


def test_pagination_cap_fires_with_over_100_messages(
    authenticated_client, _limiter_disabled
):
    """With >100 messages present, GET /messages clamps ``limit`` to 100 and
    sets ``has_more``; an in-range ``limit`` is honoured exactly."""
    create_response = authenticated_client.post(
        "/api/chat/sessions",
        json={"initial_query": "Pagination cap test"},
        content_type="application/json",
    )
    session_id = json.loads(create_response.data)["session_id"]

    # Seed 105 messages (> the 100 cap). trigger_research=False keeps each
    # send to a single message INSERT (no research/LLM work).
    for i in range(105):
        resp = authenticated_client.post(
            f"/api/chat/sessions/{session_id}/messages",
            json={"content": f"Message {i}", "trigger_research": False},
            content_type="application/json",
        )
        assert resp.status_code == 200, (
            f"seed send {i} returned {resp.status_code}: {resp.data[:200]!r}"
        )

    # Ask for far more than the cap: the route must clamp the page to 100 and
    # tell the client more rows exist.
    resp = authenticated_client.get(
        f"/api/chat/sessions/{session_id}/messages",
        query_string={"limit": 500},
    )
    assert resp.status_code == 200
    data = json.loads(resp.data)
    assert data["success"] is True
    assert len(data["messages"]) == 100, (
        f"limit=500 should be capped to 100, got {len(data['messages'])}"
    )
    assert data["has_more"] is True

    # A smaller in-range limit is honoured exactly, also with has_more.
    resp = authenticated_client.get(
        f"/api/chat/sessions/{session_id}/messages",
        query_string={"limit": 50},
    )
    data = json.loads(resp.data)
    assert len(data["messages"]) == 50
    assert data["has_more"] is True
