"""
Antizipation Engine - Rule definitions and RuleEngine.

Each rule evaluates signals and optionally produces a Suggestion.
"""

import logging
from dataclasses import dataclass
from typing import List, Optional

from .antizipation_models import Signals, Suggestion, SuggestionTone

logger = logging.getLogger(__name__)


# ==================== Rule Base Class ====================

@dataclass
class Rule:
    """Eine Regel die Signale zu Vorschlaegen mappt."""
    id: str
    name: str
    description: str

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        """Evaluiert die Regel und gibt einen Vorschlag zurueck oder None."""
        raise NotImplementedError()


# ==================== Rule Implementations ====================

class R01_CreateClasses(Rule):
    """Klassen anlegen wenn noch keine vorhanden."""

    def __init__(self):
        super().__init__(
            id="R01",
            name="Klassen anlegen",
            description="Empfiehlt Klassen anzulegen bei neuem Lehrer"
        )

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        if signals.macro_phase == "onboarding" and not signals.has_classes:
            return Suggestion(
                id="suggest_create_classes",
                title="Klassen anlegen",
                description="Legen Sie Ihre Klassen an, um den vollen Funktionsumfang zu nutzen.",
                tone=SuggestionTone.HINT,
                priority=90,
                rule_id=self.id,
                icon="group_add",
                action_url="/classes/new",
            )
        return None


class R02_PrepareRubric(Rule):
    """Erwartungshorizont erstellen wenn Klausur in 7 Tagen."""

    def __init__(self):
        super().__init__(
            id="R02",
            name="Erwartungshorizont",
            description="Empfiehlt Erwartungshorizont vor Klausur"
        )

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        if signals.exams_in_7_days:
            exam = signals.exams_in_7_days[0]
            # Pruefen ob Vorbereitung noch nicht erledigt
            if not exam.get("preparation_done", False):
                days = 7  # Vereinfacht
                return Suggestion(
                    id=f"suggest_rubric_{exam['id'][:8]}",
                    title="Erwartungshorizont erstellen",
                    description=f"Klausur '{exam['title']}' steht bevor.",
                    tone=SuggestionTone.SUGGESTION,
                    badge=f"in {days} Tagen",
                    priority=80,
                    rule_id=self.id,
                    icon="assignment",
                    action_url=f"/exams/{exam['id']}/rubric",
                )
        return None


class R03_StartCorrection(Rule):
    """Korrektur starten nach Klausur."""

    def __init__(self):
        super().__init__(
            id="R03",
            name="Korrektur starten",
            description="Empfiehlt Korrektur nach Klausur"
        )

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        if signals.exams_past_ungraded:
            exam = signals.exams_past_ungraded[0]
            return Suggestion(
                id=f"suggest_correction_{exam['id'][:8]}",
                title="Korrektur-Setup starten",
                description=f"Klausur '{exam['title']}' ist geschrieben.",
                tone=SuggestionTone.HINT,
                badge="bereit",
                priority=75,
                rule_id=self.id,
                icon="rate_review",
                action_url=f"/exams/{exam['id']}/correct",
            )
        return None


class R05_PrepareAgenda(Rule):
    """Agenda vorbereiten wenn Konferenz heute."""

    def __init__(self):
        super().__init__(
            id="R05",
            name="Konferenz-Agenda",
            description="Empfiehlt Agenda wenn Konferenz heute"
        )

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        if signals.has_conference_today:
            # Finde die Konferenz
            conf = next(
                (r for r in signals.routines_today
                 if r.get("routine_type") in ("teacher_conference", "subject_conference")),
                None
            )
            if conf:
                return Suggestion(
                    id="suggest_agenda",
                    title="Konferenz-Agenda vorbereiten",
                    description=f"{conf.get('title', 'Konferenz')} heute.",
                    tone=SuggestionTone.SUGGESTION,
                    badge="heute",
                    priority=70,
                    rule_id=self.id,
                    icon="event_note",
                )
        return None


class R07_PlanFirstExam(Rule):
    """Erste Klausur planen nach 4 Wochen."""

    def __init__(self):
        super().__init__(
            id="R07",
            name="Erste Arbeit planen",
            description="Empfiehlt erste Klausur nach Anlaufphase"
        )

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        if (signals.weeks_since_start >= 4 and
            signals.exams_scheduled_count == 0 and
            signals.has_classes):
            return Suggestion(
                id="suggest_first_exam",
                title="Erste Klassenarbeit planen",
                description="Nach 4 Wochen Unterricht ist ein guter Zeitpunkt fuer die erste Leistungsueberpruefung.",
                tone=SuggestionTone.SUGGESTION,
                priority=60,
                rule_id=self.id,
                icon="quiz",
                action_url="/exams/new",
            )
        return None


