"""Couvre `LocalePipeline`'s second `PhraseMatcher` (ustensiles,
`utensil_vocabulary.py`) — même style que `test_locale_pipeline_entities.py`
(offsets exacts, insensibilité accents/casse), mais contre le vocabulaire
*réel* (`UTENSIL_VOCABULARY`, statique, construit par `preload()` — pas
besoin d'un jeu de test dédié comme pour les techniques, voir
`LocalePipeline.preload`'s own comment)."""

from intent_service.locale_pipeline import LocalePipeline, TrainEntry

# Un `train()` minimal suffit — le `PhraseMatcher` d'ustensiles est
# construit par `preload()` (appelé par `train()`), indépendamment du
# `TrainEntry` de techniques passé ici (voir `preload()`'s own comment sur
# pourquoi les deux ne sont pas couplés).
_MINIMAL_ENTRIES = [
    TrainEntry(uid="melt", synonyms=["fondre"], utterances=["faire fondre le beurre"]),
    TrainEntry(uid="simmer", synonyms=["mijoter"], utterances=["faire mijoter à feu doux"]),
]


def _fr_pipeline() -> LocalePipeline:
    pipeline = LocalePipeline("fr")
    pipeline.train(_MINIMAL_ENTRIES)
    return pipeline


def test_matches_a_real_utensil_with_exact_span():
    pipeline = _fr_pipeline()
    text = "Dans une poêle chaude, faire fondre le beurre"
    result = pipeline.process(text)

    pan_entities = [e for e in result.entities if e.uid == "pan"]
    assert len(pan_entities) == 1
    entity = pan_entities[0]
    assert entity.kind == "utensil"
    assert text[entity.start : entity.end] == "poêle"


def test_is_case_and_accent_insensitive():
    pipeline = _fr_pipeline()
    result = pipeline.process("Verser dans la POÊLE")
    utensil_uids = [e.uid for e in result.entities if e.kind == "utensil"]
    assert utensil_uids == ["pan"]


def test_matches_a_multi_word_synonym():
    pipeline = _fr_pipeline()
    text = "Découper les légumes sur la planche à découper"
    result = pipeline.process(text)
    board_entities = [e for e in result.entities if e.uid == "cuttingBoard"]
    assert len(board_entities) == 1
    assert text[board_entities[0].start : board_entities[0].end] == "planche à découper"


def test_technique_and_utensil_are_both_returned_without_interfering():
    pipeline = _fr_pipeline()
    text = "Dans une casserole, faire mijoter à feu doux"
    result = pipeline.process(text)

    kinds_by_uid = {e.uid: e.kind for e in result.entities}
    assert kinds_by_uid.get("simmer") == "technique"
    assert kinds_by_uid.get("saucepan") == "utensil"


def test_returns_no_utensil_entities_when_none_are_mentioned():
    pipeline = _fr_pipeline()
    result = pipeline.process("Laisser reposer la pâte une heure")
    assert [e for e in result.entities if e.kind == "utensil"] == []


def test_matches_english_utensils_too():
    pipeline = LocalePipeline("en")
    pipeline.train([TrainEntry(uid="chop", synonyms=["chop"], utterances=["chop the onions finely"])])
    text = "Heat the pan before adding the onions"
    result = pipeline.process(text)
    pan_entities = [e for e in result.entities if e.uid == "pan"]
    assert len(pan_entities) == 1
    assert pan_entities[0].kind == "utensil"
    assert text[pan_entities[0].start : pan_entities[0].end] == "pan"
