"""Tests for the layered matching engine."""

import pytest

from agent_samochodowy.matcher.engine import match
from agent_samochodowy.matcher.index import CatalogIndex
from agent_samochodowy.models import Offer, PartQuery


@pytest.fixture
def index() -> CatalogIndex:
    """Build an in-memory index with sample offers."""
    idx = CatalogIndex(":memory:")
    offers = [
        Offer(
            offer_id="1", platform="allegro", url="https://a.pl/1",
            title="Pompa wody VOLVO FH13 D13A 20744939",
            brand="VOLVO", model="FH13", category="pompa",
            engine_code="D13A",
            oe_numbers=["20744939", "20734268"],
        ),
        Offer(
            offer_id="2", platform="ebay", url="https://e.com/2",
            title="Alternator OPEL Astra F C18NZ 0120488234",
            brand="OPEL", model="Astra F", category="alternator",
            engine_code="C18NZ",
            oe_numbers=["0120488234"],
        ),
        Offer(
            offer_id="3", platform="allegro", url="https://a.pl/3",
            title="Klocki hamulcowe MAN TGA 81508206039",
            brand="MAN", model="TGA", category="klocki",
            oe_numbers=["81508206039"],
        ),
        Offer(
            offer_id="4", platform="allegro", url="https://a.pl/4",
            title="Filtr oleju SCANIA R500",
            brand="SCANIA", model="R500", category="filtr",
            oe_numbers=[],
        ),
    ]
    idx.build_from_offers(offers)
    return idx


class TestOeMatch:
    def test_exact_oe_match(self, index: CatalogIndex):
        query = PartQuery(
            is_part_request=True,
            raw_text="szukam pompy 20744939",
            oe_numbers=["20744939"],
        )
        result = match(query, index)
        assert result.matched is True
        assert result.method == "oe"
        assert result.confidence == 0.95
        assert any(o.offer_id == "1" for o in result.offers)

    def test_oe_no_hit(self, index: CatalogIndex):
        query = PartQuery(
            is_part_request=True,
            raw_text="szukam 999999999",
            oe_numbers=["999999999"],
        )
        result = match(query, index)
        # Falls through all layers
        assert result.method in ("fuzzy", "brak")


class TestEngineCodeMatch:
    def test_engine_code_match(self, index: CatalogIndex):
        query = PartQuery(
            is_part_request=True,
            raw_text="alternator do Opla C18NZ",
            engine_code="C18NZ",
            brand="OPEL",
        )
        result = match(query, index)
        assert result.matched is True
        assert result.method == "engine_code"
        assert result.confidence == 0.80


class TestAttributeMatch:
    def test_brand_model_category_confirmed(self, index: CatalogIndex):
        """All three attributes confirmed → 0.90."""
        query = PartQuery(
            is_part_request=True,
            raw_text="klocki MAN TGA",
            brand="MAN",
            model="TGA",
            category="klocki",
        )
        result = match(query, index)
        assert result.matched is True
        assert result.method == "atrybuty"
        assert result.confidence == 0.90

    def test_brand_category_only(self, index: CatalogIndex):
        query = PartQuery(
            is_part_request=True,
            raw_text="filtr Scania",
            brand="SCANIA",
            category="filtr",
        )
        result = match(query, index)
        assert result.matched is True
        assert result.method == "atrybuty"
        assert result.confidence == 0.55

    def test_wrong_category_rejected(self, index: CatalogIndex):
        """brand+model match but wrong category → no match (not random parts)."""
        query = PartQuery(
            is_part_request=True,
            raw_text="rozrusznik MAN TGA",
            brand="MAN",
            model="TGA",
            category="rozrusznik",
        )
        result = match(query, index)
        # No rozrusznik in catalog for MAN TGA → should NOT return klocki
        assert result.method != "atrybuty" or result.confidence < 0.40

    def test_flexible_model_match(self, index: CatalogIndex):
        """Model variant 'TGA xyz' should match catalog model 'TGA'."""
        query = PartQuery(
            is_part_request=True,
            raw_text="klocki MAN TGA xxl",
            brand="MAN",
            model="TGA xxl",
            category="klocki",
        )
        result = match(query, index)
        assert result.matched is True
        assert result.method == "atrybuty"
        assert result.confidence == 0.90  # base model "TGA" matches


class TestNoMatch:
    def test_completely_unrelated(self, index: CatalogIndex):
        query = PartQuery(
            is_part_request=True,
            raw_text="potrzebuję zderzak Fiat Ducato 2015",
            brand="FIAT",
            model="Ducato",
            category="zderzak",
        )
        result = match(query, index)
        # No Fiat in catalog → brak or low-confidence fuzzy
        assert result.confidence < 0.5


class TestLayerPriority:
    def test_oe_wins_over_attributes(self, index: CatalogIndex):
        """When OE matches, engine_code/attributes layers are not reached."""
        query = PartQuery(
            is_part_request=True,
            raw_text="pompa Volvo 20744939",
            brand="VOLVO",
            model="FH13",
            category="pompa",
            engine_code="D13A",
            oe_numbers=["20744939"],
        )
        result = match(query, index)
        assert result.method == "oe"
        assert result.confidence == 0.95
