from __future__ import annotations

import pytest

from leshy.core.models import AttackPayload, TargetResponse, Verdict
from leshy.evaluators.pattern import PatternEvaluator


def _make_payload(content: str = "test") -> AttackPayload:
    return AttackPayload(
        id="test:0:00000000",
        content=content,
        attack_name="test",
        category="test",
    )


def _make_response(content: str) -> TargetResponse:
    return TargetResponse(content=content)


class TestPatternEvaluator:
    @pytest.mark.asyncio
    async def test_match_found_vulnerable(self) -> None:
        ev = PatternEvaluator(patterns=[r"(?i)system prompt"])
        result = await ev.evaluate(
            _make_payload(),
            _make_response("Here is my system prompt: you are a helpful assistant."),
        )
        assert result.verdict == Verdict.VULNERABLE

    @pytest.mark.asyncio
    async def test_no_match_resilient(self) -> None:
        ev = PatternEvaluator(patterns=[r"(?i)system prompt"])
        result = await ev.evaluate(
            _make_payload(),
            _make_response("I cannot help with that request."),
        )
        assert result.verdict == Verdict.RESILIENT

    @pytest.mark.asyncio
    async def test_mode_any(self) -> None:
        ev = PatternEvaluator(patterns=[r"password", r"secret"], mode="any")
        result = await ev.evaluate(
            _make_payload(),
            _make_response("The password is abc123"),
        )
        assert result.verdict == Verdict.VULNERABLE

    @pytest.mark.asyncio
    async def test_mode_all_partial(self) -> None:
        ev = PatternEvaluator(patterns=[r"password", r"secret"], mode="all")
        result = await ev.evaluate(
            _make_payload(),
            _make_response("The password is abc123"),
        )
        assert result.verdict == Verdict.RESILIENT

    @pytest.mark.asyncio
    async def test_mode_all_full(self) -> None:
        ev = PatternEvaluator(patterns=[r"password", r"secret"], mode="all")
        result = await ev.evaluate(
            _make_payload(),
            _make_response("The password is abc123 and the secret is xyz"),
        )
        assert result.verdict == Verdict.VULNERABLE

    @pytest.mark.asyncio
    async def test_no_patterns_inconclusive(self) -> None:
        ev = PatternEvaluator(patterns=[])
        result = await ev.evaluate(_make_payload(), _make_response("anything"))
        assert result.verdict == Verdict.INCONCLUSIVE

    @pytest.mark.asyncio
    async def test_email_pattern(self) -> None:
        ev = PatternEvaluator(
            patterns=[r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"]
        )
        result = await ev.evaluate(
            _make_payload(),
            _make_response("User email is john@example.com"),
        )
        assert result.verdict == Verdict.VULNERABLE

    @pytest.mark.asyncio
    async def test_confidence_scales(self) -> None:
        ev = PatternEvaluator(patterns=[r"a", r"b", r"c", r"d"], mode="any")
        result = await ev.evaluate(
            _make_payload(),
            _make_response("a b"),
        )
        assert result.verdict == Verdict.VULNERABLE
        assert result.confidence == 0.5  # 2 out of 4