class R08_CorrectionMode(Rule):
    """Korrekturmodus vor Ferien."""

    def __init__(self):
        super().__init__(
            id="R08",
            name="Ferien-Korrekturmodus",
            description="Empfiehlt Korrekturen vor Ferien"
        )

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        if signals.is_before_holidays and signals.corrections_pending > 0:
            return Suggestion(
                id="suggest_correction_mode",
                title="Ferien-Korrekturmodus",
                description=f"{signals.corrections_pending} Korrekturen noch offen vor den Ferien.",
                tone=SuggestionTone.REMINDER,
                badge=f"{signals.days_until_holidays}d bis Ferien",
                priority=65,
                rule_id=self.id,
                icon="grading",
            )
        return None


class R09_TripChecklist(Rule):
    """Klassenfahrt-Checkliste wenn Fahrt in 30 Tagen."""

    def __init__(self):
        super().__init__(
            id="R09",
            name="Klassenfahrt-Checkliste",
            description="Empfiehlt Checkliste vor Klassenfahrt"
        )

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        if signals.trips_in_30_days:
            trip = signals.trips_in_30_days[0]
            return Suggestion(
                id=f"suggest_trip_{trip['id'][:8]}",
                title="Klassenfahrt-Checkliste",
                description=f"'{trip['title']}' steht bevor.",
                tone=SuggestionTone.SUGGESTION,
                badge="in 30 Tagen",
                priority=55,
                rule_id=self.id,
                icon="luggage",
                action_url=f"/trips/{trip['id']}/checklist",
            )
        return None


class R10_CompleteGrades(Rule):
    """Noten vervollstaendigen vor Halbjahresende."""

    def __init__(self):
        super().__init__(
            id="R10",
            name="Noten vervollstaendigen",
            description="Empfiehlt Noten vor Notenschluss"
        )

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        if (signals.macro_phase in ("halbjahresabschluss", "jahresabschluss") and
            signals.grades_completion_ratio < 0.8):
            pct = int(signals.grades_completion_ratio * 100)
            return Suggestion(
                id="suggest_complete_grades",
                title="Noten vervollstaendigen",
                description=f"Nur {pct}% der Noten eingetragen. Notenschluss naht!",
                tone=SuggestionTone.REMINDER,
                priority=85,
                rule_id=self.id,
                icon="calculate",
                action_url="/grades",
            )
        return None


class R11_SetupSchedule(Rule):
    """Stundenplan einrichten wenn noch nicht vorhanden."""

    def __init__(self):
        super().__init__(
            id="R11",
            name="Stundenplan einrichten",
            description="Empfiehlt Stundenplan-Setup"
        )

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        if signals.macro_phase == "onboarding" and not signals.has_schedule:
            return Suggestion(
                id="suggest_setup_schedule",
                title="Stundenplan einrichten",
                description="Richten Sie Ihren Stundenplan ein fuer personalisierte Vorschlaege.",
                tone=SuggestionTone.HINT,
                priority=85,
                rule_id=self.id,
                icon="calendar_month",
                action_url="/schedule/setup",
            )
        return None


class R12_ParentEvening(Rule):
    """Elternabend vorbereiten."""

    def __init__(self):
        super().__init__(
            id="R12",
            name="Elternabend vorbereiten",
            description="Empfiehlt Vorbereitung vor Elternabend"
        )

    def evaluate(self, signals: Signals) -> Optional[Suggestion]:
        if signals.parent_evenings_soon:
            event = signals.parent_evenings_soon[0]
            return Suggestion(
                id=f"suggest_parent_{event['id'][:8]}",
                title="Elternabend vorbereiten",
                description=f"'{event['title']}' steht bevor.",
                tone=SuggestionTone.SUGGESTION,
                badge="bald",
                priority=65,
                rule_id=self.id,
                icon="family_restroom",
                action_url=f"/events/{event['id']}/prepare",
            )
        return None


# ==================== Rule Engine ====================

class RuleEngine:
    """
    Evaluiert alle Regeln gegen die gesammelten Signale.
    """

    def __init__(self):
        self.rules: List[Rule] = [
            R01_CreateClasses(),
            R02_PrepareRubric(),
            R03_StartCorrection(),
            R05_PrepareAgenda(),
            R07_PlanFirstExam(),
            R08_CorrectionMode(),
            R09_TripChecklist(),
            R10_CompleteGrades(),
            R11_SetupSchedule(),
            R12_ParentEvening(),
        ]

    def evaluate(self, signals: Signals) -> List[Suggestion]:
        """Evaluiert alle Regeln und gibt passende Vorschlaege zurueck."""
        suggestions = []

        for rule in self.rules:
            try:
                suggestion = rule.evaluate(signals)
                if suggestion:
                    suggestions.append(suggestion)
            except Exception as e:
                logger.warning(f"Rule {rule.id} failed: {e}")

        # Nach Prioritaet sortieren (hoechste zuerst)
        suggestions.sort(key=lambda s: s.priority, reverse=True)

        return suggestions
