"""
Tests für den Feedback-Learning-Mechanismus.

Testet wie das System aus Nutzer-Feedback lernt und das Profil anpasst.
"""

import pytest
from datetime import datetime

from alerts_agent.models.relevance_profile import RelevanceProfile, PriorityItem
from alerts_agent.models.alert_item import AlertItem


class TestFeedbackLearning:
    """Tests für den Feedback-Learning-Mechanismus."""

    def test_positive_feedback_adds_example(self):
        """Test positives Feedback fügt Beispiel hinzu."""
        profile = RelevanceProfile()

        profile.update_from_feedback(
            alert_title="Wichtiger Artikel zur Inklusion",
            alert_url="https://example.com/inklusion",
            is_relevant=True,
            reason="Sehr relevant für meine Arbeit",
        )

        assert len(profile.positive_examples) == 1
        assert profile.positive_examples[0]["title"] == "Wichtiger Artikel zur Inklusion"
        assert profile.positive_examples[0]["reason"] == "Sehr relevant für meine Arbeit"

    def test_negative_feedback_adds_example(self):
        """Test negatives Feedback fügt Beispiel hinzu."""
        profile = RelevanceProfile()

        profile.update_from_feedback(
            alert_title="Stellenanzeige Lehrer",
            alert_url="https://example.com/job",
            is_relevant=False,
            reason="Nur Werbung",
        )

        assert len(profile.negative_examples) == 1
        assert profile.negative_examples[0]["title"] == "Stellenanzeige Lehrer"

    def test_feedback_updates_counters(self):
        """Test Feedback aktualisiert Zähler."""
        profile = RelevanceProfile()

        # 3 positive, 2 negative
        for i in range(3):
            profile.update_from_feedback(f"Good {i}", f"url{i}", True)
        for i in range(2):
            profile.update_from_feedback(f"Bad {i}", f"url{i}", False)

        assert profile.total_scored == 5
        assert profile.total_kept == 3
        assert profile.total_dropped == 2

    def test_examples_limited_to_20(self):
        """Test Beispiele werden auf 20 begrenzt."""
        profile = RelevanceProfile()

        # 25 Beispiele hinzufügen
        for i in range(25):
            profile.update_from_feedback(
                f"Example {i}",
                f"https://example.com/{i}",
                is_relevant=True,
            )

        assert len(profile.positive_examples) == 20
        # Die neuesten sollten behalten werden
        titles = [ex["title"] for ex in profile.positive_examples]
        assert "Example 24" in titles
        assert "Example 0" not in titles  # Ältestes sollte weg sein

    def test_examples_in_prompt_context(self):
        """Test Beispiele erscheinen im Prompt-Kontext."""
        profile = RelevanceProfile()

        profile.update_from_feedback(
            "Relevanter Artikel",
            "https://example.com/good",
            is_relevant=True,
            reason="Wichtig",
        )
        profile.update_from_feedback(
            "Irrelevanter Artikel",
            "https://example.com/bad",
            is_relevant=False,
            reason="Spam",
        )

        context = profile.get_prompt_context()

        assert "Relevanter Artikel" in context
        assert "Irrelevanter Artikel" in context
        assert "relevante Alerts" in context
        assert "irrelevante Alerts" in context


class TestProfileEvolution:
    """Tests für die Evolution des Profils über Zeit."""

    def test_profile_learns_from_feedback_pattern(self):
        """Test Profil lernt aus Feedback-Mustern."""
        profile = RelevanceProfile()

        # Simuliere Feedback-Muster: Inklusions-Artikel sind relevant
        inklusion_articles = [
            ("Neue Inklusions-Verordnung", "https://example.com/1"),
            ("Inklusion in Bayern verstärkt", "https://example.com/2"),
            ("Förderbedarf: Neue Richtlinien", "https://example.com/3"),
        ]

        for title, url in inklusion_articles:
            profile.update_from_feedback(title, url, is_relevant=True, reason="Inklusion")

        # Simuliere irrelevante Artikel
        spam_articles = [
            ("Newsletter Dezember", "https://example.com/spam1"),
            ("Pressemitteilung", "https://example.com/spam2"),
        ]

        for title, url in spam_articles:
            profile.update_from_feedback(title, url, is_relevant=False, reason="Spam")

        # Prompt-Kontext sollte die Muster reflektieren
        context = profile.get_prompt_context()

        # Alle positiven Beispiele sollten Inklusions-bezogen sein
        for title, _ in inklusion_articles:
            assert title in context

        # Negative Beispiele sollten auch vorhanden sein
        for title, _ in spam_articles:
            assert title in context

    def test_profile_statistics_reflect_decisions(self):
        """Test Profil-Statistiken reflektieren Entscheidungen."""
        profile = RelevanceProfile()

        # 70% relevant, 30% irrelevant
        for i in range(70):
            profile.update_from_feedback(f"Good {i}", f"url{i}", True)
        for i in range(30):
            profile.update_from_feedback(f"Bad {i}", f"url{i}", False)

        assert profile.total_scored == 100
        assert profile.total_kept == 70
        assert profile.total_dropped == 30

        # Keep-Rate sollte 70% sein
        keep_rate = profile.total_kept / profile.total_scored
        assert keep_rate == 0.7


