# retoor <retoor@molodetz.nl>

import pytest

from devplacepy.services.moderation import filter as content_filter
from devplacepy.services.moderation.rules import (
    ALWAYS_BLOCK_CATEGORIES,
    FILTER_MODES,
    RULES,
    matches,
    score_for,
)

MODE_ORDER = content_filter.MODE_ORDER
VERDICT_ORDER = content_filter.VERDICT_ORDER

DEVELOPER_PROSE = [
    "Here is a proof of concept for CVE-2024-1234, the exploit overwrites the stack.",
    "The kernel panic dump shows a segmentation fault in the parser.",
    "Reverse engineering this malware sample took two evenings of disassembly.",
    "I hate this framework and everyone who defends it should read the source.",
    "Traceback (most recent call last): RuntimeError: process was killed",
    "Our red team ran a penetration test against the staging cluster.",
    "This weapon of a regex kills my CPU: (a+)+$",
    "The build failed with 'fatal error: cannot execute'.",
]

PROHIBITED_PROSE = [
    ("i will kill you when i find you", "violence"),
    ("go kill yourself, nobody wants you here", "harassment"),
    ("selling stolen credit cards and bank logs here", "illegal"),
    ("how to build a pipe bomb at home", "weapons"),
]


def test_every_rule_has_a_positive_weight_and_a_known_category():
    from devplacepy.database.moderation import REPORT_REASONS

    for rule in RULES:
        assert rule.weight > 0
        assert rule.category in REPORT_REASONS


@pytest.mark.parametrize("text", DEVELOPER_PROSE)
def test_developer_prose_is_never_flagged(text, local_db):
    result = content_filter.classify(text, "review")
    assert result.verdict == "allow", f"{text!r} -> {result}"


@pytest.mark.parametrize("text,category", PROHIBITED_PROSE)
def test_prohibited_prose_is_flagged_with_its_category(text, category, local_db):
    result = content_filter.classify(text, "review")
    assert result.flagged
    assert category in result.categories


def test_the_always_block_categories_block_in_every_active_mode(local_db):
    text = "selling child porn here"
    for mode in ("review", "block"):
        assert content_filter.classify(text, mode).verdict == "block"
    assert content_filter.classify(text, "off").verdict == "allow"


def test_score_is_monotonic_in_the_number_of_matched_rules():
    previous = 0
    accumulated = ""
    for text, _ in PROHIBITED_PROSE:
        accumulated = f"{accumulated}\n{text}"
        current = score_for(accumulated, matches(accumulated))
        assert current >= previous
        previous = current


def test_technical_context_only_ever_lowers_the_score():
    for text, _ in PROHIBITED_PROSE:
        plain = score_for(text, matches(text))
        technical = f"{text}\nThis is a malware analysis write-up."
        discounted = score_for(technical, matches(technical))
        assert discounted <= plain


def test_a_verdict_never_weakens_as_the_mode_strengthens():
    samples = DEVELOPER_PROSE + [text for text, _ in PROHIBITED_PROSE]
    for text in samples:
        previous = -1
        for mode in sorted(FILTER_MODES, key=lambda name: MODE_ORDER[name]):
            current = VERDICT_ORDER[content_filter.classify(text, mode).verdict]
            assert current >= previous, f"{text!r} weakened at mode {mode}"
            previous = current


def test_resolve_verdict_is_total_over_every_mode_and_verdict():
    for mode in FILTER_MODES:
        for verdict in VERDICT_ORDER:
            resolved = content_filter.resolve_verdict(verdict, mode)
            assert resolved in VERDICT_ORDER


def test_classification_failure_falls_back_to_review(monkeypatch, local_db):
    def explode(text):
        raise RuntimeError("rule engine unavailable")

    monkeypatch.setattr(content_filter, "matches", explode)
    result = content_filter.classify("anything at all", "review")
    assert result.verdict == "review"
    assert result.failed is True
    assert result.detail


def test_empty_and_blank_text_is_allowed(local_db):
    for text in ("", "   ", "\n\t"):
        assert content_filter.classify(text, "block").verdict == "allow"


def test_screen_reports_the_worst_field_and_names_every_flagged_one(local_db):
    screening = content_filter.screen(
        {
            "title": "a normal title",
            "content": "i will kill you when i find you",
            "extra": "buy now 100% free money",
        },
        "review",
    )
    assert screening.flagged
    assert "content" in screening.fields
    assert "extra" in screening.fields
    assert "title" not in screening.fields


def test_always_block_categories_are_a_subset_of_the_rule_categories():
    assert ALWAYS_BLOCK_CATEGORIES <= {rule.category for rule in RULES}
