import uuid

from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.utils import timezone

from .land import DokumentLink


class Destinataer(models.Model):
    """Destinatäre (Beneficiaries) für Förderungen"""

    FAMILIENZWIG_CHOICES = [
        ("hauptzweig", "Hauptzweig"),
        ("nebenzweig", "Nebenzweig"),
        ("verwandt", "Verwandt"),
        ("anderer", "Anderer"),
    ]

    BERUFSGRUPPE_CHOICES = [
        ("student", "Student/Studentin"),
        ("wissenschaftler", "Wissenschaftler/in"),
        ("künstler", "Künstler/in"),
        ("sozialarbeiter", "Sozialarbeiter/in"),
        ("umweltschützer", "Umweltschützer/in"),
        ("andere", "Andere"),
    ]

    ANREDE_CHOICES = [
        ("Herr", "Herr"),
        ("Frau", "Frau"),
        ("Divers", "Divers"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    anrede = models.CharField(
        max_length=20,
        choices=ANREDE_CHOICES,
        blank=True,
        null=True,
        verbose_name="Anrede",
    )
    familienzweig = models.CharField(
        max_length=100, choices=FAMILIENZWIG_CHOICES, blank=True, null=True
    )
    vorname = models.CharField(max_length=100, verbose_name="Vorname")
    nachname = models.CharField(max_length=100, verbose_name="Nachname")
    geburtsdatum = models.DateField(null=True, blank=True, verbose_name="Geburtsdatum")
    email = models.EmailField(null=True, blank=True, verbose_name="E-Mail")
    telefon = models.CharField(
        max_length=20, null=True, blank=True, verbose_name="Telefon"
    )
    iban = models.CharField(max_length=34, null=True, blank=True, verbose_name="IBAN")

    # Adressfelder
    strasse = models.CharField(
        max_length=200, verbose_name="Straße", blank=True, null=True
    )
    plz = models.CharField(max_length=10, verbose_name="PLZ", blank=True, null=True)
    ort = models.CharField(max_length=100, verbose_name="Ort", blank=True, null=True)

    # Förderungs-spezifische Felder
    berufsgruppe = models.CharField(
        max_length=20,
        choices=BERUFSGRUPPE_CHOICES,
        blank=True,
        null=True,
        verbose_name="Berufsgruppe",
    )
    ausbildungsstand = models.CharField(
        max_length=100, null=True, blank=True, verbose_name="Ausbildungsstand"
    )
    institution = models.CharField(
        max_length=200, null=True, blank=True, verbose_name="Institution/Organisation"
    )
    projekt_beschreibung = models.TextField(
        null=True, blank=True, verbose_name="Projektbeschreibung"
    )

    # Finanzielle Informationen
    jaehrliches_einkommen = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        null=True,
        blank=True,
        verbose_name="Jährliches Einkommen (€)",
    )
    finanzielle_notlage = models.BooleanField(
        default=False, verbose_name="Finanzielle Notlage"
    )

    # Kontakt und Notizen
    notizen = models.TextField(null=True, blank=True, verbose_name="Notizen")
    aktiv = models.BooleanField(default=True, verbose_name="Aktiv")

    # Unterstützung – Prüf- und Verwaltungsfelder
    ist_abkoemmling = models.BooleanField(
        default=False, verbose_name="Abkömmling gem. Satzung"
    )
    haushaltsgroesse = models.PositiveIntegerField(
        default=1, verbose_name="Haushaltsgröße"
    )
    monatliche_bezuege = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        null=True,
        blank=True,
        verbose_name="Monatliche Bezüge (€)",
    )
    vermoegen = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        null=True,
        blank=True,
        verbose_name="Vermögen (€)",
    )
    unterstuetzung_bestaetigt = models.BooleanField(
        default=False, verbose_name="Unterstützung bestätigt"
    )
    standard_konto = models.ForeignKey(
        "StiftungsKonto",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name="Standard Auszahlungskonto",
    )
    vierteljaehrlicher_betrag = models.DecimalField(
        max_digits=12,
        decimal_places=2,
        null=True,
        blank=True,
        verbose_name="Vierteljährlicher Betrag (€)",
    )

    # Studiennachweise
    studiennachweis_erforderlich = models.BooleanField(
        default=False, verbose_name="Studiennachweis erforderlich"
    )
    letzter_studiennachweis = models.DateField(
        null=True, blank=True, verbose_name="Letzter Studiennachweis"
    )

    class Meta:
        verbose_name = "Destinatär"
        verbose_name_plural = "Destinatäre"
        ordering = ["nachname", "vorname"]

    def __str__(self):
        if self.vorname:
            return f"{self.nachname}, {self.vorname}"
        else:
            return self.nachname

    def get_full_name(self):
        if self.vorname:
            return f"{self.vorname} {self.nachname}"
        else:
            return self.nachname

    def get_total_foerderungen(self):
        """Calculate total funding received"""
        return self.foerderung_set.aggregate(total=models.Sum("betrag"))["total"] or 0

    def get_foerderungen_count(self):
        """Count total funding grants"""
        return self.foerderung_set.count()

    def get_letzte_foerderung(self):
        """Get the most recent funding grant"""
        return self.foerderung_set.order_by("-jahr", "-betrag").first()

    @property
    def adresse(self):
        """Construct full address from separate fields"""
        parts = []
        if self.strasse:
            parts.append(self.strasse)
        if self.plz or self.ort:
            city_part = []
            if self.plz:
                city_part.append(self.plz)
            if self.ort:
                city_part.append(self.ort)
            parts.append(" ".join(city_part))
        return "\n".join(parts) if parts else ""

    def erfuellt_voraussetzungen(self):
        """Prüft die Unterstützungsvoraussetzungen gemäß Angaben.
        - Abkömmling muss True sein
        - Monatliche Bezüge ≤ zulässige Grenze
        - Vermögen ≤ 15.500 €
        Die zulässige Grenze wird aus dem Regelsatz (standard 563 €) * 5 für die erste Person
        und + 0.8 * Regelsatz je weiterer Person approximiert.
        """
        from decimal import Decimal

        regelsatz = Decimal("563.00")
        basis = regelsatz * 5
        zuschlag = max(0, (self.haushaltsgroesse or 1) - 1) * (
            regelsatz * Decimal("0.80")
        )
        grenze = basis + zuschlag
        einkommen_ok = (self.monatliche_bezuege or Decimal("0")) <= grenze
        vermoegen_ok = (self.vermoegen or Decimal("0")) <= Decimal("15500")
        return bool(self.ist_abkoemmling and einkommen_ok and vermoegen_ok)

    @property
    def adresse(self):
        """Computed address property combining strasse, plz, ort"""
        parts = []
        if self.strasse:
            parts.append(self.strasse)
        if self.plz and self.ort:
            parts.append(f"{self.plz} {self.ort}")
        elif self.plz:
            parts.append(self.plz)
        elif self.ort:
            parts.append(self.ort)
        return "\n".join(parts) if parts else None

    def naechste_studiennachweis_termine(self):
        """Gibt die nächsten beiden Stichtage (15.03, 15.09) zurück."""
        import datetime as _dt

        today = _dt.date.today()
        jahr = today.year
        maerz = _dt.date(jahr, 3, 15)
        sep = _dt.date(jahr, 9, 15)
        termine = []
        for d in (maerz, sep):
            if d >= today:
                termine.append(d)
        if len(termine) < 2:
            # Ergänzen aus folgendem Jahr
            termine.append(_dt.date(jahr + 1, 3, 15))
            if len(termine) < 2:
                termine.append(_dt.date(jahr + 1, 9, 15))
        return termine[:2]