class TestFeedbackWithPriorities:
    """Tests für Feedback in Kombination mit Prioritäten."""

    def test_priority_keywords_in_feedback(self):
        """Test Feedback-Beispiele ergänzen Prioritäts-Keywords."""
        profile = RelevanceProfile()
        profile.add_priority(
            "Inklusion",
            weight=0.9,
            keywords=["Förderbedarf", "inklusiv"],
        )

        # Feedback mit zusätzlichem Kontext
        profile.update_from_feedback(
            "Nachteilsausgleich für Schüler mit Förderbedarf",
            "https://example.com/nachteilsausgleich",
            is_relevant=True,
            reason="Nachteilsausgleich ist wichtig für Inklusion",
        )

        # Das Feedback-Beispiel sollte im Kontext erscheinen
        context = profile.get_prompt_context()
        assert "Nachteilsausgleich" in context

    def test_exclusion_patterns_from_feedback(self):
        """Test Ausschlüsse werden durch Feedback-Muster erkannt."""
        profile = RelevanceProfile()

        # Mehrere Stellenanzeigen als irrelevant markieren
        for i in range(5):
            profile.update_from_feedback(
                f"Stellenanzeige: Position {i}",
                f"https://example.com/job{i}",
                is_relevant=False,
                reason="Stellenanzeige",
            )

        # Das Muster sollte in negativen Beispielen sichtbar sein
        assert len(profile.negative_examples) == 5
        assert all("Stellenanzeige" in ex["title"] for ex in profile.negative_examples)


class TestDefaultProfileFeedback:
    """Tests für Feedback mit dem Default-Bildungsprofil."""

    def test_default_profile_with_feedback(self):
        """Test Default-Profil kann Feedback verarbeiten."""
        profile = RelevanceProfile.create_default_education_profile()

        # Starte mit Default-Werten
        initial_examples = len(profile.positive_examples)

        # Füge Feedback hinzu
        profile.update_from_feedback(
            "Datenschutz an Schulen: Neue DSGVO-Richtlinien",
            "https://example.com/dsgvo",
            is_relevant=True,
            reason="DSGVO-relevant",
        )

        assert len(profile.positive_examples) == initial_examples + 1
        assert profile.total_kept == 1

    def test_default_priorities_preserved_after_feedback(self):
        """Test Default-Prioritäten bleiben nach Feedback erhalten."""
        profile = RelevanceProfile.create_default_education_profile()
        original_priorities = len(profile.priorities)

        # Feedback sollte Prioritäten nicht ändern
        profile.update_from_feedback("Test", "https://test.com", True)

        assert len(profile.priorities) == original_priorities


class TestFeedbackTimestamps:
    """Tests für Feedback-Zeitstempel."""

    def test_feedback_has_timestamp(self):
        """Test Feedback-Beispiele haben Zeitstempel."""
        profile = RelevanceProfile()

        profile.update_from_feedback(
            "Test Article",
            "https://example.com",
            is_relevant=True,
        )

        example = profile.positive_examples[0]
        assert "added_at" in example
        # Sollte ein ISO-Format Datum sein
        datetime.fromisoformat(example["added_at"])

    def test_profile_updated_at_changes(self):
        """Test updated_at ändert sich nach Feedback."""
        profile = RelevanceProfile()
        original_updated = profile.updated_at

        # Kurz warten und Feedback geben
        import time
        time.sleep(0.01)

        profile.update_from_feedback("Test", "https://test.com", True)

        assert profile.updated_at > original_updated
