"""
State Engine Rules - Antizipations-Regeln für proaktive Vorschläge.

Definiert:
- Suggestion: Ein Vorschlag mit Priorität und Aktion
- Rule: Eine Regel die auf TeacherContext angewendet wird
- RULES: Vordefinierte Regeln (15+)
"""

from dataclasses import dataclass
from enum import Enum
from typing import Callable, List, Optional, TYPE_CHECKING

if TYPE_CHECKING:
    from .models import TeacherContext


class SuggestionPriority(Enum):
    """Priorität eines Vorschlags."""
    URGENT = 1      # Sofort erforderlich
    HIGH = 2        # Heute/Diese Woche
    MEDIUM = 3      # Diese Woche/Bald
    LOW = 4         # Irgendwann


@dataclass
class Suggestion:
    """Ein Vorschlag für den Lehrer."""
    id: str
    title: str
    description: str
    action_type: str          # "navigate", "create", "remind"
    action_target: str        # URL oder Action-ID
    priority: SuggestionPriority
    category: str             # "classes", "grades", "communication", etc.
    icon: str                 # Material Icon Name
    estimated_time: int       # Minuten

    def to_dict(self):
        return {
            "id": self.id,
            "title": self.title,
            "description": self.description,
            "action_type": self.action_type,
            "action_target": self.action_target,
            "priority": self.priority.name,
            "priority_value": self.priority.value,
            "category": self.category,
            "icon": self.icon,
            "estimated_time": self.estimated_time,
        }


@dataclass
class Rule:
    """Eine Antizipations-Regel."""
    id: str
    name: str
    condition: Callable[['TeacherContext'], bool]
    suggestion_generator: Callable[['TeacherContext'], Suggestion]
    applies_to_phases: List[str]  # Leere Liste = alle Phasen

    def evaluate(self, ctx: 'TeacherContext') -> Optional[Suggestion]:
        """
        Evaluiert die Regel gegen den Kontext.

        Returns:
            Suggestion wenn Regel zutrifft, sonst None
        """
        # Prüfe Phasen-Einschränkung
        if self.applies_to_phases:
            if ctx.current_phase.value not in self.applies_to_phases:
                return None

        # Prüfe Condition
        try:
            if not self.condition(ctx):
                return None
        except Exception:
            return None

        return self.suggestion_generator(ctx)


# ============================================================================
# Helper Functions für Regeln
# ============================================================================

def _get_parent_meeting_days(ctx: 'TeacherContext') -> int:
    """Gibt Tage bis zum nächsten Elternabend zurück."""
    for e in ctx.upcoming_events:
        if e.type == "parent_meeting":
            return e.in_days
    return 999


def _get_next_exam_days(ctx: 'TeacherContext') -> int:
    """Gibt Tage bis zur nächsten Klausur zurück."""
    for e in ctx.upcoming_events:
        if e.type == "exam" and e.in_days > 0:
            return e.in_days
    return 999


def _get_uncorrected_exams(ctx: 'TeacherContext') -> int:
    """Gibt Anzahl unkorrigierter Klausuren zurück."""
    return ctx.stats.exams_scheduled - ctx.stats.exams_graded


# ============================================================================
# Vordefinierte Regeln (15+)
# ============================================================================