# Keep the old Person model for backward compatibility (will be removed in future)
class Person(models.Model):
    FAMILIENZWIG_CHOICES = [
        ("hauptzweig", "Hauptzweig"),
        ("nebenzweig", "Nebenzweig"),
        ("verwandt", "Verwandt"),
        ("anderer", "Anderer"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    familienzweig = models.CharField(
        max_length=100, choices=FAMILIENZWIG_CHOICES, default="hauptzweig"
    )
    vorname = models.CharField(max_length=100)
    nachname = models.CharField(max_length=100)
    geburtsdatum = models.DateField(null=True, blank=True)
    email = models.EmailField(null=True, blank=True)
    telefon = models.CharField(max_length=20, null=True, blank=True)
    iban = models.CharField(max_length=34, null=True, blank=True)
    adresse = models.TextField(null=True, blank=True)
    notizen = models.TextField(null=True, blank=True)
    aktiv = models.BooleanField(default=True)

    class Meta:
        verbose_name = "Person (Legacy)"
        verbose_name_plural = "Personen (Legacy)"
        ordering = ["nachname", "vorname"]

    def __str__(self):
        return f"{self.nachname}, {self.vorname} (Legacy)"

    def get_full_name(self):
        return f"{self.vorname} {self.nachname}"

    def get_total_foerderungen(self):
        return self.foerderung_set.aggregate(total=models.Sum("betrag"))["total"] or 0


class Foerderung(models.Model):
    KATEGORIE_CHOICES = [
        ("bildung", "Bildung"),
        ("forschung", "Forschung"),
        ("kultur", "Kultur"),
        ("soziales", "Soziales"),
        ("umwelt", "Umwelt"),
        ("anderes", "Anderes"),
    ]

    STATUS_CHOICES = [
        ("beantragt", "Beantragt"),
        ("genehmigt", "Genehmigt"),
        ("ausgezahlt", "Ausgezahlt"),
        ("abgelehnt", "Abgelehnt"),
        ("storniert", "Storniert"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    # Legacy field for migration - will be removed after data migration
    person = models.ForeignKey(
        Person,
        on_delete=models.CASCADE,
        verbose_name="Person (Legacy)",
        null=True,
        blank=True,
    )
    destinataer = models.ForeignKey(
        Destinataer,
        on_delete=models.CASCADE,
        verbose_name="Destinatär",
        null=True,
        blank=True,
    )
    jahr = models.IntegerField(
        validators=[MinValueValidator(1900), MaxValueValidator(2100)]
    )
    betrag = models.DecimalField(max_digits=12, decimal_places=2)
    kategorie = models.CharField(
        max_length=20, choices=KATEGORIE_CHOICES, default="anderes"
    )
    status = models.CharField(
        max_length=20, choices=STATUS_CHOICES, default="beantragt"
    )
    verwendungsnachweis = models.ForeignKey(
        DokumentLink,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name="Verwendungsnachweis",
    )
    bemerkungen = models.TextField(null=True, blank=True)
    antragsdatum = models.DateField(default=timezone.now)
    entscheidungsdatum = models.DateField(null=True, blank=True)

    class Meta:
        verbose_name = "Förderung"
        verbose_name_plural = "Förderungen"
        ordering = ["-jahr", "-betrag"]
        # Note: unique_together will be updated after migration

    def __str__(self):
        if self.destinataer:
            return f"{self.destinataer} - {self.jahr} - €{self.betrag}"
        elif self.person:
            return f"{self.person} (Legacy) - {self.jahr} - €{self.betrag}"
        return f"Unbekannt - {self.jahr} - €{self.betrag}"

    def get_status_color(self):
        colors = {
            "beantragt": "orange",
            "genehmigt": "blue",
            "ausgezahlt": "green",
            "abgelehnt": "red",
            "storniert": "gray",
        }
        return colors.get(self.status, "black")


class DestinataerUnterstuetzung(models.Model):
    """Geplante/ausgeführte Unterstützungszahlungen an Destinatäre"""

    STATUS_CHOICES = [
        ("geplant", "Offen"),
        ("faellig", "Fällig"),
        ("nachweis_eingereicht", "Nachweis eingereicht"),
        ("freigegeben", "Freigegeben (4-Augen)"),
        ("in_bearbeitung", "In Bearbeitung"),
        ("ausgezahlt", "Überwiesen"),
        ("abgeschlossen", "Abgeschlossen"),
        ("storniert", "Storniert"),
    ]

    # Pipeline-stage für Zahlungsstatus-Anzeige
    PIPELINE_STAGES = [
        ("geplant", "Offen"),
        ("nachweis_eingereicht", "Nachweis eingereicht"),
        ("freigegeben", "Freigegeben"),
        ("ausgezahlt", "Überwiesen"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    destinataer = models.ForeignKey(
        "Destinataer",
        on_delete=models.CASCADE,
        related_name="unterstuetzungen",
        verbose_name="Destinatär",
    )
    konto = models.ForeignKey(
        "StiftungsKonto", on_delete=models.PROTECT, verbose_name="Zahlungskonto"
    )
    betrag = models.DecimalField(
        max_digits=12, decimal_places=2, verbose_name="Betrag (€)"
    )
    faellig_am = models.DateField(verbose_name="Fällig am")
    status = models.CharField(
        max_length=20, choices=STATUS_CHOICES, default="geplant", verbose_name="Status"
    )
    beschreibung = models.CharField(
        max_length=255, blank=True, verbose_name="Beschreibung"
    )

    # Enhanced fields for recurrent payments and IBAN tracking
    empfaenger_iban = models.CharField(
        max_length=34, blank=True, verbose_name="Empfänger IBAN"
    )
    empfaenger_name = models.CharField(
        max_length=200, blank=True, verbose_name="Empfänger Name"
    )
    verwendungszweck = models.CharField(
        max_length=140, blank=True, verbose_name="Verwendungszweck"
    )
    ausgezahlt_am = models.DateField(
        null=True, blank=True, verbose_name="Ausgezahlt am"
    )
    ausgezahlt_von = models.ForeignKey(
        "auth.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="ausgezahlte_unterstuetzungen",
        verbose_name="Ausgezahlt von",
    )

    # 4-Augen-Prinzip: Freigabe durch zweiten Nutzer
    freigegeben_am = models.DateField(
        null=True, blank=True, verbose_name="Freigegeben am"
    )
    freigegeben_von = models.ForeignKey(
        "auth.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="freigegebene_unterstuetzungen",
        verbose_name="Freigegeben von (4-Augen)",
        help_text="Muss ein anderer Nutzer als der Ersteller sein (Vier-Augen-Prinzip)",
    )
    erstellt_von = models.ForeignKey(
        "auth.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="erstellte_unterstuetzungen",
        verbose_name="Erstellt von",
    )

    # Link to recurrent payment template if this was auto-generated
    wiederkehrend_von = models.ForeignKey(
        "UnterstuetzungWiederkehrend",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Wiederkehrende Zahlung",
    )

    erstellt_am = models.DateTimeField(auto_now_add=True)
    aktualisiert_am = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "Destinatärunterstützung"
        verbose_name_plural = "Destinatärunterstützungen"
        ordering = ["-faellig_am", "-erstellt_am"]
        indexes = [
            models.Index(fields=["status", "faellig_am"]),
            models.Index(fields=["destinataer", "status"]),
            models.Index(fields=["wiederkehrend_von"]),
        ]

    def __str__(self):
        return f"{self.destinataer.get_full_name()} – €{self.betrag} am {self.faellig_am} ({self.get_status_display()})"

    def is_overdue(self):
        """Check if payment is overdue"""
        from django.utils import timezone

        return self.faellig_am < timezone.now().date() and self.status in [
            "geplant",
            "faellig",
        ]

    def can_be_marked_paid(self):
        """Check if payment can be marked as paid"""
        return self.status in ["geplant", "faellig", "nachweis_eingereicht", "freigegeben", "in_bearbeitung"]

    def can_be_freigegeben(self, requesting_user):
        """4-Augen: Freigabe nur durch anderen Nutzer als Ersteller"""
        if self.status not in ["nachweis_eingereicht", "faellig", "in_bearbeitung"]:
            return False
        if self.erstellt_von and self.erstellt_von == requesting_user:
            return False  # Selber Nutzer darf nicht freigeben
        return True

    def get_pipeline_stage(self):
        """Gibt die Pipeline-Stufe als Integer zurück (1-5)"""
        stage_map = {
            "geplant": 1,
            "faellig": 2,
            "nachweis_eingereicht": 2,
            "in_bearbeitung": 3,
            "freigegeben": 3,
            "ausgezahlt": 4,
            "abgeschlossen": 4,
            "storniert": 0,
        }
        return stage_map.get(self.status, 1)


class UnterstuetzungWiederkehrend(models.Model):
    """Template for recurring support payments"""

    INTERVALL_CHOICES = [
        ("monatlich", "Monatlich"),
        ("quartalsweise", "Vierteljährlich"),
        ("halbjaehrlich", "Halbjährlich"),
        ("jaehrlich", "Jährlich"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    destinataer = models.ForeignKey(
        "Destinataer",
        on_delete=models.CASCADE,
        related_name="wiederkehrende_unterstuetzungen",
        verbose_name="Destinatär",
    )
    konto = models.ForeignKey(
        "StiftungsKonto", on_delete=models.PROTECT, verbose_name="Zahlungskonto"
    )
    betrag = models.DecimalField(
        max_digits=12, decimal_places=2, verbose_name="Betrag (€)"
    )
    intervall = models.CharField(
        max_length=20, choices=INTERVALL_CHOICES, verbose_name="Intervall"
    )
    beschreibung = models.CharField(
        max_length=255, blank=True, verbose_name="Beschreibung"
    )

    # IBAN and payment details
    empfaenger_iban = models.CharField(max_length=34, verbose_name="Empfänger IBAN")
    empfaenger_name = models.CharField(max_length=200, verbose_name="Empfänger Name")
    verwendungszweck = models.CharField(
        max_length=140, blank=True, verbose_name="Verwendungszweck"
    )

    # Schedule settings
    erste_zahlung_am = models.DateField(verbose_name="Erste Zahlung am")
    letzte_zahlung_am = models.DateField(
        null=True, blank=True, verbose_name="Letzte Zahlung am (optional)"
    )
    naechste_generierung = models.DateField(verbose_name="Nächste Generierung")

    aktiv = models.BooleanField(default=True, verbose_name="Aktiv")
    erstellt_am = models.DateTimeField(auto_now_add=True)
    erstellt_von = models.ForeignKey(
        "auth.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Erstellt von",
    )

    class Meta:
        verbose_name = "Wiederkehrende Unterstützung"
        verbose_name_plural = "Wiederkehrende Unterstützungen"
        ordering = ["-erstellt_am"]
        indexes = [
            models.Index(fields=["aktiv", "naechste_generierung"]),
            models.Index(fields=["destinataer", "aktiv"]),
        ]

    def __str__(self):
        return f"{self.destinataer.get_full_name()} – {self.get_intervall_display()} €{self.betrag}"

    def generiere_naechste_zahlung(self):
        """Generate the next scheduled payment"""
        from datetime import timedelta

        from dateutil.relativedelta import relativedelta

        if not self.aktiv:
            return None

        heute = timezone.now().date()
        if self.naechste_generierung > heute:
            return None  # Not yet time to generate

        # Check if we've reached the end date
        if (
            self.letzte_zahlung_am
            and self.naechste_generierung > self.letzte_zahlung_am
        ):
            return None

        # Create the next payment
        neue_zahlung = DestinataerUnterstuetzung.objects.create(
            destinataer=self.destinataer,
            konto=self.konto,
            betrag=self.betrag,
            faellig_am=self.naechste_generierung,
            beschreibung=self.beschreibung
            or f"{self.get_intervall_display()} Unterstützung",
            empfaenger_iban=self.empfaenger_iban,
            empfaenger_name=self.empfaenger_name,
            verwendungszweck=self.verwendungszweck,
            wiederkehrend_von=self,
            status="geplant",
        )

        # Calculate next generation date
        if self.intervall == "monatlich":
            self.naechste_generierung = self.naechste_generierung + relativedelta(
                months=1
            )
        elif self.intervall == "quartalsweise":
            self.naechste_generierung = self.naechste_generierung + relativedelta(
                months=3
            )
        elif self.intervall == "halbjaehrlich":
            self.naechste_generierung = self.naechste_generierung + relativedelta(
                months=6
            )
        elif self.intervall == "jaehrlich":
            self.naechste_generierung = self.naechste_generierung + relativedelta(
                years=1
            )

        self.save()
        return neue_zahlung


class DestinataerNotiz(models.Model):
    """Zeitgestempelte Notizen/Telefonvermerke zu einem Destinatär, optional mit Datei."""

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    destinataer = models.ForeignKey(
        "Destinataer",
        on_delete=models.CASCADE,
        related_name="notizen_eintraege",
        verbose_name="Destinatär",
    )
    titel = models.CharField(max_length=200, blank=True, verbose_name="Titel")
    text = models.TextField(blank=True, verbose_name="Notiz")
    datei = models.FileField(
        upload_to="destinataer_notizen/", null=True, blank=True, verbose_name="Anhang"
    )
    erstellt_von = models.ForeignKey(
        "auth.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Erstellt von",
    )
    erstellt_am = models.DateTimeField(auto_now_add=True, verbose_name="Erstellt am")

    class Meta:
        verbose_name = "Destinatär-Notiz"
        verbose_name_plural = "Destinatär-Notizen"
        ordering = ["-erstellt_am"]

    def __str__(self):
        return self.titel or f"Notiz {self.erstellt_am.strftime('%d.%m.%Y %H:%M')}"


class VierteljahresNachweis(models.Model):
    """Quarterly confirmation system for Destinatäre"""

    QUARTAL_CHOICES = [
        (1, "Q1 (Jan-Mär)"),
        (2, "Q2 (Apr-Jun)"),
        (3, "Q3 (Jul-Sep)"),
        (4, "Q4 (Okt-Dez)"),
    ]

    STATUS_CHOICES = [
        ("offen", "Nachweis ausstehend"),
        ("teilweise", "Teilweise eingereicht"),
        ("eingereicht", "Vollständig eingereicht"),
        ("geprueft", "Geprüft & Freigegeben"),
        ("auto_geprueft", "Automatisch freigegeben (Semesterbasis)"),
        ("nachbesserung", "Nachbesserung erforderlich"),
        ("abgelehnt", "Abgelehnt"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    destinataer = models.ForeignKey(
        Destinataer,
        on_delete=models.CASCADE,
        related_name="quartalseinreichungen",
        verbose_name="Destinatär"
    )

    # Time period
    jahr = models.IntegerField(
        verbose_name="Jahr",
        validators=[MinValueValidator(2020), MaxValueValidator(2050)]
    )
    quartal = models.IntegerField(
        choices=QUARTAL_CHOICES,
        verbose_name="Quartal"
    )

    # Study proof (if required)
    studiennachweis_erforderlich = models.BooleanField(
        default=True,
        verbose_name="Studiennachweis erforderlich"
    )
    studiennachweis_eingereicht = models.BooleanField(
        default=False,
        verbose_name="Studiennachweis eingereicht"
    )
    studiennachweis_datei = models.FileField(
        upload_to="quarterly_proofs/studies/%Y/Q%m/",
        null=True,
        blank=True,
        verbose_name="Studiennachweis (Datei)"
    )
    studiennachweis_bemerkung = models.TextField(
        null=True,
        blank=True,
        verbose_name="Bemerkung zum Studiennachweis"
    )

    # Income/situation confirmation
    einkommenssituation_bestaetigt = models.BooleanField(
        default=False,
        verbose_name="Einkommenssituation bestätigt"
    )
    einkommenssituation_text = models.TextField(
        null=True,
        blank=True,
        verbose_name="Einkommenssituation (Text)",
        help_text="Z.B. 'Keine Änderungen seit letzter Meldung' oder Details zu Änderungen"
    )
    einkommenssituation_datei = models.FileField(
        upload_to="quarterly_proofs/income/%Y/Q%m/",
        null=True,
        blank=True,
        verbose_name="Einkommenssituation (Datei)"
    )

    # Asset/wealth confirmation
    vermogenssituation_bestaetigt = models.BooleanField(
        default=False,
        verbose_name="Vermögenssituation bestätigt"
    )
    vermogenssituation_text = models.TextField(
        null=True,
        blank=True,
        verbose_name="Vermögenssituation (Text)",
        help_text="Z.B. 'Keine Änderungen seit letzter Meldung' oder Details zu Änderungen"
    )
    vermogenssituation_datei = models.FileField(
        upload_to="quarterly_proofs/assets/%Y/Q%m/",
        null=True,
        blank=True,
        verbose_name="Vermögenssituation (Datei)"
    )

    # Additional documents
    weitere_dokumente = models.FileField(
        upload_to="quarterly_proofs/additional/%Y/Q%m/",
        null=True,
        blank=True,
        verbose_name="Weitere Dokumente"
    )
    weitere_dokumente_beschreibung = models.TextField(
        null=True,
        blank=True,
        verbose_name="Beschreibung weitere Dokumente"
    )

    # DMS-Dokumente als Nachweise verknuepfen (aus dem allgemeinen DMS)
    nachweis_dokumente = models.ManyToManyField(
        "DokumentDatei",
        blank=True,
        related_name="quartalsnachweise",
        verbose_name="Verknuepfte DMS-Dokumente",
        help_text="Dokumente aus dem DMS, die als Nachweise fuer dieses Quartal dienen.",
    )

    # Kategorie-spezifische DMS-Verknuepfungen
    studiennachweis_dms_dokument = models.ForeignKey(
        "DokumentDatei",
        on_delete=models.SET_NULL,
        null=True, blank=True,
        related_name="als_studiennachweis",
        verbose_name="Studiennachweis (DMS-Dokument)",
    )
    einkommenssituation_dms_dokument = models.ForeignKey(
        "DokumentDatei",
        on_delete=models.SET_NULL,
        null=True, blank=True,
        related_name="als_einkommensnachweis",
        verbose_name="Einkommenssituation (DMS-Dokument)",
    )
    vermogenssituation_dms_dokument = models.ForeignKey(
        "DokumentDatei",
        on_delete=models.SET_NULL,
        null=True, blank=True,
        related_name="als_vermoegensnachweis",
        verbose_name="Vermoegenssituation (DMS-Dokument)",
    )

    # Review and approval
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default="offen",
        verbose_name="Status"
    )
    interne_notizen = models.TextField(
        null=True,
        blank=True,
        verbose_name="Interne Notizen (nur für Verwaltung)"
    )

    # Timestamps and tracking
    erstellt_am = models.DateTimeField(auto_now_add=True, verbose_name="Erstellt am")
    aktualisiert_am = models.DateTimeField(auto_now=True, verbose_name="Aktualisiert am")
    eingereicht_am = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="Eingereicht am"
    )
    geprueft_am = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="Geprüft am"
    )
    geprueft_von = models.ForeignKey(
        "auth.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name="Geprüft von"
    )

    # Deadline tracking
    faelligkeitsdatum = models.DateField(
        null=True,
        blank=True,
        verbose_name="Fälligkeitsdatum",
        help_text="Veraltet - wird durch studiennachweis_faelligkeitsdatum und zahlung_faelligkeitsdatum ersetzt"
    )

    # Separate deadlines for study proof (semester-based) and payment (quarterly)
    studiennachweis_faelligkeitsdatum = models.DateField(
        null=True,
        blank=True,
        verbose_name="Studiennachweis Fälligkeitsdatum",
        help_text="Semesterbasierte Frist: Q1/Q2 → 15. März, Q3/Q4 → 15. September"
    )

    zahlung_faelligkeitsdatum = models.DateField(
        null=True,
        blank=True,
        verbose_name="Zahlungsfälligkeit",
        help_text="Vierteljährliche Zahlungsfälligkeit im Voraus: Q1→15. Dez (Vorjahr), Q2→15. Mär, Q3→15. Jun, Q4→15. Sep"
    )

    class Meta:
        verbose_name = "Vierteljahresnachweis"
        verbose_name_plural = "Vierteljahresnachweise"
        ordering = ["-jahr", "-quartal", "destinataer__nachname"]
        unique_together = ["destinataer", "jahr", "quartal"]  # One entry per quarter per person
        indexes = [
            models.Index(fields=["jahr", "quartal", "status"]),
            models.Index(fields=["destinataer", "status"]),
            models.Index(fields=["faelligkeitsdatum"]),
        ]

    def __str__(self):
        return f"{self.destinataer.get_full_name()} - {self.jahr} Q{self.quartal} ({self.get_status_display()})"

    def get_quarter_display(self):
        """Get a nice display name for the quarter"""
        quarter_names = {
            1: "Q1 (Januar - März)",
            2: "Q2 (April - Juni)",
            3: "Q3 (Juli - September)",
            4: "Q4 (Oktober - Dezember)"
        }
        return quarter_names.get(self.quartal, f"Q{self.quartal}")

    def is_complete(self):
        """Check if all required documents/confirmations are provided"""
        complete = True

        # DMS-Dokumente (kategorie-spezifisch oder generisch) zaehlen als Nachweis
        has_dms_studiennachweis = (
            bool(self.studiennachweis_dms_dokument_id)
            or self.nachweis_dokumente.filter(kontext="studiennachweis").exists()
        )

        # Check study proof (always required now)
        complete &= self.studiennachweis_eingereicht and (
            bool(self.studiennachweis_datei) or bool(self.studiennachweis_bemerkung) or has_dms_studiennachweis
        )

        # Check income situation (either text, file, or DMS document)
        complete &= self.einkommenssituation_bestaetigt and (
            bool(self.einkommenssituation_text) or bool(self.einkommenssituation_datei)
            or bool(self.einkommenssituation_dms_dokument_id)
        )

        # Check asset situation (either text, file, or DMS document)
        complete &= self.vermogenssituation_bestaetigt and (
            bool(self.vermogenssituation_text) or bool(self.vermogenssituation_datei)
            or bool(self.vermogenssituation_dms_dokument_id)
        )

        return complete

    def is_overdue(self):
        """Check if the deadline has passed"""
        if not self.faelligkeitsdatum:
            return False
        return timezone.now().date() > self.faelligkeitsdatum and self.status in ["offen", "teilweise"]

    def get_completion_percentage(self):
        """Calculate completion percentage"""
        total_requirements = 2  # Income and assets always required
        completed_requirements = 0

        has_dms_studiennachweis = (
            bool(self.studiennachweis_dms_dokument_id)
            or self.nachweis_dokumente.filter(kontext="studiennachweis").exists()
        )

        # Study proof (if required)
        if self.studiennachweis_erforderlich:
            total_requirements += 1
            if self.studiennachweis_eingereicht and (
                bool(self.studiennachweis_datei) or bool(self.studiennachweis_bemerkung) or has_dms_studiennachweis
            ):
                completed_requirements += 1

        # Income situation
        if self.einkommenssituation_bestaetigt and (
            bool(self.einkommenssituation_text) or bool(self.einkommenssituation_datei)
            or bool(self.einkommenssituation_dms_dokument_id)
        ):
            completed_requirements += 1

        # Asset situation
        if self.vermogenssituation_bestaetigt and (
            bool(self.vermogenssituation_text) or bool(self.vermogenssituation_datei)
            or bool(self.vermogenssituation_dms_dokument_id)
        ):
            completed_requirements += 1

        return int((completed_requirements / total_requirements) * 100) if total_requirements > 0 else 0

    def get_study_proof_deadline(self):
        """Calculate semester-based study proof deadline"""
        from datetime import date
        # Q1, Q2 → March 15 (same year)
        # Q3, Q4 → September 15 (same year)
        if self.quartal in [1, 2]:
            return date(self.jahr, 3, 15)
        else:  # Q3, Q4
            return date(self.jahr, 9, 15)

    def get_payment_due_date(self):
        """Calculate quarterly payment due date (paid in advance)"""
        from datetime import date
        # Q1 → December 15 (previous year)
        # Q2 → March 15 (same year)
        # Q3 → June 15 (same year)
        # Q4 → September 15 (same year)
        if self.quartal == 1:
            return date(self.jahr - 1, 12, 15)
        elif self.quartal == 2:
            return date(self.jahr, 3, 15)
        elif self.quartal == 3:
            return date(self.jahr, 6, 15)
        else:  # Q4
            return date(self.jahr, 9, 15)

    def is_study_proof_overdue(self):
        """Check if study proof deadline has passed"""
        if not self.studiennachweis_faelligkeitsdatum:
            return False
        from django.utils import timezone
        return timezone.now().date() > self.studiennachweis_faelligkeitsdatum and not self.studiennachweis_eingereicht

    def is_payment_overdue(self):
        """Check if payment due date has passed"""
        if not self.zahlung_faelligkeitsdatum:
            return False
        from django.utils import timezone
        # Payment is overdue if due date passed and no payment exists or payment is not completed
        payment = self.get_related_support_payment()
        if payment and payment.status in ['bezahlt', 'in_bearbeitung']:
            return False
        return timezone.now().date() > self.zahlung_faelligkeitsdatum

    def is_overdue(self):
        """Check if either deadline has passed"""
        return self.is_study_proof_overdue() or self.is_payment_overdue()

    def save(self, *args, **kwargs):
        """Override save to auto-update status and timestamps"""
        # Set study proof deadline (semester-based) if not provided
        if not self.studiennachweis_faelligkeitsdatum:
            self.studiennachweis_faelligkeitsdatum = self.get_study_proof_deadline()

        # Set payment due date (quarterly, advance) if not provided
        if not self.zahlung_faelligkeitsdatum:
            self.zahlung_faelligkeitsdatum = self.get_payment_due_date()

        # Backward compatibility: set faelligkeitsdatum from study proof deadline if not set
        if not self.faelligkeitsdatum:
            self.faelligkeitsdatum = self.studiennachweis_faelligkeitsdatum

        # Auto-update status based on completion
        if self.is_complete():
            if self.status == "offen":
                self.status = "eingereicht"
                self.eingereicht_am = timezone.now()
        else:
            completion = self.get_completion_percentage()
            if completion > 0 and completion < 100 and self.status == "offen":
                self.status = "teilweise"

        super().save(*args, **kwargs)

    def get_related_support_payment(self):
        """Get the related support payment for this quarterly confirmation"""
        from datetime import date, timedelta
        from django.db.models import Q

        # Use payment due date from quarterly confirmation for accurate search
        # This is more accurate than using quarter date range, especially for Q1 (Dec 15 prev year)
        payment_due_date = self.zahlung_faelligkeitsdatum
        if not payment_due_date:
            # Fallback: calculate if not set
            if self.quartal == 1:
                payment_due_date = date(self.jahr - 1, 12, 15)
            elif self.quartal == 2:
                payment_due_date = date(self.jahr, 3, 15)
            elif self.quartal == 3:
                payment_due_date = date(self.jahr, 6, 15)
            else:  # Q4
                payment_due_date = date(self.jahr, 9, 15)

        # Search for existing payment - match by payment due date and description
        # Use a date range around the due date (±30 days) to catch any variations
        date_start = payment_due_date - timedelta(days=30)
        date_end = payment_due_date + timedelta(days=30)

        return DestinataerUnterstuetzung.objects.filter(
            destinataer=self.destinataer,
            faellig_am__gte=date_start,
            faellig_am__lte=date_end
        ).filter(
            Q(beschreibung__contains=f"Q{self.quartal}/{self.jahr}") |
            Q(beschreibung__contains=f"Vierteljährliche Unterstützung Q{self.quartal}/{self.jahr}")
        ).first()

    def auto_approve_next_quarter(self):
        """Auto-approve the next quarter when Q1 or Q3 is approved (semester-based logic)"""
        if self.quartal in [1, 3] and self.status == "geprueft":
            next_quarter = self.quartal + 1
            try:
                next_nachweis = VierteljahresNachweis.objects.get(
                    destinataer=self.destinataer,
                    jahr=self.jahr,
                    quartal=next_quarter
                )

                if next_nachweis.status in ["offen", "teilweise"]:
                    # Copy study proof confirmations from current quarter (semester-based)
                    next_nachweis.studiennachweis_eingereicht = self.studiennachweis_eingereicht
                    next_nachweis.studiennachweis_datei = self.studiennachweis_datei
                    next_nachweis.studiennachweis_bemerkung = self.studiennachweis_bemerkung

                    # Set study proof deadline for next quarter (same semester)
                    next_nachweis.studiennachweis_faelligkeitsdatum = next_nachweis.get_study_proof_deadline()

                    # Set auto-approved status
                    next_nachweis.status = "auto_geprueft"
                    next_nachweis.geprueft_am = timezone.now()
                    next_nachweis.geprueft_von = self.geprueft_von
                    next_nachweis.save(update_fields=[
                        'studiennachweis_eingereicht', 'studiennachweis_datei', 'studiennachweis_bemerkung',
                        'studiennachweis_faelligkeitsdatum', 'status', 'geprueft_am', 'geprueft_von'
                    ])

                    return next_nachweis
            except VierteljahresNachweis.DoesNotExist:
                pass
        return None

    @classmethod
    def get_or_create_for_period(cls, destinataer, jahr, quartal):
        """Get or create a quarterly confirmation for a specific period"""
        nachweis, created = cls.objects.get_or_create(
            destinataer=destinataer,
            jahr=jahr,
            quartal=quartal,
            defaults={
                'studiennachweis_erforderlich': destinataer.studiennachweis_erforderlich,
                'status': 'offen'
            }
        )
        return nachweis, created

    @classmethod
    def get_current_quarter(cls):
        """Get the current quarter based on today's date"""
        from datetime import date
        today = date.today()
        month = today.month

        if month <= 3:
            return today.year, 1
        elif month <= 6:
            return today.year, 2
        elif month <= 9:
            return today.year, 3
        else:
            return today.year, 4

    @classmethod
    def get_overdue_confirmations(cls):
        """Get all overdue quarterly confirmations"""
        from datetime import date
        today = date.today()

        return cls.objects.filter(
            faelligkeitsdatum__lt=today,
            status__in=["offen", "teilweise"]
        ).select_related("destinataer")

    def auto_approve_next_quarter(self):
        """Auto-approve the next quarter when Q1 or Q3 is approved (semester-based logic)"""
        if self.quartal in [1, 3] and self.status == "geprueft":
            next_quarter = self.quartal + 1
            try:
                next_nachweis = VierteljahresNachweis.objects.get(
                    destinataer=self.destinataer,
                    jahr=self.jahr,
                    quartal=next_quarter
                )

                if next_nachweis.status in ["offen", "teilweise"]:
                    # Copy document confirmations from current quarter
                    next_nachweis.studiennachweis_eingereicht = self.studiennachweis_eingereicht
                    next_nachweis.einkommenssituation_bestaetigt = self.einkommenssituation_bestaetigt
                    next_nachweis.vermogenssituation_bestaetigt = self.vermogenssituation_bestaetigt

                    # Set auto-approved status
                    next_nachweis.status = "auto_geprueft"
                    next_nachweis.geprueft_am = timezone.now()
                    next_nachweis.geprueft_von = self.geprueft_von
                    next_nachweis.save(update_fields=[
                        'studiennachweis_eingereicht', 'einkommenssituation_bestaetigt',
                        'vermogenssituation_bestaetigt', 'status', 'geprueft_am', 'geprueft_von'
                    ])

                    return next_nachweis
            except VierteljahresNachweis.DoesNotExist:
                pass
        return None


class EmailEingang(models.Model):
    """
    Erfasst eingehende E-Mails (Destinataere, Rechnungen, Grundstuecke, Allgemein).

    Wird automatisch durch den Celery-Task `poll_emails` befuellt,
    der das IMAP-Postfach der Stiftung (paperless@vhtv-stiftung.de) ueberwacht.
    Anhaenge werden direkt als DokumentDatei im Django-DMS gespeichert.
    """

    KATEGORIE_CHOICES = [
        ("destinataer", "Destinataer"),
        ("rechnung", "Rechnung"),
        ("land_pacht", "Grundstueck / Pacht"),
        ("stiftungsgeschichte", "Stiftungsgeschichte"),
        ("allgemein", "Allgemein"),
    ]

    STATUS_CHOICES = [
        ("neu", "Neu / Unbearbeitet"),
        ("zugewiesen", "Destinataer zugewiesen"),
        ("verarbeitet", "Verarbeitet"),
        ("rechnung_erfasst", "Rechnung erfasst"),
        ("zahlung_gebucht", "Zahlung gebucht"),
        ("unbekannt", "Unbekannter Absender"),
        ("fehler", "Fehler bei Verarbeitung"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    # Klassifizierung
    kategorie = models.CharField(
        max_length=20,
        choices=KATEGORIE_CHOICES,
        default="allgemein",
        verbose_name="Kategorie",
    )

    # Verknuepfung zum Destinataer (None = kein Destinataer-Bezug)
    destinataer = models.ForeignKey(
        Destinataer,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="email_eingaenge",
        verbose_name="Destinataer",
    )

    # Verknuepfung zu Verwaltungskosten (Rechnungsworkflow)
    verwaltungskosten = models.ForeignKey(
        "Verwaltungskosten",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="email_eingaenge",
        verbose_name="Verwaltungskosten / Rechnung",
    )

    # Verknuepfung zu Land / Verpachtung
    land = models.ForeignKey(
        "Land",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="email_eingaenge",
        verbose_name="Laenderei",
    )
    verpachtung = models.ForeignKey(
        "LandVerpachtung",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="email_eingaenge",
        verbose_name="Verpachtung",
    )

    # E-Mail-Metadaten
    absender_email = models.EmailField(verbose_name="Absender-E-Mail")
    absender_name = models.CharField(
        max_length=255, blank=True, verbose_name="Absender-Name"
    )
    betreff = models.CharField(max_length=500, blank=True, verbose_name="Betreff")
    eingangsdatum = models.DateTimeField(verbose_name="Eingangsdatum")
    email_text = models.TextField(blank=True, verbose_name="E-Mail-Text")

    # Anhaenge: DMS-Dokumente (Phase 3 – DokumentDatei)
    dokument_dateien = models.ManyToManyField(
        "DokumentDatei",
        blank=True,
        related_name="email_eingaenge",
        verbose_name="DMS-Dokumente (Anhaenge)",
        help_text="Automatisch befuellte Anhaenge als Django-DMS-Dateien.",
    )

    # Anhaenge: Liste der Paperless-Dokument-IDs (JSON-Format, deprecated)
    paperless_dokument_ids = models.JSONField(
        default=list,
        blank=True,
        verbose_name="Paperless Dokument-IDs (Anhaenge, veraltet)",
        help_text="Veraltet – wird nach vollstaendiger Migration entfernt. Neue Anhaenge in dokument_dateien.",
    )

    # Verarbeitungsstatus
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default="neu",
        verbose_name="Status",
    )
    fehler_details = models.TextField(
        blank=True,
        verbose_name="Fehlerdetails",
        help_text="Technische Fehlermeldung bei Verarbeitungsfehlern",
    )
    notizen = models.TextField(
        blank=True,
        verbose_name="Interne Notizen",
        help_text="Manuelle Notizen der Verwaltung zur E-Mail",
    )

    # Verweis auf VierteljahresNachweis, falls E-Mail einem Quartal zugeordnet
    quartalsnachweis = models.ForeignKey(
        "VierteljahresNachweis",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="email_eingaenge",
        verbose_name="Quartalsnachweis (zugeordnet)",
    )

    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Erfasst am")

    class Meta:
        verbose_name = "E-Mail-Eingang"
        verbose_name_plural = "E-Mail-Eingaenge"
        ordering = ["-eingangsdatum"]

    def __str__(self):
        dest = str(self.destinataer) if self.destinataer else self.absender_email
        return f"[{self.eingangsdatum.strftime('%d.%m.%Y')}] {dest}: {self.betreff[:60]}"

    def get_paperless_links(self):
        """Gibt Liste der Paperless-Dokument-URLs zurueck (deprecated)."""
        from django.conf import settings
        base = settings.PAPERLESS_API_URL or ""
        return [
            f"{base}/documents/{doc_id}/"
            for doc_id in (self.paperless_dokument_ids or [])
        ]

    def get_dms_dokumente(self):
        """Gibt alle verknuepften DokumentDatei-Objekte zurueck."""
        return self.dokument_dateien.all()


# Backward-compatible alias
DestinataerEmailEingang = EmailEingang


class UploadToken(models.Model):
    """
    Einmaliger Upload-Token für tokenbasiertes Nachweis-Upload-Portal.

    Ermöglicht Destinatären den Dokumenten-Upload ohne Nutzerkonto.
    Der Token wird per E-Mail (mit QR-Code) versendet und ist 30 Tage gültig.
    Nach einmaliger Nutzung (Upload) wird eingeloest_am gesetzt.
    Die IP-Adresse wird nur als SHA-256-Hash gespeichert (DSGVO-konform).
    """

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    token = models.CharField(
        max_length=128,
        unique=True,
        db_index=True,
        verbose_name="Token",
    )
    destinataer = models.ForeignKey(
        "Destinataer",
        on_delete=models.CASCADE,
        related_name="upload_tokens",
        verbose_name="Destinatär",
    )
    nachweis = models.ForeignKey(
        "VierteljahresNachweis",
        on_delete=models.CASCADE,
        related_name="upload_tokens",
        verbose_name="Nachweis",
    )
    gueltig_bis = models.DateTimeField(verbose_name="Gültig bis")
    erstellt_am = models.DateTimeField(auto_now_add=True, verbose_name="Erstellt am")
    eingeloest_am = models.DateTimeField(
        null=True, blank=True, verbose_name="Eingelöst am"
    )
    ist_aktiv = models.BooleanField(default=True, verbose_name="Aktiv")
    ip_hash = models.CharField(
        max_length=64, blank=True, null=True, verbose_name="IP-Hash (SHA-256)"
    )
    erinnerung_gesendet = models.BooleanField(
        default=False, verbose_name="Erinnerung gesendet"
    )
    einwilligung_erteilt_am = models.DateTimeField(
        null=True, blank=True, verbose_name="Einwilligung erteilt am",
        help_text="Zeitpunkt der DSGVO-Einwilligung beim Upload (Art. 7 Abs. 1 DSGVO)"
    )

    class Meta:
        verbose_name = "Upload-Token"
        verbose_name_plural = "Upload-Token"
        ordering = ["-erstellt_am"]

    def __str__(self):
        return f"Token für {self.destinataer} ({self.nachweis})"

    def ist_gueltig(self):
        """Prüft ob der Token noch gültig und aktiv ist."""
        from django.utils import timezone
        return (
            self.ist_aktiv
            and self.eingeloest_am is None
            and self.gueltig_bis > timezone.now()
        )

    def einloesen(self, ip_address=None):
        """Markiert den Token als eingelöst. IP wird als Hash gespeichert."""
        import hashlib
        from django.utils import timezone
        self.eingeloest_am = timezone.now()
        self.ist_aktiv = False
        if ip_address:
            self.ip_hash = hashlib.sha256(ip_address.encode()).hexdigest()
        self.save(update_fields=["eingeloest_am", "ist_aktiv", "ip_hash"])


class OnboardingEinladung(models.Model):
    """
    Einladung zum Onboarding für neue Destinatäre.

    Verwaltungsmitarbeiter versenden eine Einladungs-E-Mail.
    Der Eingeladene füllt das mehrstufige Onboarding-Formular aus.
    Nach Abschluss wird ein neuer Destinatär mit unterstuetzung_bestaetigt=False angelegt.
    """

    STATUS_CHOICES = [
        ("offen", "Offen"),
        ("abgeschlossen", "Abgeschlossen"),
        ("abgelaufen", "Abgelaufen"),
        ("widerrufen", "Widerrufen"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    token = models.CharField(
        max_length=128,
        unique=True,
        db_index=True,
        verbose_name="Token",
    )
    email = models.EmailField(verbose_name="E-Mail-Adresse des Eingeladenen")
    vorname = models.CharField(
        max_length=100, blank=True, verbose_name="Vorname (optional)"
    )
    nachname = models.CharField(
        max_length=100, blank=True, verbose_name="Nachname (optional)"
    )
    eingeladen_von = models.ForeignKey(
        "auth.User",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="onboarding_einladungen",
        verbose_name="Eingeladen von",
    )
    gueltig_bis = models.DateTimeField(verbose_name="Gültig bis")
    erstellt_am = models.DateTimeField(auto_now_add=True, verbose_name="Erstellt am")
    abgeschlossen_am = models.DateTimeField(
        null=True, blank=True, verbose_name="Abgeschlossen am"
    )
    destinataer = models.ForeignKey(
        "Destinataer",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="onboarding_einladung",
        verbose_name="Resultierender Destinatär",
    )
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default="offen",
        verbose_name="Status",
    )
    notizen = models.TextField(blank=True, verbose_name="Interne Notizen")

    class Meta:
        verbose_name = "Onboarding-Einladung"
        verbose_name_plural = "Onboarding-Einladungen"
        ordering = ["-erstellt_am"]

    def __str__(self):
        return f"Einladung für {self.email} ({self.get_status_display()})"

    def ist_gueltig(self):
        """Prüft ob die Einladung noch gültig ist."""
        from django.utils import timezone
        return (
            self.status == "offen"
            and self.gueltig_bis > timezone.now()
        )
