"""Tests for the relationship cue scanner — ISA/ISPART patterns and of-Z modifier."""
import pytest
from festinger.cue_scanner import scan_cues


def _find(triples, subj, parent, dim=None, is_isa=None):
    for t in triples:
        if t.subject != subj or t.parent != parent:
            continue
        if dim is not None and t.dimension != dim:
            continue
        if is_isa is not None and t.is_isa != is_isa:
            continue
        return t
    return None


# ---------------------------------------------------------------------------
# ISA patterns
# ---------------------------------------------------------------------------

def test_is_a_pattern():
    triples = scan_cues("gnommoweb is a repo")
    t = _find(triples, "gnommoweb", "repo", is_isa=True)
    assert t is not None
    assert t.dimension == "type"


def test_is_an_pattern():
    triples = scan_cues("gnommoweb is an api")
    t = _find(triples, "gnommoweb", "api", is_isa=True)
    assert t is not None


def test_isa_explicit():
    triples = scan_cues("gnommoweb ISA repo")
    t = _find(triples, "gnommoweb", "repo", is_isa=True)
    assert t is not None
    assert t.confidence >= 0.9


def test_of_z_dimension_modifier():
    # "is a repo of Glitch University" → dim = glitch_university
    triples = scan_cues("gnommoweb is a repo of Glitch University")
    t = _find(triples, "gnommoweb", "repo", is_isa=True)
    assert t is not None
    assert t.dimension == "glitch_university"


def test_is_a_state_of_usa():
    # Core scenario A trigger pattern
    triples = scan_cues("michigan is a state of USA")
    t = _find(triples, "michigan", "state", is_isa=True)
    assert t is not None
    assert t.dimension == "usa"


def test_is_a_kind_of():
    triples = scan_cues("gnommoweb is a kind of service")
    t = _find(triples, "gnommoweb", "service", is_isa=True)
    assert t is not None


# ---------------------------------------------------------------------------
# ISPART patterns
# ---------------------------------------------------------------------------

def test_is_part_of():
    triples = scan_cues("gnommoweb is part of Glitch University")
    t = _find(triples, "gnommoweb", "glitch_university", is_isa=False)
    assert t is not None


def test_runs_on():
    triples = scan_cues("gnommoweb runs on Docker")
    t = _find(triples, "gnommoweb", "docker", is_isa=False)
    assert t is not None
    assert t.dimension == "runs-on"


def test_belongs_to():
    triples = scan_cues("gnommoweb belongs to Agent0")
    t = _find(triples, "gnommoweb", "agent0", is_isa=False)
    assert t is not None


def test_is_owned_by():
    triples = scan_cues("gnommoweb is owned by jenstandstad")
    t = _find(triples, "gnommoweb", "jenstandstad", is_isa=False)
    assert t is not None
    assert t.dimension == "owned-by"


def test_deployed_on():
    triples = scan_cues("dobby deployed on docker_host_2")
    t = _find(triples, "dobby", "docker_host_2", is_isa=False)
    assert t is not None
    assert t.dimension == "runs-on"


# ---------------------------------------------------------------------------
# No false positives
# ---------------------------------------------------------------------------

def test_no_match_plain_sentence():
    triples = scan_cues("please update the configuration file")
    assert triples == []


def test_deduplication():
    # Same triple from multiple overlapping patterns should appear once
    triples = scan_cues("gnommoweb is a repo")
    matches = [t for t in triples if t.subject == "gnommoweb" and t.parent == "repo"]
    # May match both "is a" and "is an" patterns but should deduplicate
    assert len(matches) <= 2  # at most one per distinct pattern type
