"""Unit tests for document search operation."""

import httpx
import pytest
import respx

from pinecone._internal.http import HTTPClient, HTTPConfig
from pinecone.index.documents import Documents


@respx.mock
def test_search_text_query():
    """Test text-based document search."""
    respx.post("https://test.io/namespaces/my-ns/documents/search").mock(
        return_value=httpx.Response(
            200,
            json={
                "matches": [
                    {"_id": "doc1", "score": 0.95, "title": "Hello World"},
                    {"_id": "doc2", "score": 0.85, "title": "Test"},
                ],
                "namespace": "my-ns",
                "usage": {"read_units": 5},
            },
        )
    )

    client = HTTPClient(api_key="test", config=HTTPConfig(http2=False))
    documents = Documents(http=client, base_url="https://test.io")

    response = documents.search(
        namespace="my-ns",
        top_k=10,
        score_by=[{"type": "text", "field": "title", "query": "hello"}],
        include_fields=["_id", "title"],
    )

    assert len(response.matches) == 2
    assert response.matches[0].id == "doc1"
    assert response.matches[0].score == 0.95
    assert response.namespace == "my-ns"
    assert response.usage.read_units == 5


@respx.mock
def test_search_vector_query():
    """Test vector-based document search."""
    respx.post("https://test.io/namespaces/my-ns/documents/search").mock(
        return_value=httpx.Response(
            200,
            json={
                "matches": [{"_id": "doc1", "score": 0.92}],
                "namespace": "my-ns",
                "usage": {"read_units": 3},
            },
        )
    )

    client = HTTPClient(api_key="test", config=HTTPConfig(http2=False))
    documents = Documents(http=client, base_url="https://test.io")

    response = documents.search(
        namespace="my-ns",
        top_k=5,
        score_by=[{"type": "dense_vector", "field": "vec", "values": [0.1, 0.2, 0.3]}],
    )

    assert len(response.matches) == 1
    assert response.matches[0].id == "doc1"
    assert response.namespace == "my-ns"


@respx.mock
def test_search_validates_empty_namespace():
    """Test that empty namespace raises ValueError."""
    client = HTTPClient(api_key="test", config=HTTPConfig(http2=False))
    documents = Documents(http=client, base_url="https://test.io")

    with pytest.raises(ValueError, match="namespace"):
        documents.search(
            namespace="",
            top_k=10,
            score_by=[{"type": "text", "field": "title", "query": "test"}],
        )


@respx.mock
def test_search_validates_top_k_range():
    """Test that top_k out of range raises ValueError."""
    client = HTTPClient(api_key="test", config=HTTPConfig(http2=False))
    documents = Documents(http=client, base_url="https://test.io")

    with pytest.raises(ValueError, match="top_k"):
        documents.search(
            namespace="my-ns",
            top_k=0,
            score_by=[{"type": "text", "field": "title", "query": "test"}],
        )

    with pytest.raises(ValueError, match="top_k"):
        documents.search(
            namespace="my-ns",
            top_k=10001,
            score_by=[{"type": "text", "field": "title", "query": "test"}],
        )


@respx.mock
def test_search_validates_empty_score_by():
    """Test that empty score_by raises ValueError."""
    client = HTTPClient(api_key="test", config=HTTPConfig(http2=False))
    documents = Documents(http=client, base_url="https://test.io")

    with pytest.raises(ValueError, match="score_by must not be empty"):
        documents.search(namespace="my-ns", top_k=10, score_by=[])


@respx.mock
def test_search_with_typed_models():
    """Test search with typed query models."""
    from pinecone.models import DenseVectorQuery, SparseVectorQuery
    from pinecone.models.documents import SparseValues

    respx.post("https://test.io/namespaces/my-ns/documents/search").mock(
        return_value=httpx.Response(
            200,
            json={
                "matches": [{"_id": "doc1", "score": 0.92}],
                "namespace": "my-ns",
                "usage": {"read_units": 3},
            },
        )
    )

    client = HTTPClient(api_key="test", config=HTTPConfig(http2=False))
    documents = Documents(http=client, base_url="https://test.io")

    # Test with DenseVectorQuery
    response = documents.search(
        namespace="my-ns",
        top_k=5,
        score_by=[DenseVectorQuery(field="vec", values=[0.1, 0.2, 0.3])],
    )

    assert len(response.matches) == 1
    assert response.namespace == "my-ns"

    # Test with SparseVectorQuery
    respx.clear()
    respx.post("https://test.io/namespaces/my-ns/documents/search").mock(
        return_value=httpx.Response(
            200,
            json={
                "matches": [{"_id": "doc2", "score": 0.85}],
                "namespace": "my-ns",
                "usage": {"read_units": 2},
            },
        )
    )

    response = documents.search(
        namespace="my-ns",
        top_k=5,
        score_by=[
            SparseVectorQuery(
                field="sparse_vec",
                sparse_values=SparseValues(indices=[0, 5, 10], values=[0.5, 0.3, 0.8]),
            )
        ],
    )

    assert len(response.matches) == 1
    assert response.matches[0].id == "doc2"