RULES: List[Rule] = [
    # ═══════════════════════════════════════════════════════════════════════
    # ONBOARDING / SCHULJAHRESSTART
    # ═══════════════════════════════════════════════════════════════════════

    Rule(
        id="no_classes",
        name="Keine Klassen angelegt",
        condition=lambda ctx: len(ctx.classes) == 0,
        suggestion_generator=lambda ctx: Suggestion(
            id="create_first_class",
            title="Erste Klasse anlegen",
            description="Lege deine erste Klasse an, um loszulegen.",
            action_type="navigate",
            action_target="/studio/school",
            priority=SuggestionPriority.URGENT,
            category="classes",
            icon="group_add",
            estimated_time=5,
        ),
        applies_to_phases=["onboarding", "school_year_start"],
    ),

    Rule(
        id="no_students",
        name="Klassen ohne Schüler",
        condition=lambda ctx: len(ctx.classes) > 0 and ctx.total_students == 0,
        suggestion_generator=lambda ctx: Suggestion(
            id="add_students",
            title="Schüler hinzufügen",
            description=f"Deine {len(ctx.classes)} Klasse(n) haben noch keine Schüler.",
            action_type="navigate",
            action_target="/studio/school",
            priority=SuggestionPriority.HIGH,
            category="classes",
            icon="person_add",
            estimated_time=10,
        ),
        applies_to_phases=["school_year_start"],
    ),

    Rule(
        id="consent_missing",
        name="Einwilligung ausstehend",
        condition=lambda ctx: not ctx.has_completed_milestone("consent_accept"),
        suggestion_generator=lambda ctx: Suggestion(
            id="accept_consent",
            title="Datenschutz-Einwilligung",
            description="Bitte akzeptiere die Datenschutzbestimmungen.",
            action_type="navigate",
            action_target="/studio/consent",
            priority=SuggestionPriority.URGENT,
            category="settings",
            icon="security",
            estimated_time=2,
        ),
        applies_to_phases=["onboarding"],
    ),

    Rule(
        id="profile_incomplete",
        name="Profil unvollständig",
        condition=lambda ctx: not ctx.has_completed_milestone("profile_complete"),
        suggestion_generator=lambda ctx: Suggestion(
            id="complete_profile",
            title="Profil vervollständigen",
            description="Vervollständige dein Profil für bessere Personalisierung.",
            action_type="navigate",
            action_target="/studio/profile",
            priority=SuggestionPriority.HIGH,
            category="settings",
            icon="account_circle",
            estimated_time=5,
        ),
        applies_to_phases=["onboarding", "school_year_start"],
    ),

    # ═══════════════════════════════════════════════════════════════════════
    # UNTERRICHT
    # ═══════════════════════════════════════════════════════════════════════

    Rule(
        id="no_learning_units",
        name="Keine Lerneinheiten",
        condition=lambda ctx: (
            ctx.current_phase.value in ["teaching_setup", "teaching_2"] and
            ctx.stats.learning_units_created == 0
        ),
        suggestion_generator=lambda ctx: Suggestion(
            id="create_learning_unit",
            title="Erste Lerneinheit erstellen",
            description="Erstelle Lerneinheiten für deine Klassen.",
            action_type="navigate",
            action_target="/studio/worksheets",
            priority=SuggestionPriority.HIGH,
            category="teaching",
            icon="auto_stories",
            estimated_time=15,
        ),
        applies_to_phases=["teaching_setup", "teaching_2"],
    ),

    Rule(
        id="few_learning_units",
        name="Wenige Lerneinheiten",
        condition=lambda ctx: (
            ctx.current_phase.value in ["teaching_setup", "teaching_2"] and
            0 < ctx.stats.learning_units_created < 3
        ),
        suggestion_generator=lambda ctx: Suggestion(
            id="create_more_units",
            title="Weitere Lerneinheiten erstellen",
            description=f"Du hast {ctx.stats.learning_units_created} Lerneinheit(en). Erstelle mehr für abwechslungsreichen Unterricht.",
            action_type="navigate",
            action_target="/studio/worksheets",
            priority=SuggestionPriority.MEDIUM,
            category="teaching",
            icon="library_add",
            estimated_time=15,
        ),
        applies_to_phases=["teaching_setup", "teaching_2"],
    ),

    # ═══════════════════════════════════════════════════════════════════════
    # ELTERNKOMMUNIKATION
    # ═══════════════════════════════════════════════════════════════════════

    Rule(
        id="parent_meeting_upcoming",
        name="Elternabend steht bevor",
        condition=lambda ctx: any(
            e.type == "parent_meeting" and e.in_days <= 14
            for e in ctx.upcoming_events
        ),
        suggestion_generator=lambda ctx: Suggestion(
            id="prepare_parent_meeting",
            title="Elternabend vorbereiten",
            description=f"In {_get_parent_meeting_days(ctx)} Tagen ist Elternabend.",
            action_type="navigate",
            action_target="/studio/letters",
            priority=SuggestionPriority.HIGH,
            category="communication",
            icon="groups",
            estimated_time=30,
        ),
        applies_to_phases=[],  # Alle Phasen
    ),

    Rule(
        id="unanswered_parent_messages",
        name="Unbeantwortete Elternnachrichten",
        condition=lambda ctx: ctx.stats.unanswered_messages > 0,
        suggestion_generator=lambda ctx: Suggestion(
            id="answer_messages",
            title="Elternnachrichten beantworten",
            description=f"{ctx.stats.unanswered_messages} Nachricht(en) warten auf Antwort.",
            action_type="navigate",
            action_target="/studio/messenger",
            priority=SuggestionPriority.HIGH if ctx.stats.unanswered_messages > 3 else SuggestionPriority.MEDIUM,
            category="communication",
            icon="mail",
            estimated_time=15,
        ),
        applies_to_phases=[],  # Alle Phasen
    ),

    Rule(
        id="no_parent_contact",
        name="Keine Elternkontakte",
        condition=lambda ctx: (
            ctx.total_students > 0 and
            ctx.stats.parent_messages_count == 0 and
            ctx.weeks_since_start >= 4
        ),
        suggestion_generator=lambda ctx: Suggestion(
            id="start_parent_communication",
            title="Elternkommunikation starten",
            description="Nimm Kontakt mit den Eltern auf.",
            action_type="navigate",
            action_target="/studio/letters",
            priority=SuggestionPriority.MEDIUM,
            category="communication",
            icon="family_restroom",
            estimated_time=20,
        ),
        applies_to_phases=["teaching_setup", "teaching_2"],
    ),

    # ═══════════════════════════════════════════════════════════════════════
    # LEISTUNG / KLAUSUREN
    # ═══════════════════════════════════════════════════════════════════════

    Rule(
        id="exam_in_7_days",
        name="Klausur in 7 Tagen",
        condition=lambda ctx: any(
            e.type == "exam" and 0 < e.in_days <= 7
            for e in ctx.upcoming_events
        ),
        suggestion_generator=lambda ctx: Suggestion(
            id="prepare_exam",
            title="Klausur vorbereiten",
            description=f"Klausur in {_get_next_exam_days(ctx)} Tagen.",
            action_type="navigate",
            action_target="/studio/worksheets",
            priority=SuggestionPriority.URGENT,
            category="exams",
            icon="quiz",
            estimated_time=60,
        ),
        applies_to_phases=["performance_1", "performance_2"],
    ),

    Rule(
        id="exam_needs_correction",
        name="Klausur wartet auf Korrektur",
        condition=lambda ctx: _get_uncorrected_exams(ctx) > 0,
        suggestion_generator=lambda ctx: Suggestion(
            id="correct_exam",
            title="Klausur korrigieren",
            description=f"{_get_uncorrected_exams(ctx)} Klausur(en) warten auf Korrektur.",
            action_type="navigate",
            action_target="/studio/correction",
            priority=SuggestionPriority.URGENT,
            category="exams",
            icon="grading",
            estimated_time=120,
        ),
        applies_to_phases=["performance_1", "performance_2"],
    ),

    Rule(
        id="no_exams_scheduled",
        name="Keine Klausuren geplant",
        condition=lambda ctx: (
            ctx.current_phase.value in ["performance_1", "performance_2"] and
            ctx.stats.exams_scheduled == 0
        ),
        suggestion_generator=lambda ctx: Suggestion(
            id="schedule_exams",
            title="Klausuren planen",
            description="Plane die Klausuren für diese Leistungsphase.",
            action_type="navigate",
            action_target="/studio/school",
            priority=SuggestionPriority.HIGH,
            category="exams",
            icon="event",
            estimated_time=15,
        ),
        applies_to_phases=["performance_1", "performance_2"],
    ),

    # ═══════════════════════════════════════════════════════════════════════
    # NOTEN / ZEUGNISSE
    # ═══════════════════════════════════════════════════════════════════════

    Rule(
        id="grades_missing",
        name="Noten fehlen",
        condition=lambda ctx: (
            ctx.current_phase.value in ["semester_end", "year_end"] and
            not ctx.has_completed_milestone("complete_grades")
        ),
        suggestion_generator=lambda ctx: Suggestion(
            id="enter_grades",
            title="Noten eintragen",
            description="Trage alle Noten für die Zeugnisse ein.",
            action_type="navigate",
            action_target="/studio/gradebook",
            priority=SuggestionPriority.URGENT,
            category="grades",
            icon="calculate",
            estimated_time=30,
        ),
        applies_to_phases=["semester_end", "year_end"],
    ),

    Rule(
        id="certificates_due",
        name="Zeugnisse erstellen",
        condition=lambda ctx: (
            ctx.current_phase.value in ["semester_end", "year_end"] and
            ctx.has_completed_milestone("complete_grades") and
            not ctx.has_completed_milestone("generate_certificates")
        ),
        suggestion_generator=lambda ctx: Suggestion(
            id="generate_certificates",
            title="Zeugnisse erstellen",
            description="Alle Noten sind eingetragen. Erstelle jetzt die Zeugnisse.",
            action_type="navigate",
            action_target="/studio/certificates",
            priority=SuggestionPriority.HIGH,
            category="certificates",
            icon="description",
            estimated_time=45,
        ),
        applies_to_phases=["semester_end", "year_end"],
    ),

    Rule(
        id="gradebook_empty",
        name="Notenbuch leer",
        condition=lambda ctx: (
            ctx.stats.grades_entered == 0 and
            ctx.weeks_since_start >= 6
        ),
        suggestion_generator=lambda ctx: Suggestion(
            id="start_gradebook",
            title="Notenbuch nutzen",
            description="Beginne mit der Notenverwaltung im Notenbuch.",
            action_type="navigate",
            action_target="/studio/gradebook",
            priority=SuggestionPriority.MEDIUM,
            category="grades",
            icon="grade",
            estimated_time=10,
        ),
        applies_to_phases=["teaching_setup", "performance_1", "teaching_2", "performance_2"],
    ),

    # ═══════════════════════════════════════════════════════════════════════
    # ALLGEMEINE ERINNERUNGEN
    # ═══════════════════════════════════════════════════════════════════════

    Rule(
        id="long_time_inactive",
        name="Lange inaktiv",
        condition=lambda ctx: ctx.days_in_phase > 14 and len(ctx.completed_milestones) == 0,
        suggestion_generator=lambda ctx: Suggestion(
            id="get_started",
            title="Loslegen",
            description="Du bist schon eine Weile in dieser Phase. Lass uns starten!",
            action_type="navigate",
            action_target="/studio",
            priority=SuggestionPriority.HIGH,
            category="general",
            icon="rocket_launch",
            estimated_time=5,
        ),
        applies_to_phases=[],  # Alle Phasen
    ),

    Rule(
        id="deadline_approaching",
        name="Deadline naht",
        condition=lambda ctx: any(
            e.type == "deadline" and 0 < e.in_days <= 3
            for e in ctx.upcoming_events
        ),
        suggestion_generator=lambda ctx: Suggestion(
            id="check_deadline",
            title="Deadline beachten",
            description=f"Eine Deadline in {ctx.get_next_deadline().in_days if ctx.get_next_deadline() else 0} Tagen.",
            action_type="navigate",
            action_target="/studio",
            priority=SuggestionPriority.URGENT,
            category="general",
            icon="alarm",
            estimated_time=5,
        ),
        applies_to_phases=[],
    ),
]


def get_rules_for_phase(phase: str) -> List[Rule]:
    """Gibt alle Regeln für eine bestimmte Phase zurück."""
    return [
        rule for rule in RULES
        if not rule.applies_to_phases or phase in rule.applies_to_phases
    ]
