import uuid

from django.db import models


class CSVImport(models.Model):
    """Track CSV import operations for audit purposes"""

    IMPORT_TYPE_CHOICES = [
        ("destinataere", "Destinatäre"),
        ("paechter", "Pächter"),
        ("laendereien", "Ländereien"),
        ("verpachtungen", "Verpachtungen"),
        ("foerderungen", "Förderungen"),
        ("konten", "Stiftungskonten"),
        ("verwaltungskosten", "Verwaltungskosten"),
        ("rentmeister", "Rentmeister"),
        ("personen", "Personen (Legacy)"),
    ]

    STATUS_CHOICES = [
        ("pending", "Ausstehend"),
        ("processing", "Wird verarbeitet"),
        ("completed", "Abgeschlossen"),
        ("failed", "Fehlgeschlagen"),
        ("partial", "Teilweise erfolgreich"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    import_type = models.CharField(
        max_length=20, choices=IMPORT_TYPE_CHOICES, verbose_name="Import-Typ"
    )
    filename = models.CharField(max_length=255, verbose_name="Dateiname")
    file_size = models.IntegerField(verbose_name="Dateigröße (Bytes)")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="pending")

    # Results
    total_rows = models.IntegerField(default=0, verbose_name="Gesamtzeilen")
    imported_rows = models.IntegerField(default=0, verbose_name="Importierte Zeilen")
    failed_rows = models.IntegerField(default=0, verbose_name="Fehlgeschlagene Zeilen")
    error_log = models.TextField(null=True, blank=True, verbose_name="Fehlerprotokoll")

    # Metadata
    created_by = models.CharField(
        max_length=100, null=True, blank=True, verbose_name="Erstellt von"
    )
    started_at = models.DateTimeField(auto_now_add=True, verbose_name="Gestartet um")
    completed_at = models.DateTimeField(
        null=True, blank=True, verbose_name="Abgeschlossen um"
    )

    class Meta:
        verbose_name = "CSV Import"
        verbose_name_plural = "CSV Imports"
        ordering = ["-started_at"]

    def __str__(self):
        return f"{self.get_import_type_display()} - {self.filename} ({self.status})"

    def get_duration(self):
        """Calculate import duration"""
        if self.completed_at and self.started_at:
            return self.completed_at - self.started_at
        return None

    def get_success_rate(self):
        """Calculate success rate percentage"""
        if self.total_rows > 0:
            return (self.imported_rows / self.total_rows) * 100
        return 0


class ApplicationPermission(models.Model):
    """Custom permissions for application functions"""

    class Meta:
        managed = False  # No database table creation
        default_permissions = ()  # Remove default Django permissions
        permissions = [
            # Entity Management Permissions
            ("manage_destinataere", "Kann Destinatäre verwalten"),
            ("view_destinataere", "Kann Destinatäre anzeigen"),
            ("manage_land", "Kann Ländereien verwalten"),
            ("view_land", "Kann Ländereien anzeigen"),
            ("manage_paechter", "Kann Pächter verwalten"),
            ("view_paechter", "Kann Pächter anzeigen"),
            ("manage_verpachtungen", "Kann Verpachtungen verwalten"),
            ("view_verpachtungen", "Kann Verpachtungen anzeigen"),
            ("manage_foerderungen", "Kann Förderungen verwalten"),
            ("view_foerderungen", "Kann Förderungen anzeigen"),
            # Document Management Permissions
            ("manage_documents", "Kann Dokumente verwalten"),
            ("view_documents", "Kann Dokumente anzeigen"),
            ("link_documents", "Kann Dokumente verknüpfen"),
            # Financial Management Permissions
            ("manage_verwaltungskosten", "Kann Verwaltungskosten verwalten"),
            ("view_verwaltungskosten", "Kann Verwaltungskosten anzeigen"),
            ("approve_payments", "Kann Zahlungen genehmigen"),
            ("manage_konten", "Kann Stiftungskonten verwalten"),
            ("view_konten", "Kann Stiftungskonten anzeigen"),
            ("manage_rentmeister", "Kann Rentmeister verwalten"),
            ("view_rentmeister", "Kann Rentmeister anzeigen"),
            # Administration Permissions
            ("access_administration", "Kann Administration aufrufen"),
            ("view_audit_logs", "Kann Audit-Logs anzeigen"),
            ("manage_backups", "Kann Backups erstellen und verwalten"),
            ("manage_users", "Kann Benutzer verwalten"),
            ("manage_permissions", "Kann Berechtigungen verwalten"),
            # Veranstaltungen Permissions
            ("manage_veranstaltungen", "Kann Veranstaltungen verwalten"),
            ("view_veranstaltungen", "Kann Veranstaltungen anzeigen"),
            # Import/Export Permissions
            ("import_data", "Kann Daten importieren"),
            ("export_data", "Kann Daten exportieren"),
            # System Permissions
            ("access_django_admin", "Kann Django Admin aufrufen"),
            ("view_system_stats", "Kann Systemstatistiken anzeigen"),
            # AI Agent Permissions
            ("can_use_agent", "Kann AI-Assistenten nutzen"),
        ]


class AuditLog(models.Model):
    """Audit Log für alle Benutzeraktionen im System"""

    ACTION_TYPES = [
        ("create", "Erstellt"),
        ("update", "Aktualisiert"),
        ("delete", "Gelöscht"),
        ("link", "Verknüpft"),
        ("unlink", "Verknüpfung entfernt"),
        ("login", "Anmeldung"),
        ("logout", "Abmeldung"),
        ("backup", "Backup erstellt"),
        ("restore", "Wiederherstellung"),
        ("export", "Export"),
        ("import", "Import"),
    ]

    ENTITY_TYPES = [
        ("destinataer", "Destinatär"),
        ("land", "Länderei"),
        ("paechter", "Pächter"),
        ("verpachtung", "Verpachtung"),
        ("foerderung", "Förderung"),
        ("rentmeister", "Rentmeister"),
        ("stiftungskonto", "Stiftungskonto"),
        ("verwaltungskosten", "Verwaltungskosten"),
        ("banktransaction", "Bank-Transaktion"),
        ("dokumentlink", "Dokument-Verknüpfung"),
        ("system", "System"),
        ("user", "Benutzer"),
    ]

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

    # Benutzer und Zeitpunkt
    user = models.ForeignKey(
        "auth.User", on_delete=models.SET_NULL, null=True, verbose_name="Benutzer"
    )
    username = models.CharField(
        max_length=150, verbose_name="Benutzername"
    )  # Fallback falls User gelöscht wird
    timestamp = models.DateTimeField(auto_now_add=True, verbose_name="Zeitpunkt")

    # Aktion
    action = models.CharField(
        max_length=20, choices=ACTION_TYPES, verbose_name="Aktion"
    )
    entity_type = models.CharField(
        max_length=20, choices=ENTITY_TYPES, verbose_name="Entitätstyp"
    )
    entity_id = models.CharField(max_length=100, blank=True, verbose_name="Entitäts-ID")
    entity_name = models.CharField(max_length=255, verbose_name="Entitätsname")

    # Details
    description = models.TextField(verbose_name="Beschreibung")
    changes = models.JSONField(
        null=True, blank=True, verbose_name="Änderungen"
    )  # Alte und neue Werte

    # Request-Informationen
    ip_address = models.GenericIPAddressField(
        null=True, blank=True, verbose_name="IP-Adresse"
    )
    user_agent = models.TextField(blank=True, verbose_name="User Agent")
    session_key = models.CharField(
        max_length=40, blank=True, verbose_name="Session-Key"
    )

    class Meta:
        verbose_name = "Audit Log Eintrag"
        verbose_name_plural = "Audit Log Einträge"
        ordering = ["-timestamp"]
        indexes = [
            models.Index(fields=["timestamp"]),
            models.Index(fields=["user", "timestamp"]),
            models.Index(fields=["entity_type", "timestamp"]),
            models.Index(fields=["action", "timestamp"]),
        ]

    def __str__(self):
        return f"{self.username} - {self.get_action_display()} {self.get_entity_type_display()} '{self.entity_name}' ({self.timestamp.strftime('%d.%m.%Y %H:%M')})"

    def get_changes_summary(self):
        """Erstellt eine lesbare Zusammenfassung der Änderungen"""
        if not self.changes:
            return "Keine Details verfügbar"

        if isinstance(self.changes, dict):
            summary = []
            for field, values in self.changes.items():
                if isinstance(values, dict) and "old" in values and "new" in values:
                    old_val = values["old"] or "Leer"
                    new_val = values["new"] or "Leer"
                    summary.append(f"{field}: '{old_val}' → '{new_val}'")
            return "; ".join(summary) if summary else "Keine Änderungen dokumentiert"

        return str(self.changes)


class BackupJob(models.Model):
    """Backup-Jobs und deren Status"""

    STATUS_CHOICES = [
        ("pending", "Wartend"),
        ("running", "Läuft"),
        ("completed", "Abgeschlossen"),
        ("failed", "Fehlgeschlagen"),
        ("cancelled", "Abgebrochen"),
    ]

    TYPE_CHOICES = [
        ("full", "Vollständiges Backup"),
        ("database", "Nur Datenbank"),
        ("files", "Nur Dateien"),
    ]

    OPERATION_CHOICES = [
        ("backup", "Backup"),
        ("restore", "Wiederherstellung"),
    ]

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

    # Job-Details
    operation = models.CharField(
        max_length=20, choices=OPERATION_CHOICES, default="backup", verbose_name="Vorgang"
    )
    backup_type = models.CharField(
        max_length=20, choices=TYPE_CHOICES, verbose_name="Backup-Typ"
    )
    status = models.CharField(
        max_length=20, choices=STATUS_CHOICES, default="pending", verbose_name="Status"
    )

    # Ausführung
    created_by = models.ForeignKey(
        "auth.User", on_delete=models.SET_NULL, null=True, verbose_name="Erstellt von"
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Erstellt am")
    started_at = models.DateTimeField(
        null=True, blank=True, verbose_name="Gestartet am"
    )
    completed_at = models.DateTimeField(
        null=True, blank=True, verbose_name="Abgeschlossen am"
    )

    # Ergebnis
    backup_filename = models.CharField(
        max_length=255, blank=True, verbose_name="Backup-Dateiname"
    )
    backup_size = models.BigIntegerField(
        null=True, blank=True, verbose_name="Backup-Größe (Bytes)"
    )
    error_message = models.TextField(blank=True, verbose_name="Fehlermeldung")

    # Metadaten
    database_size = models.BigIntegerField(
        null=True, blank=True, verbose_name="Datenbankgröße (Bytes)"
    )
    files_count = models.IntegerField(
        null=True, blank=True, verbose_name="Anzahl Dateien"
    )

    class Meta:
        verbose_name = "Backup-Job"
        verbose_name_plural = "Backup-Jobs"
        ordering = ["-created_at"]

    def __str__(self):
        return f"{self.get_backup_type_display()} - {self.get_status_display()} ({self.created_at.strftime('%d.%m.%Y %H:%M')})"

    def get_duration(self):
        """Berechnet die Dauer des Backup-Jobs"""
        if self.started_at and self.completed_at:
            return self.completed_at - self.started_at
        elif self.started_at:
            from django.utils import timezone

            return timezone.now() - self.started_at
        return None

    def get_size_display(self):
        """Formatiert die Backup-Größe für die Anzeige"""
        if not self.backup_size:
            return "Unbekannt"

        size = self.backup_size
        for unit in ["B", "KB", "MB", "GB"]:
            if size < 1024:
                return f"{size:.1f} {unit}"
            size /= 1024
        return f"{size:.1f} TB"


class AppConfiguration(models.Model):
    """Application configuration settings that can be managed through the admin interface"""

    SETTING_TYPE_CHOICES = [
        ("text", "Text"),
        ("password", "Password"),
        ("number", "Number"),
        ("boolean", "Boolean"),
        ("url", "URL"),
        ("tag", "Tag Name"),
        ("tag_id", "Tag ID"),
    ]

    CATEGORY_CHOICES = [
        ("paperless", "Paperless Integration"),
        ("email", "E-Mail / IMAP"),
        ("general", "General Settings"),
        ("corporate", "Corporate Identity"),
        ("notifications", "Notifications"),
        ("system", "System Settings"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    key = models.CharField(max_length=100, unique=True, verbose_name="Setting Key")
    display_name = models.CharField(max_length=200, verbose_name="Display Name")
    description = models.TextField(blank=True, null=True, verbose_name="Description")
    value = models.TextField(verbose_name="Value")
    default_value = models.TextField(verbose_name="Default Value")
    setting_type = models.CharField(
        max_length=20, choices=SETTING_TYPE_CHOICES, default="text", verbose_name="Type"
    )
    category = models.CharField(
        max_length=50,
        choices=CATEGORY_CHOICES,
        default="general",
        verbose_name="Category",
    )
    is_active = models.BooleanField(default=True, verbose_name="Active")
    is_system = models.BooleanField(
        default=False, verbose_name="System Setting (read-only)"
    )
    order = models.IntegerField(default=0, verbose_name="Display Order")

    # Metadata
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "App Configuration"
        verbose_name_plural = "App Configurations"
        ordering = ["category", "order", "display_name"]

    def __str__(self):
        return f"{self.display_name} ({self.key})"

    def get_typed_value(self):
        """Return the value converted to the appropriate type"""
        if self.setting_type == "boolean":
            return self.value.lower() in ("true", "1", "yes", "on")
        elif self.setting_type == "number":
            try:
                if "." in self.value:
                    return float(self.value)
                return int(self.value)
            except (ValueError, TypeError):
                return 0
        return self.value

    @classmethod
    def get_setting(cls, key, default=None):
        """Get a setting value by key"""
        try:
            setting = cls.objects.get(key=key, is_active=True)
            return setting.get_typed_value()
        except cls.DoesNotExist:
            return default

    @classmethod
    def set_setting(
        cls,
        key,
        value,
        display_name=None,
        description=None,
        setting_type="text",
        category="general",
    ):
        """Set or update a setting value"""
        setting, created = cls.objects.get_or_create(
            key=key,
            defaults={
                "display_name": display_name or key,
                "description": description,
                "value": str(value),
                "default_value": str(value),
                "setting_type": setting_type,
                "category": category,
            },
        )
        if not created:
            setting.value = str(value)
            setting.save()
        return setting


class HelpBox(models.Model):
    """Editierbare Hilfe-Infoboxen für Formulare"""

    PAGE_CHOICES = [
        ("destinataer_new", "Neuer Destinatär"),
        ("unterstuetzung_new", "Neue Unterstützung"),
        ("foerderung_new", "Neue Förderung"),
        ("paechter_new", "Neuer Pächter"),
        ("laenderei_new", "Neue Länderei"),
        ("verpachtung_new", "Neue Verpachtung"),
        ("land_abrechnung_new", "Neue Landabrechnung"),
        ("person_new", "Neue Person"),
        ("konto_new", "Neues Konto"),
        ("verwaltungskosten_new", "Neue Verwaltungskosten"),
        ("rentmeister_new", "Neuer Rentmeister"),
        ("dokument_new", "Neues Dokument"),
        ("user_new", "Neuer Benutzer"),
        ("csv_import_new", "CSV Import"),
        ("destinataer_notiz_new", "Destinatär Notiz"),
    ]

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    page_key = models.CharField(
        max_length=50, choices=PAGE_CHOICES, unique=True, verbose_name="Seite"
    )
    title = models.CharField(max_length=200, verbose_name="Titel der Hilfsbox")
    content = models.TextField(
        verbose_name="Inhalt (Markdown unterstützt)",
        help_text="Sie können Markdown verwenden: **fett**, *kursiv*, `code`, [Link](url), etc.",
    )
    is_active = models.BooleanField(default=True, verbose_name="Aktiv")

    # Metadata
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Erstellt am")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="Aktualisiert am")
    created_by = models.CharField(
        max_length=100, null=True, blank=True, verbose_name="Erstellt von"
    )
    updated_by = models.CharField(
        max_length=100, null=True, blank=True, verbose_name="Aktualisiert von"
    )

    class Meta:
        verbose_name = "Hilfs-Infobox"
        verbose_name_plural = "Hilfs-Infoboxen"
        ordering = ["page_key"]

    def __str__(self):
        return f"{self.get_page_key_display()}: {self.title}"

    @classmethod
    def get_help_for_page(cls, page_key):
        """Hole die aktive Hilfs-Infobox für eine bestimmte Seite"""
        try:
            return cls.objects.get(page_key=page_key, is_active=True)
        except cls.DoesNotExist:
            return None

