# SPDX-License-Identifier: Apache-2.0
"""Tests for contradiction detection."""

from nlai import Claim, Evidence, find_contradictions, attach_evidence
from nlai.claims import STATUS_UNSUPPORTED, STATUS_SUPPORTED, STATUS_CONTESTED, STRENGTH_ASSERTIVE
from nlai.contradictions import _normalize_for_matching


def _make_claim(text: str, status: str = STATUS_UNSUPPORTED) -> Claim:
    """Helper to make claims with minimal boilerplate."""
    return Claim(text=text, strength=STRENGTH_ASSERTIVE, status=status)


def _make_supported(text: str) -> Claim:
    """Helper to make a supported claim."""
    c = _make_claim(text)
    return attach_evidence(c, Evidence(kind="test_result", reference="ref"))


class TestFindContradictions:
    """Opposing-pair contradiction detection."""

    def test_no_priors_no_contradictions(self):
        claims = [_make_claim("The system is faster")]
        result = find_contradictions(claims, [])
        assert all(c.status == STATUS_UNSUPPORTED for c in result)

    def test_opposing_pair_detected(self):
        claims = [_make_claim("The system is faster")]
        priors = [_make_supported("The system is slower")]
        result = find_contradictions(claims, priors)
        assert result[0].status == STATUS_CONTESTED
        assert "The system is slower" in result[0].conflicts_with

    def test_case_insensitive(self):
        claims = [_make_claim("It PASSES all checks")]
        priors = [_make_supported("It fails all checks")]
        result = find_contradictions(claims, priors)
        assert result[0].status == STATUS_CONTESTED

    def test_bidirectional(self):
        """If A contradicts B, B also contradicts A."""
        claims_ab = [_make_claim("System is faster")]
        priors_ab = [_make_supported("System is slower")]
        result_ab = find_contradictions(claims_ab, priors_ab)

        claims_ba = [_make_claim("System is slower")]
        priors_ba = [_make_supported("System is faster")]
        result_ba = find_contradictions(claims_ba, priors_ba)

        assert result_ab[0].status == STATUS_CONTESTED
        assert result_ba[0].status == STATUS_CONTESTED

    def test_word_boundary(self):
        """'unsafe' matches opposing pair but 'unsafely' does NOT match 'safe'."""
        # "unsafe" is in the opposing pairs directly
        claims = [_make_claim("The system is unsafe")]
        priors = [_make_supported("The system is safe")]
        result = find_contradictions(claims, priors)
        assert result[0].status == STATUS_CONTESTED

    def test_word_boundary_no_partial(self):
        """Word boundary prevents matching 'insecurely' against 'secure'."""
        claims = [_make_claim("Done insecurely")]
        priors = [_make_supported("It is secure")]
        result = find_contradictions(claims, priors)
        # "insecurely" should NOT match "secure" at word boundary
        assert result[0].status == STATUS_UNSUPPORTED

    def test_multiple_contradictions(self):
        claims = [_make_claim("It is faster and better")]
        priors = [
            _make_supported("It is slower"),
            _make_supported("It is worse"),
        ]
        result = find_contradictions(claims, priors)
        assert result[0].status == STATUS_CONTESTED
        assert len(result[0].conflicts_with) == 2

    def test_no_false_positives(self):
        claims = [_make_claim("The weather is nice")]
        priors = [_make_supported("The code compiles")]
        result = find_contradictions(claims, priors)
        assert result[0].status == STATUS_UNSUPPORTED

    def test_does_not_modify_input(self):
        original = _make_claim("System is faster")
        claims = [original]
        priors = [_make_supported("System is slower")]
        find_contradictions(claims, priors)
        assert original.status == STATUS_UNSUPPORTED
        assert original.conflicts_with == ()

    def test_empty_claims(self):
        result = find_contradictions([], [_make_supported("hello")])
        assert result == []

    def test_unsupported_priors_ignored(self):
        """UNSUPPORTED priors should NOT trigger contradictions."""
        claims = [_make_claim("System is faster")]
        priors = [_make_claim("System is slower", status=STATUS_UNSUPPORTED)]
        result = find_contradictions(claims, priors)
        assert result[0].status == STATUS_UNSUPPORTED

    def test_contested_priors_trigger(self):
        """CONTESTED priors should still trigger contradictions."""
        claims = [_make_claim("System is faster")]
        prior = _make_claim("System is slower", status=STATUS_CONTESTED)
        result = find_contradictions(claims, [prior])
        assert result[0].status == STATUS_CONTESTED


class TestNormalize:
    """Text normalization for matching."""

    def test_whitespace_collapsing(self):
        assert _normalize_for_matching("  hello   world  ") == "hello world"

    def test_lowercase(self):
        assert _normalize_for_matching("HELLO") == "hello"
