"""Tests for faceted search."""

from __future__ import annotations

import pytest

from search.backends.memory import MemoryBackend
from search.models import (
    IndexConfig,
    SearchDocument,
    SearchQuery,
)


@pytest.fixture()
async def backend() -> MemoryBackend:
    b = MemoryBackend()
    await b.create_index(
        IndexConfig(
            name="products",
            searchable_fields=["name", "description"],
            filterable_fields=["category", "brand", "color"],
        )
    )
    docs = [
        SearchDocument(
            id="1",
            content={"name": "Red Shirt", "description": "Cotton shirt", "category": "clothing", "brand": "Nike", "color": "red"},
            index_name="products",
        ),
        SearchDocument(
            id="2",
            content={"name": "Blue Shirt", "description": "Silk shirt", "category": "clothing", "brand": "Adidas", "color": "blue"},
            index_name="products",
        ),
        SearchDocument(
            id="3",
            content={"name": "Running Shoes", "description": "Lightweight running shoes", "category": "footwear", "brand": "Nike", "color": "black"},
            index_name="products",
        ),
        SearchDocument(
            id="4",
            content={"name": "Casual Shoes", "description": "Everyday casual shoes", "category": "footwear", "brand": "Adidas", "color": "white"},
            index_name="products",
        ),
        SearchDocument(
            id="5",
            content={"name": "Red Hat", "description": "Baseball cap", "category": "accessories", "brand": "Nike", "color": "red"},
            index_name="products",
        ),
    ]
    await b.bulk_index(docs)
    return b


class TestFacetedSearch:
    async def test_single_facet(self, backend: MemoryBackend):
        result = await backend.search(
            "products", SearchQuery(query="", facets=["category"])
        )
        assert "category" in result.facets
        assert result.facets["category"]["clothing"] == 2
        assert result.facets["category"]["footwear"] == 2
        assert result.facets["category"]["accessories"] == 1

    async def test_multiple_facets(self, backend: MemoryBackend):
        result = await backend.search(
            "products", SearchQuery(query="", facets=["category", "brand"])
        )
        assert "category" in result.facets
        assert "brand" in result.facets
        assert result.facets["brand"]["Nike"] == 3
        assert result.facets["brand"]["Adidas"] == 2

    async def test_facets_with_filter(self, backend: MemoryBackend):
        result = await backend.search(
            "products",
            SearchQuery(query="", facets=["brand"], filters={"category": "footwear"}),
        )
        assert result.facets["brand"]["Nike"] == 1
        assert result.facets["brand"]["Adidas"] == 1

    async def test_facets_with_query(self, backend: MemoryBackend):
        result = await backend.search(
            "products", SearchQuery(query="shirt", facets=["category", "color"])
        )
        assert result.facets["category"]["clothing"] == 2
        assert "footwear" not in result.facets["category"]

    async def test_no_facets_when_not_requested(self, backend: MemoryBackend):
        result = await backend.search("products", SearchQuery(query=""))
        assert result.facets == {}

    async def test_facet_for_nonexistent_field(self, backend: MemoryBackend):
        result = await backend.search(
            "products", SearchQuery(query="", facets=["nonexistent"])
        )
        assert result.facets["nonexistent"] == {}
