"""Tests for the FastAPI search router."""

from __future__ import annotations

import pytest

from search.backends.memory import MemoryBackend
from search.config import set_search
from search.models import IndexConfig, SearchDocument


@pytest.fixture()
async def client():
    """Provide an HTTPX async test client with the search router mounted."""
    try:
        from fastapi import FastAPI
        from httpx import ASGITransport, AsyncClient
    except ImportError:
        pytest.skip("fastapi and httpx required for router tests")

    from search.router import create_search_router

    backend = MemoryBackend()
    set_search(backend)

    await backend.create_index(
        IndexConfig(name="articles", searchable_fields=["title", "body"])
    )
    await backend.bulk_index([
        SearchDocument(id="1", content={"title": "Python Basics", "body": "Learn Python"}, index_name="articles"),
        SearchDocument(id="2", content={"title": "Rust Guide", "body": "Systems programming"}, index_name="articles"),
        SearchDocument(id="3", content={"title": "Go Patterns", "body": "Concurrency in Go"}, index_name="articles"),
    ])

    app = FastAPI()
    app.include_router(create_search_router())

    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as ac:
        yield ac


class TestSearchEndpoint:
    async def test_search_returns_results(self, client):
        resp = await client.post("/search/articles", json={"query": "Python"})
        assert resp.status_code == 200
        data = resp.json()
        assert data["total"] >= 1
        assert any(r["id"] == "1" for r in data["results"])

    async def test_search_empty_results(self, client):
        resp = await client.post("/search/articles", json={"query": "nonexistent"})
        assert resp.status_code == 200
        assert resp.json()["total"] == 0

    async def test_search_pagination(self, client):
        resp = await client.post(
            "/search/articles", json={"query": "", "per_page": 2, "page": 1}
        )
        assert resp.status_code == 200
        data = resp.json()
        assert len(data["results"]) == 2
        assert data["per_page"] == 2

    async def test_search_with_filters(self, client):
        resp = await client.post(
            "/search/articles", json={"query": "", "filters": {}}
        )
        assert resp.status_code == 200

    async def test_search_invalid_body(self, client):
        resp = await client.post("/search/articles", json={})
        assert resp.status_code == 422  # missing required 'query'


class TestSuggestEndpoint:
    async def test_suggest_returns_results(self, client):
        resp = await client.get("/search/articles/suggest", params={"q": "Py"})
        assert resp.status_code == 200
        data = resp.json()
        assert data["per_page"] == 5

    async def test_suggest_empty_query_rejected(self, client):
        resp = await client.get("/search/articles/suggest", params={"q": ""})
        assert resp.status_code == 422

    async def test_suggest_custom_limit(self, client):
        resp = await client.get("/search/articles/suggest", params={"q": "test", "limit": 3})
        assert resp.status_code == 200


class TestReindexEndpoint:
    async def test_reindex_returns_501(self, client):
        resp = await client.post("/search/articles/reindex")
        assert resp.status_code == 501
        assert "fetch function" in resp.json()["detail"]
