import os
import requests
import csv
import io
from datetime import datetime
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.db.models import Q, Sum, Count, Avg, Value, IntegerField, DecimalField, F
from django.db.models.functions import Coalesce, Cast, Replace, NullIf
from decimal import Decimal
import time
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.utils import timezone
from rest_framework.response import Response
from rest_framework.decorators import api_view
from django.conf import settings
from .models import Person, Paechter, Destinataer, DokumentLink, Foerderung, Land, CSVImport, LandAbrechnung, LandVerpachtung, AppConfiguration, DestinataerUnterstuetzung, UnterstuetzungWiederkehrend
import json

# Lazy import for PDF generator to avoid startup errors
def get_pdf_generator():
    """Lazy load PDF generator to handle missing dependencies gracefully"""
    try:
        from .utils.pdf_generator import pdf_generator
        return pdf_generator
    except ImportError as e:
        # Return a mock generator if dependencies are missing
        class MockPDFGenerator:
            def is_available(self):
                return False
            def export_data_list_pdf(self, *args, **kwargs):
                from django.http import HttpResponse
                error_html = f"""
                <!DOCTYPE html>
                <html>
                <head><title>PDF Not Available</title></head>
                <body>
                    <h1>PDF Export Not Available</h1>
                    <p>PDF generation requires additional system dependencies that are not installed.</p>
                    <p>Error: {str(e)}</p>
                    <p>Please install WeasyPrint dependencies or use CSV export instead.</p>
                </body>
                </html>
                """
                response = HttpResponse(error_html, content_type='text/html')
                response['Content-Disposition'] = 'inline; filename="pdf_not_available.html"'
                return response
        return MockPDFGenerator()

class GrampsClient:
    """Lightweight client for Gramps Web API."""
    def __init__(self, base_url: str, token: str = '', username: str = '', password: str = ''):
        self.base_url = base_url.rstrip('/')
        self.session = requests.Session()
        if token:
            self.session.headers.update({"Authorization": f"Bearer {token}"})
        self.username = username
        self.password = password
        self._cached_token = token

    def search_people(self, query: str, limit: int = 5):
        try:
            r = self.session.get(f"{self.base_url}/api/people/", params={"q": query, "limit": limit}, timeout=10)
            r.raise_for_status()
            return r.json()
        except Exception as e:
            # try login-once if unauthorized and we have credentials
            if self.username and self.password and '401' in str(e):
                if self._login():
                    return self.search_people(query, limit)
            return {"error": str(e)}

    def get_person(self, handle_or_id: str):
        try:
            r = self.session.get(f"{self.base_url}/api/people/{handle_or_id}", timeout=10)
            r.raise_for_status()
            return r.json()
        except Exception as e:
            if self.username and self.password and '401' in str(e):
                if self._login():
                    return self.get_person(handle_or_id)
            return {"error": str(e)}

    def _login(self) -> bool:
        try:
            # try common endpoints
            endpoints = [
                ("/api/auth/login", {"username": self.username, "password": self.password}, "json"),
                ("/auth/login", {"username": self.username, "password": self.password}, "json"),
                ("/api/token", {"username": self.username, "password": self.password}, "form"),
                ("/login", {"username": self.username, "password": self.password}, "form"),
                ("/token", {"username": self.username, "password": self.password}, "form"),
                ("/api/login", {"username": self.username, "password": self.password}, "json"),
            ]
            for path, payload, mode in endpoints:
                url = f"{self.base_url}{path}"
                if mode == 'json':
                    r = self.session.post(url, json=payload, timeout=10, allow_redirects=False)
                else:
                    r = self.session.post(url, data=payload, timeout=10, allow_redirects=False)
                # Success with token body
                if r.status_code in (200, 201) and 'application/json' in r.headers.get('Content-Type',''):
                    data = r.json()
                    token = data.get('access_token') or data.get('token') or data.get('access') or data.get('jwt')
                    if token:
                        self._cached_token = token
                        self.session.headers.update({"Authorization": f"Bearer {token}"})
                        return True
                # Success via session cookie and redirect
                if r.status_code in (200, 302) and ('set-cookie' in {k.lower():v for k,v in r.headers.items()}):
                    return True
            # Basic Auth fallback (some setups protect API with Basic)
            try:
                self.session.auth = (self.username, self.password)
                r = self.session.get(f"{self.base_url}/api/people/?limit=1", timeout=10)
                if r.status_code == 200:
                    return True
            except Exception:
                pass
            return False
        except Exception:
            return False

def get_gramps_client() -> GrampsClient:
    return GrampsClient(
        getattr(settings, 'GRAMPS_URL', ''),
        getattr(settings, 'GRAMPS_API_TOKEN', ''),
        getattr(settings, 'GRAMPS_USERNAME', ''),
        getattr(settings, 'GRAMPS_PASSWORD', ''),
    )

@api_view(['GET'])
def gramps_debug_api(_request):
    return Response({
        'GRAMPS_URL': getattr(settings, 'GRAMPS_URL', ''),
        'has_username': bool(getattr(settings, 'GRAMPS_USERNAME', '')),
        'has_password': bool(getattr(settings, 'GRAMPS_PASSWORD', '')),
    })

from .forms import PersonForm, PaechterForm, DestinataerForm, DokumentLinkForm, FoerderungForm, UnterstuetzungForm, UnterstuetzungMarkAsPaidForm, LandForm, DestinataerUnterstuetzungForm, DestinataerNotizForm
from stiftung.models import DestinataerUnterstuetzung, DestinataerNotiz

def home(request):
    """Home page for the Stiftungsverwaltung application"""
    return render(request, 'stiftung/home.html', {
        'title': 'Stiftungsverwaltung',
        'description': 'Foundation Management System'
    })

@login_required
def dokument_management(request):
    """Dokumentenverwaltung: zeigt Paperless-Dokumente (mit Stiftung-Tags) und bestehende Verknüpfungen.
    Bietet Filter und ermöglicht Re-Linking.
    """
    return render(request, 'stiftung/dokument_management.html')

@api_view(['GET'])
def paperless_document_redirect(_request, doc_id: int):
    """Redirects to the Paperless UI document URL and supports thumbnails if needed later."""
    from stiftung.utils.config import get_paperless_config
    
    config = get_paperless_config()
    url = config['api_url']
    if not url:
        return Response({'error': 'Paperless API not configured'}, status=400)
    base_url = url.rstrip('/api') if url.endswith('/api') else url
    return redirect(f"{base_url}/documents/{doc_id}/")

@api_view(['GET'])
def health_check(request):
    """Simple health check endpoint for deployment monitoring"""
    return JsonResponse({
        'status': 'healthy',
        'timestamp': timezone.now().isoformat(),
        'service': 'stiftung-web'
    })

## Removed duplicate paperless_ping referencing non-existent PAPERLESS_URL

# CSV Import Views
@login_required
def csv_import_list(request):
    """List all CSV import operations"""
    imports = CSVImport.objects.all().order_by('-started_at')
    
    paginator = Paginator(imports, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    context = {
        'page_obj': page_obj,
        'import_types': CSVImport.IMPORT_TYPE_CHOICES,
        'status_choices': CSVImport.STATUS_CHOICES,
    }
    return render(request, 'stiftung/csv_import_list.html', context)

@login_required
def csv_import_create(request):
    """Show CSV import form and handle file upload"""
    if request.method == 'POST':
        import_type = request.POST.get('import_type')
        csv_file = request.FILES.get('csv_file')
        
        if not csv_file or not import_type:
            messages.error(request, 'Bitte wählen Sie einen Import-Typ und eine CSV-Datei aus.')
            return redirect('stiftung:csv_import_create')
        
        if not csv_file.name.endswith('.csv'):
            messages.error(request, 'Bitte wählen Sie eine gültige CSV-Datei aus.')
            return redirect('stiftung:csv_import_create')
        
        try:
            # Create import record
            csv_import = CSVImport.objects.create(
                import_type=import_type,
                filename=csv_file.name,
                file_size=csv_file.size,
                created_by=request.user.username if request.user.is_authenticated else 'Unknown',
                status='processing'
            )
            
            # Process the CSV file
            if import_type == 'destinataere':
                result = process_destinataere_csv(csv_file, csv_import)
            elif import_type == 'paechter':
                result = process_paechter_csv(csv_file, csv_import)
            elif import_type == 'personen':
                result = process_personen_csv(csv_file, csv_import)
            elif import_type == 'laendereien':
                result = process_laendereien_csv(csv_file, csv_import)
            else:
                messages.error(request, 'Unbekannter Import-Typ.')
                csv_import.status = 'failed'
                csv_import.save()
                return redirect('stiftung:csv_import_create')
            
            # Update import record
            csv_import.total_rows = result['total_rows']
            csv_import.imported_rows = result['imported_rows']
            csv_import.failed_rows = result['failed_rows']
            csv_import.error_log = result['error_log']
            csv_import.status = result['status']
            csv_import.completed_at = timezone.now()
            csv_import.save()
            
            if result['status'] == 'completed':
                messages.success(request, f'CSV-Import erfolgreich! {result["imported_rows"]} Datensätze importiert.')
            elif result['status'] == 'partial':
                messages.warning(request, f'CSV-Import teilweise erfolgreich. {result["imported_rows"]} importiert, {result["failed_rows"]} fehlgeschlagen.')
            else:
                messages.error(request, f'CSV-Import fehlgeschlagen. {result["error_log"]}')
            
            return redirect('stiftung:csv_import_list')
            
        except Exception as e:
            messages.error(request, f'Fehler beim CSV-Import: {str(e)}')
            return redirect('stiftung:csv_import_create')
    
    context = {
        'import_types': CSVImport.IMPORT_TYPE_CHOICES,
    }
    return render(request, 'stiftung/csv_import_form.html', context)

def process_personen_csv(csv_file, csv_import):
    """Process CSV file for Personen import"""
    decoded_file = csv_file.read().decode('utf-8')
    # Handle both comma and semicolon separated files
    if ';' in decoded_file.split('\n')[0]:
        csv_data = csv.DictReader(io.StringIO(decoded_file), delimiter=';')
    else:
        csv_data = csv.DictReader(io.StringIO(decoded_file))
    
    total_rows = 0
    imported_rows = 0
    failed_rows = 0
    error_log = []
    
    for row_num, row in enumerate(csv_data, start=2):  # Start at 2 because row 1 is header
        total_rows += 1
        
        try:
            # Map CSV columns to model fields
            person_data = {
                'vorname': row.get('Vorname', '').strip(),
                'nachname': row.get('Nachname', '').strip(),
                'familienzweig': row.get('Familienzweig', 'hauptzweig').strip(),
                'email': row.get('E-Mail', '').strip() or None,
                'telefon': row.get('Telefon', '').strip() or None,
                'iban': row.get('IBAN', '').strip() or None,
                'adresse': row.get('Adresse', '').strip() or None,
                'notizen': row.get('Notizen', '').strip() or None,
                'aktiv': row.get('Aktiv', 'true').lower() == 'true',
            }
            
            # Handle date fields
            if row.get('Geburtsdatum'):
                try:
                    person_data['geburtsdatum'] = datetime.strptime(row['Geburtsdatum'], '%d.%m.%Y').date()
                except ValueError:
                    try:
                        person_data['geburtsdatum'] = datetime.strptime(row['Geburtsdatum'], '%Y-%m-%d').date()
                    except ValueError:
                        person_data['geburtsdatum'] = None
            
            # Validate required fields
            if not person_data['vorname'] or not person_data['nachname']:
                error_log.append(f"Zeile {row_num}: Vorname und Nachname sind erforderlich")
                failed_rows += 1
                continue
            
            # Check if person already exists
            existing_person = Person.objects.filter(
                vorname__iexact=person_data['vorname'],
                nachname__iexact=person_data['nachname']
            ).first()
            
            if existing_person:
                # Update existing person
                for field, value in person_data.items():
                    if value is not None:
                        setattr(existing_person, field, value)
                existing_person.save()
            else:
                # Create new person
                Person.objects.create(**person_data)
            
            imported_rows += 1
            
        except Exception as e:
            error_log.append(f"Zeile {row_num}: {str(e)}")
            failed_rows += 1
    
    # Determine status
    if failed_rows == 0:
        status = 'completed'
    elif imported_rows > 0:
        status = 'partial'
    else:
        status = 'failed'
    
    return {
        'total_rows': total_rows,
        'imported_rows': imported_rows,
        'failed_rows': failed_rows,
        'error_log': '\n'.join(error_log) if error_log else None,
        'status': status
    }

def process_destinataere_csv(csv_file, csv_import):
    """Process CSV file for Destinatäre import"""
    decoded_file = csv_file.read().decode('utf-8')
    # Handle both comma and semicolon separated files
    if ';' in decoded_file.split('\n')[0]:
        csv_data = csv.DictReader(io.StringIO(decoded_file), delimiter=';')
    else:
        csv_data = csv.DictReader(io.StringIO(decoded_file))
    
    total_rows = 0
    imported_rows = 0
    failed_rows = 0
    error_log = []
    
    for row_num, row in enumerate(csv_data, start=2):  # Start at 2 because row 1 is header
        total_rows += 1
        
        try:
            # Map CSV columns to model fields
            destinataer_data = {
                'vorname': row.get('Vorname', '').strip(),
                'nachname': row.get('Nachname', '').strip(),
                'familienzweig': row.get('Familienzweig', 'hauptzweig').strip(),
                'email': row.get('E-Mail', '').strip() or None,
                'telefon': row.get('Telefon', '').strip() or None,
                'iban': row.get('IBAN', '').strip() or None,
                'strasse': row.get('Straße', '').strip() or None,
                'plz': row.get('PLZ', '').strip() or None,
                'ort': row.get('Ort', '').strip() or None,
                'berufsgruppe': row.get('Berufsgruppe', 'andere').strip(),
                'ausbildungsstand': row.get('Ausbildungsstand', '').strip() or None,
                'institution': row.get('Institution', '').strip() or None,
                'projekt_beschreibung': row.get('Projektbeschreibung', '').strip() or None,
                'jaehrliches_einkommen': float(row.get('Jährliches_Einkommen', 0)) if row.get('Jährliches_Einkommen') else None,
                'finanzielle_notlage': row.get('Finanzielle_Notlage', 'false').lower() == 'true',
                'notizen': row.get('Notizen', '').strip() or None,
                'aktiv': row.get('Aktiv', 'true').lower() == 'true',
            }
            
            # Handle date fields
            if row.get('Geburtsdatum'):
                try:
                    destinataer_data['geburtsdatum'] = datetime.strptime(row['Geburtsdatum'], '%d.%m.%Y').date()
                except ValueError:
                    try:
                        destinataer_data['geburtsdatum'] = datetime.strptime(row['Geburtsdatum'], '%Y-%m-%d').date()
                    except ValueError:
                        destinataer_data['geburtsdatum'] = None
            
            # Validate required fields
            if not destinataer_data['vorname'] or not destinataer_data['nachname']:
                error_log.append(f"Zeile {row_num}: Vorname und Nachname sind erforderlich")
                failed_rows += 1
                continue
            
            # Check if destinataer already exists
            existing_destinataer = Destinataer.objects.filter(
                vorname__iexact=destinataer_data['vorname'],
                nachname__iexact=destinataer_data['nachname']
            ).first()
            
            if existing_destinataer:
                # Update existing destinataer
                for field, value in destinataer_data.items():
                    if value is not None:
                        setattr(existing_destinataer, field, value)
                existing_destinataer.save()
            else:
                # Create new destinataer
                Destinataer.objects.create(**destinataer_data)
            
            imported_rows += 1
            
        except Exception as e:
            error_log.append(f"Zeile {row_num}: {str(e)}")
            failed_rows += 1
    
    # Determine status
    if failed_rows == 0:
        status = 'completed'
    elif imported_rows > 0:
        status = 'partial'
    else:
        status = 'failed'
    
    return {
        'total_rows': total_rows,
        'imported_rows': imported_rows,
        'failed_rows': failed_rows,
        'error_log': '\n'.join(error_log) if error_log else None,
        'status': status
    }

def process_paechter_csv(csv_file, csv_import):
    """Process CSV file for Paechter import"""
    decoded_file = csv_file.read().decode('utf-8')
    
    # Handle both comma and semicolon separated files
    if ';' in decoded_file.split('\n')[0]:
        csv_data = csv.DictReader(io.StringIO(decoded_file), delimiter=';')
    else:
        csv_data = csv.DictReader(io.StringIO(decoded_file))
    
    total_rows = 0
    imported_rows = 0
    failed_rows = 0
    error_log = []
    
    for row_num, row in enumerate(csv_data, start=2):  # Start at 2 because row 1 is header
        total_rows += 1
        
        try:
            # Get raw values from CSV - handle both semicolon and comma separated
            # Handle BOM in column names
            vorname_raw = row.get('Vorname', '') or row.get('\ufeffVorname', '')
            nachname_raw = row.get('Nachname', '')
            personentyp_raw = row.get('Personentyp', '')
            
            # Clean up the values (remove extra whitespace but keep empty strings)
            vorname_raw = vorname_raw.strip() if vorname_raw else ''
            nachname_raw = nachname_raw.strip() if nachname_raw else ''
            personentyp_raw = personentyp_raw.strip() if personentyp_raw else ''
            
            # Debug: Log raw values and available columns
            error_log.append(f"Zeile {row_num}: Available columns: {list(row.keys())}")
            error_log.append(f"Zeile {row_num}: RAW Vorname='{vorname_raw}', Nachname='{nachname_raw}', Personentyp='{personentyp_raw}'")
            
            # Determine personentyp based on the data
            if personentyp_raw in ['Gesellschaft', 'KG', 'GbR', 'GmbH']:
                personentyp = 'gesellschaft'
            elif personentyp_raw in ['Herrn', 'Frau']:
                personentyp = 'natuerlich'
            else:
                # Fallback: analyze the Nachname to detect companies
                nachname_lower = nachname_raw.lower()
                if any(keyword in nachname_lower for keyword in ['kg', 'gbr', 'gmbh', 'ag', 'ohg', 'e.v.', 'stiftung', 'genossenschaft']):
                    personentyp = 'gesellschaft'
                else:
                    personentyp = 'natuerlich'
            
            # Handle Vorname - keep original value unless it's 'N/A'
            vorname = vorname_raw if vorname_raw and vorname_raw != 'N/A' else ''
            
            # Debug: Log processed values
            error_log.append(f"Zeile {row_num}: PROCESSED Vorname='{vorname}', Nachname='{nachname_raw}', Personentyp='{personentyp}'")
            
            paechter_data = {
                'vorname': vorname,
                'nachname': nachname_raw,
                'email': row.get('E-Mail', '').strip() or None,
                'telefon': row.get('Telefon', '').strip() or None,
                'iban': row.get('IBAN', '').strip() or None,
                'strasse': row.get('Straße', '').strip() or None,
                'plz': row.get('PLZ', '').strip() or None,
                'ort': row.get('Ort', '').strip() or None,
                'personentyp': personentyp,
                'pachtnummer': row.get('Pachtnummer', '').strip() or None,
                'landwirtschaftliche_ausbildung': row.get('Landwirtschaftliche_Ausbildung', 'false').lower() == 'true',
                'berufserfahrung_jahre': int(row.get('Berufserfahrung_Jahre', 0)) if row.get('Berufserfahrung_Jahre') else None,
                'spezialisierung': row.get('Spezialisierung', '').strip() or None,
                'notizen': row.get('Notizen', '').strip() or None,
                'aktiv': row.get('Aktiv', 'true').lower() in ['true', 'wahr', 'ja', '1'],
            }
            
            # Handle date fields
            if row.get('Geburtsdatum'):
                try:
                    paechter_data['geburtsdatum'] = datetime.strptime(row['Geburtsdatum'], '%d.%m.%Y').date()
                except ValueError:
                    try:
                        paechter_data['geburtsdatum'] = datetime.strptime(row['Geburtsdatum'], '%Y-%m-%d').date()
                    except ValueError:
                        paechter_data['geburtsdatum'] = None
            
            if row.get('Pachtbeginn_Erste'):
                try:
                    paechter_data['pachtbeginn_erste'] = datetime.strptime(row['Pachtbeginn_Erste'], '%d.%m.%Y').date()
                except ValueError:
                    try:
                        paechter_data['pachtbeginn_erste'] = datetime.strptime(row['Pachtbeginn_Erste'], '%Y-%m-%d').date()
                    except ValueError:
                        paechter_data['pachtbeginn_erste'] = None
            
            if row.get('Pachtende_Letzte'):
                try:
                    paechter_data['pachtende_letzte'] = datetime.strptime(row['Pachtende_Letzte'], '%d.%m.%Y').date()
                except ValueError:
                    try:
                        paechter_data['pachtende_letzte'] = datetime.strptime(row['Pachtende_Letzte'], '%Y-%m-%d').date()
                    except ValueError:
                        paechter_data['pachtende_letzte'] = None
            
            # Handle decimal fields
            if row.get('Pachtzins_Aktuell'):
                try:
                    paechter_data['pachtzins_aktuell'] = float(row['Pachtzins_Aktuell'])
                except ValueError:
                    paechter_data['pachtzins_aktuell'] = None
            
            # Validate required fields
            if personentyp == 'gesellschaft':
                # For companies, only Nachname is required
                if not paechter_data['nachname']:
                    error_log.append(f"Zeile {row_num}: Nachname ist für Gesellschaften erforderlich")
                    failed_rows += 1
                    continue
            else:
                # For natural persons, only Nachname is required
                if not paechter_data['nachname']:
                    error_log.append(f"Zeile {row_num}: Nachname ist für natürliche Personen erforderlich")
                    failed_rows += 1
                    continue
            
            # Check if paechter already exists
            if personentyp == 'gesellschaft':
                # For companies, search by Nachname only
                existing_paechter = Paechter.objects.filter(
                    nachname__iexact=paechter_data['nachname'],
                    personentyp='gesellschaft'
                ).first()
            else:
                # For natural persons, search by Nachname only (since Vorname can be empty)
                existing_paechter = Paechter.objects.filter(
                    nachname__iexact=paechter_data['nachname'],
                    personentyp='natuerlich'
                ).first()
            
            if existing_paechter:
                # Update existing paechter
                for field, value in paechter_data.items():
                    if value is not None:
                        setattr(existing_paechter, field, value)
                existing_paechter.save()
            else:
                # Create new paechter
                Paechter.objects.create(**paechter_data)
            
            imported_rows += 1
            
        except Exception as e:
            error_log.append(f"Zeile {row_num}: {str(e)}")
            failed_rows += 1
    
    # Determine status
    if failed_rows == 0:
        status = 'completed'
    elif imported_rows > 0:
        status = 'partial'
    else:
        status = 'failed'
    
    return {
        'total_rows': total_rows,
        'imported_rows': imported_rows,
        'failed_rows': failed_rows,
        'error_log': '\n'.join(error_log) if error_log else None,
        'status': status
    }

def process_laendereien_csv(csv_file, csv_import):
    """Process CSV file for Ländereien import"""
    decoded_file = csv_file.read().decode('utf-8')
    # Handle both comma and semicolon separated files
    if ';' in decoded_file.split('\n')[0]:
        csv_data = csv.DictReader(io.StringIO(decoded_file), delimiter=';')
    else:
        csv_data = csv.DictReader(io.StringIO(decoded_file))
    
    total_rows = 0
    imported_rows = 0
    failed_rows = 0
    error_log = []
    
    last_gemeinde = None
    for row_num, row in enumerate(csv_data, start=2):
        total_rows += 1
        
        try:
            # Build case-insensitive access helpers (strip BOM, normalize separators)
            def clean_key(key: str) -> str:
                return (key or '').replace('\ufeff', '').replace('\uFEFF', '').strip()
            normalized_row = { clean_key(k): (v or '').strip() for k, v in row.items() }
            lower_row = { clean_key(k).lower(): (v or '').strip() for k, v in row.items() }
            sanitized_row = {
                clean_key(k).lower().replace('-', '_').replace(' ', '_'): (v or '').strip()
                for k, v in row.items()
            }

            def get_val(*keys):
                # Try exact keys first, then case-insensitive
                for key in keys:
                    if key in normalized_row:
                        return normalized_row[key]
                for key in keys:
                    lk = key.lower()
                    if lk in lower_row:
                        return lower_row[lk]
                    sk = lk.replace('-', '_').replace(' ', '_')
                    if sk in sanitized_row:
                        return sanitized_row[sk]
                return ''

            def parse_float(value):
                if not value:
                    return 0
                # replace comma decimal if present
                v = value.replace('.', '').replace(',', '.') if value.count(',') == 1 and value.count('.') > 1 else value.replace(',', '.')
                try:
                    return float(v)
                except ValueError:
                    return 0

            # Map CSV columns to model fields (robust to header variants)
            lfd_nr_val = get_val('Lfd_Nr', 'lfd_nr', 'LfdNr', 'lfdnr', 'laufende_nummer', 'laufende-nummer')
            land_data = {
                'lfd_nr': lfd_nr_val,
                'ew_nummer': get_val('EW_Nummer', 'ew_nummer') or None,
                'amtsgericht': get_val('Amtsgericht', 'amtsgericht'),
                'gemeinde': get_val('Gemeinde', 'gemeinde'),
                'gemarkung': get_val('Gemarkung', 'gemarkung'),
                'flur': get_val('Flur', 'flur'),
                'flurstueck': get_val('Flurstück', 'Flurstueck', 'flurstück', 'flurstueck'),
                'groesse_qm': parse_float(get_val('Größe_qm', 'Groesse_qm', 'groesse_qm', 'größe_qm')),
                'gruenland_qm': parse_float(get_val('Grünland_qm', 'Gruenland_qm', 'gruenland_qm', 'grünland_qm')),
                'acker_qm': parse_float(get_val('Acker_qm', 'acker_qm')),
                'wald_qm': parse_float(get_val('Wald_qm', 'wald_qm')),
                'sonstiges_qm': parse_float(get_val('Sonstiges_qm', 'sonstiges_qm')),
                'verpachtete_gesamtflaeche': parse_float(get_val('Verpachtete_Gesamtfläche_qm', 'Verpachtete_Gesamtflaeche_qm', 'verpachtete_gesamtfläche_qm', 'verpachtete_gesamtflaeche_qm')),
                'verp_flaeche_aktuell': parse_float(get_val('Verp_Fläche_aktuell_qm', 'Verp_Flaeche_aktuell_qm', 'verp_flaeche_aktuell_qm', 'verp_fläche_aktuell_qm')),
                'aktiv': get_val('Aktiv', 'aktiv').lower() in ['true', 'wahr', 'ja', '1'],
                'notizen': get_val('Notizen', 'notizen') or None,
            }
            
            # Fallback for missing 'Gemeinde' -> set explicit placeholder
            if not land_data['gemeinde']:
                land_data['gemeinde'] = 'FEHLT'

            # Validate required fields
            required_fields = ['lfd_nr', 'gemeinde', 'gemarkung', 'flur', 'flurstueck']
            missing_fields = [field for field in required_fields if not land_data[field]]
            
            if missing_fields:
                # Log header diagnostics on first failure only to help debugging
                if row_num == 2:
                    error_log.append(f"Erkannte Spalten: {list(normalized_row.keys())}")
                error_log.append(f"Zeile {row_num}: Fehlende Pflichtfelder: {', '.join(missing_fields)}")
                failed_rows += 1
                continue
            
            # Check if land already exists
            existing_land = Land.objects.filter(lfd_nr=land_data['lfd_nr']).first()
            
            if existing_land:
                # Update existing land
                for field, value in land_data.items():
                    if value is not None:
                        setattr(existing_land, field, value)
                existing_land.save()
            else:
                # Create new land
                Land.objects.create(**land_data)
            
            imported_rows += 1
            if land_data['gemeinde']:
                last_gemeinde = land_data['gemeinde']
            
        except Exception as e:
            error_log.append(f"Zeile {row_num}: {str(e)}")
            failed_rows += 1
    
    # Determine status
    if failed_rows == 0:
        status = 'completed'
    elif imported_rows > 0:
        status = 'partial'
    else:
        status = 'failed'
    
    return {
        'total_rows': total_rows,
        'imported_rows': imported_rows,
        'failed_rows': failed_rows,
        'error_log': '\n'.join(error_log) if error_log else None,
        'status': status
    }

# Person Views
@login_required
def person_list(request):
    search_query = request.GET.get('search', '')
    familienzweig_filter = request.GET.get('familienzweig', '')
    aktiv_filter = request.GET.get('aktiv', '')
    
    persons = Person.objects.all()
    
    if search_query:
        persons = persons.filter(
            Q(nachname__icontains=search_query) |
            Q(vorname__icontains=search_query) |
            Q(email__icontains=search_query) |
            Q(familienzweig__icontains=search_query)
        )
    
    if familienzweig_filter:
        persons = persons.filter(familienzweig=familienzweig_filter)
    
    if aktiv_filter == 'true':
        persons = persons.filter(aktiv=True)
    elif aktiv_filter == 'false':
        persons = persons.filter(aktiv=False)
    
    # Annotate with total funding
    persons = persons.annotate(total_foerderungen=Sum('foerderung__betrag'))
    
    paginator = Paginator(persons, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    context = {
        'page_obj': page_obj,
        'search_query': search_query,
        'familienzweig_filter': familienzweig_filter,
        'aktiv_filter': aktiv_filter,
        'familienzweig_choices': Person.FAMILIENZWIG_CHOICES,
    }
    return render(request, 'stiftung/person_list.html', context)

@login_required
def person_detail(request, pk):
    person = get_object_or_404(Person, pk=pk)
    foerderungen = person.foerderung_set.all().order_by('-jahr', '-betrag')
    # Get new LandVerpachtungen for this person's Paechter instances
    verpachtungen = LandVerpachtung.objects.filter(paechter__person=person).order_by('-pachtbeginn')
    
    context = {
        'person': person,
        'foerderungen': foerderungen,
        'verpachtungen': verpachtungen,
    }
    return render(request, 'stiftung/person_detail.html', context)

@login_required
def person_create(request):
    if request.method == 'POST':
        form = PersonForm(request.POST)
        if form.is_valid():
            person = form.save()
            messages.success(request, f'Person "{person.get_full_name()}" wurde erfolgreich erstellt.')
            return redirect('stiftung:person_detail', pk=person.pk)
    else:
        form = PersonForm()
    
    context = {'form': form, 'title': 'Neue Person erstellen'}
    return render(request, 'stiftung/person_form.html', context)

@login_required
def person_update(request, pk):
    person = get_object_or_404(Person, pk=pk)
    if request.method == 'POST':
        form = PersonForm(request.POST, instance=person)
        if form.is_valid():
            person = form.save()
            messages.success(request, f'Person "{person.get_full_name()}" wurde erfolgreich aktualisiert.')
            return redirect('stiftung:person_detail', pk=person.pk)
    else:
        form = PersonForm(instance=person)
    
    context = {'form': form, 'person': person, 'title': f'Person bearbeiten: {person.get_full_name()}'}
    return render(request, 'stiftung/person_form.html', context)

@login_required
def person_delete(request, pk):
    person = get_object_or_404(Person, pk=pk)
    if request.method == 'POST':
        person.delete()
        messages.success(request, f'Person "{person.get_full_name()}" wurde erfolgreich gelöscht.')
        return redirect('stiftung:person_list')
    
    context = {'person': person}
    return render(request, 'stiftung/person_confirm_delete.html', context)

# Destinatär Views (Förderungsempfänger)
@login_required
def destinataer_list(request):
    search_query = request.GET.get('search', '')
    familienzweig_filter = request.GET.get('familienzweig', '')
    berufsgruppe_filter = request.GET.get('berufsgruppe', '')
    aktiv_filter = request.GET.get('aktiv', '')
    sort = request.GET.get('sort', '')
    direction = request.GET.get('dir', 'asc')
    
    destinataere = Destinataer.objects.all()
    
    if search_query:
        destinataere = destinataere.filter(
            Q(nachname__icontains=search_query) |
            Q(vorname__icontains=search_query) |
            Q(email__icontains=search_query) |
            Q(institution__icontains=search_query) |
            Q(familienzweig__icontains=search_query)
        )
    
    if familienzweig_filter:
        destinataere = destinataere.filter(familienzweig=familienzweig_filter)
    
    if berufsgruppe_filter:
        destinataere = destinataere.filter(berufsgruppe=berufsgruppe_filter)
    
    if aktiv_filter == 'true':
        destinataere = destinataere.filter(aktiv=True)
    elif aktiv_filter == 'false':
        destinataere = destinataere.filter(aktiv=False)
    
    # Annotate with total funding (coalesce nulls to Decimal for stable sorting)
    destinataere = destinataere.annotate(
        total_foerderungen=Coalesce(
            Sum('foerderung__betrag'),
            Value(Decimal('0.00'), output_field=DecimalField(max_digits=12, decimal_places=2)),
            output_field=DecimalField(max_digits=12, decimal_places=2),
        )
    )

    # Sorting
    sort_map = {
        'name': ['nachname', 'vorname'],
        'familienzweig': ['familienzweig'],
        'berufsgruppe': ['berufsgruppe'],
        'institution': ['institution'],
        'email': ['email'],
        'foerderungen': ['total_foerderungen'],
        'status': ['aktiv'],
    }
    if sort in sort_map:
        fields = sort_map[sort]
        if direction == 'desc':
            order_fields = [f'-{f}' for f in fields]
        else:
            order_fields = fields
        destinataere = destinataere.order_by(*order_fields)
    
    paginator = Paginator(destinataere, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    context = {
        'page_obj': page_obj,
        'search_query': search_query,
        'familienzweig_filter': familienzweig_filter,
        'berufsgruppe_filter': berufsgruppe_filter,
        'aktiv_filter': aktiv_filter,
        'familienzweig_choices': Destinataer.FAMILIENZWIG_CHOICES,
        'berufsgruppe_choices': Destinataer.BERUFSGRUPPE_CHOICES,
        'sort': sort,
        'dir': direction,
    }
    return render(request, 'stiftung/destinataer_list.html', context)

@login_required
def destinataer_detail(request, pk):
    destinataer = get_object_or_404(Destinataer, pk=pk)
    
    # Alle mit diesem Destinatär verknüpften Dokumente laden
    verknuepfte_dokumente = DokumentLink.objects.filter(
        destinataer_id=destinataer.pk
    ).order_by('kontext', 'titel')
    
    # Förderungen für diesen Destinatär laden
    foerderungen = Foerderung.objects.filter(destinataer=destinataer).order_by('-jahr', '-betrag')
    
    # Unterstützungen für diesen Destinatär laden
    unterstuetzungen = DestinataerUnterstuetzung.objects.filter(destinataer=destinataer).order_by('-faellig_am')

    # Notizen laden
    notizen_eintraege = DestinataerNotiz.objects.filter(destinataer=destinataer).order_by('-erstellt_am')

    context = {
        'destinataer': destinataer,
        'verknuepfte_dokumente': verknuepfte_dokumente,
        'foerderungen': foerderungen,
        'unterstuetzungen': unterstuetzungen,
        'notizen_eintraege': notizen_eintraege,
    }
    return render(request, 'stiftung/destinataer_detail.html', context)

@login_required
def destinataer_create(request):
    if request.method == 'POST':
        form = DestinataerForm(request.POST)
        if form.is_valid():
            destinataer = form.save()
            messages.success(request, f'Destinatär "{destinataer.get_full_name()}" wurde erfolgreich erstellt.')
            return redirect('stiftung:destinataer_detail', pk=destinataer.pk)
    else:
        form = DestinataerForm()
    
    context = {'form': form, 'title': 'Neuen Destinatär erstellen'}
    return render(request, 'stiftung/destinataer_form.html', context)

@login_required
def destinataer_update(request, pk):
    destinataer = get_object_or_404(Destinataer, pk=pk)
    if request.method == 'POST':
        form = DestinataerForm(request.POST, instance=destinataer)
        if form.is_valid():
            destinataer = form.save()
            try:
                # Auto-create a Destinatärunterstützung if conditions are met
                if (
                    destinataer.aktiv
                    and destinataer.unterstuetzung_bestaetigt
                    and destinataer.standard_konto
                    and destinataer.vierteljaehrlicher_betrag
                    and destinataer.vierteljaehrlicher_betrag > 0
                ):
                    from decimal import Decimal
                    from stiftung.models import DestinataerUnterstuetzung
                    heute = timezone.now().date()
                    beschreibung = f"Vierteljährliche Vorauszahlung für {destinataer.get_full_name()}"
                    # ensure only one upcoming planned entry; update if one exists
                    existing = DestinataerUnterstuetzung.objects.filter(
                        destinataer=destinataer,
                        status='geplant'
                    ).order_by('faellig_am').first()
                    if existing:
                        existing.konto = destinataer.standard_konto
                        existing.betrag = Decimal(destinataer.vierteljaehrlicher_betrag)
                        existing.faellig_am = heute
                        existing.beschreibung = beschreibung
                        existing.save()
                    else:
                        DestinataerUnterstuetzung.objects.create(
                            destinataer=destinataer,
                            konto=destinataer.standard_konto,
                            betrag=Decimal(destinataer.vierteljaehrlicher_betrag),
                            faellig_am=heute,
                            status='geplant',
                            beschreibung=beschreibung,
                        )
            except Exception:
                pass
            messages.success(request, f'Destinatär "{destinataer.get_full_name()}" wurde erfolgreich aktualisiert.')
            return redirect('stiftung:destinataer_detail', pk=destinataer.pk)
    else:
        form = DestinataerForm(instance=destinataer)
    
    context = {'form': form, 'destinataer': destinataer, 'title': f'Destinatär bearbeiten: {destinataer.get_full_name()}'}
    return render(request, 'stiftung/destinataer_form.html', context)

@login_required
def destinataer_delete(request, pk):
    destinataer = get_object_or_404(Destinataer, pk=pk)
    if request.method == 'POST':
        destinataer.delete()
        messages.success(request, f'Destinatär "{destinataer.get_full_name()}" wurde erfolgreich gelöscht.')
        return redirect('stiftung:destinataer_list')
    
    context = {'destinataer': destinataer}
    return render(request, 'stiftung/destinataer_confirm_delete.html', context)

# Paechter Views (Landpächter)
@login_required
def paechter_list(request):
    search_query = request.GET.get('search', '')
    ausbildung_filter = request.GET.get('ausbildung', '')
    aktiv_filter = request.GET.get('aktiv', '')
    sort = request.GET.get('sort', '')
    direction = request.GET.get('dir', 'asc')
    
    paechter = Paechter.objects.all()
    
    if search_query:
        paechter = paechter.filter(
            Q(nachname__icontains=search_query) |
            Q(vorname__icontains=search_query) |
            Q(email__icontains=search_query) |
            Q(pachtnummer__icontains=search_query)
        )
    
    if ausbildung_filter == 'true':
        paechter = paechter.filter(landwirtschaftliche_ausbildung=True)
    elif ausbildung_filter == 'false':
        paechter = paechter.filter(landwirtschaftliche_ausbildung=False)
    
    if aktiv_filter == 'true':
        paechter = paechter.filter(aktiv=True)
    elif aktiv_filter == 'false':
        paechter = paechter.filter(aktiv=False)
    
    # Annotate with total leased area and rent (coalesce nulls to Decimal for stable sorting)
    paechter = paechter.annotate(
        gesamt_flaeche=Coalesce(
            Sum('neue_verpachtungen__verpachtete_flaeche'),
            Value(Decimal('0.00'), output_field=DecimalField(max_digits=12, decimal_places=2)),
            output_field=DecimalField(max_digits=12, decimal_places=2),
        ),
        gesamt_pachtzins=Coalesce(
            Sum('neue_verpachtungen__pachtzins_pauschal'),
            Value(Decimal('0.00'), output_field=DecimalField(max_digits=12, decimal_places=2)),
            output_field=DecimalField(max_digits=12, decimal_places=2)),
    )

    # Sorting
    sort_map = {
        'name': ['nachname', 'vorname'],
        'pachtnummer': ['pachtnummer'],
        'ausbildung': ['landwirtschaftliche_ausbildung'],
        'spezialisierung': ['spezialisierung'],
        'flaeche': ['gesamt_flaeche'],
        'pachtzins': ['gesamt_pachtzins'],
        'status': ['aktiv'],
    }
    if sort in sort_map:
        fields = sort_map[sort]
        if direction == 'desc':
            order_fields = [f'-{f}' for f in fields]
        else:
            order_fields = fields
        paechter = paechter.order_by(*order_fields)
    
    paginator = Paginator(paechter, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    context = {
        'page_obj': page_obj,
        'search_query': search_query,
        'ausbildung_filter': ausbildung_filter,
        'aktiv_filter': aktiv_filter,
        'sort': sort,
        'dir': direction,
    }
    return render(request, 'stiftung/paechter_list.html', context)

@login_required
def paechter_detail(request, pk):
    paechter = get_object_or_404(Paechter, pk=pk)
    
    # Alle mit diesem Pächter verknüpften Dokumente laden
    verknuepfte_dokumente = DokumentLink.objects.filter(
        paechter_id=paechter.pk
    ).order_by('kontext', 'titel')
    
    # Neue LandVerpachtungen für diesen Pächter laden
    verpachtungen = LandVerpachtung.objects.filter(paechter=paechter).order_by('-pachtbeginn')
    
    # Neue gepachtete Ländereien (über aktueller_paechter)
    gepachtete_laendereien = paechter.gepachtete_laendereien.filter(aktiv=True).order_by('gemeinde', 'gemarkung')
    
    # Statistiken berechnen
    total_flaeche_neu = sum(land.verp_flaeche_aktuell or 0 for land in gepachtete_laendereien)
    total_pachtzins_neu = sum(land.pachtzins_pauschal or 0 for land in gepachtete_laendereien)
    
    context = {
        'paechter': paechter,
        'verknuepfte_dokumente': verknuepfte_dokumente,
        'verpachtungen': verpachtungen,  # Now using LandVerpachtung
        'gepachtete_laendereien': gepachtete_laendereien,  # Neu
        'total_flaeche_neu': total_flaeche_neu,
        'total_pachtzins_neu': total_pachtzins_neu,
    }
    return render(request, 'stiftung/paechter_detail.html', context)

@login_required
def paechter_create(request):
    if request.method == 'POST':
        form = PaechterForm(request.POST)
        if form.is_valid():
            paechter = form.save()
            messages.success(request, f'Pächter "{paechter.get_full_name()}" wurde erfolgreich erstellt.')
            return redirect('stiftung:paechter_detail', pk=paechter.pk)
        else:
            # Debug: Log form errors and show them to user
            print(f"Form errors: {form.errors}")
            print(f"Form data: {request.POST}")
            messages.error(request, f'Formular-Fehler: {form.errors}')
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f'{field}: {error}')
    else:
        form = PaechterForm()
    
    context = {'form': form, 'title': 'Neuen Pächter erstellen'}
    return render(request, 'stiftung/paechter_form.html', context)

@login_required
def paechter_update(request, pk):
    paechter = get_object_or_404(Paechter, pk=pk)
    if request.method == 'POST':
        form = PaechterForm(request.POST, instance=paechter)
        if form.is_valid():
            paechter = form.save()
            messages.success(request, f'Pächter "{paechter.get_full_name()}" wurde erfolgreich aktualisiert.')
            return redirect('stiftung:paechter_detail', pk=paechter.pk)
        else:
            # Debug: Log form errors and show them to user
            print(f"Form errors: {form.errors}")
            print(f"Form data: {request.POST}")
            messages.error(request, f'Formular-Fehler: {form.errors}')
            for field, errors in form.errors.items():
                for error in errors:
                    messages.error(request, f'{field}: {error}')
    else:
        form = PaechterForm(instance=paechter)
    
    context = {'form': form, 'paechter': paechter, 'title': f'Pächter bearbeiten: {paechter.get_full_name()}'}
    return render(request, 'stiftung/paechter_form.html', context)

@login_required
def paechter_delete(request, pk):
    paechter = get_object_or_404(Paechter, pk=pk)
    if request.method == 'POST':
        paechter.delete()
        messages.success(request, f'Pächter "{paechter.get_full_name()}" wurde erfolgreich gelöscht.')
        return redirect('stiftung:paechter_list')
    
    context = {'paechter': paechter}
    return render(request, 'stiftung/paechter_confirm_delete.html', context)

# Land Views
@login_required
def land_list(request):
    search_query = request.GET.get('search', '')
    gemeinde_filter = request.GET.get('gemeinde', '')
    aktiv_filter = request.GET.get('aktiv', '')
    sort = request.GET.get('sort', '')
    direction = request.GET.get('dir', 'asc')
    
    lands = Land.objects.all()
    
    if search_query:
        lands = lands.filter(
            Q(lfd_nr__icontains=search_query) |
            Q(gemeinde__icontains=search_query) |
            Q(gemarkung__icontains=search_query) |
            Q(flur__icontains=search_query) |
            Q(flurstueck__icontains=search_query)
        )
    
    if gemeinde_filter:
        lands = lands.filter(gemeinde=gemeinde_filter)
    
    if aktiv_filter == 'true':
        lands = lands.filter(aktiv=True)
    elif aktiv_filter == 'false':
        lands = lands.filter(aktiv=False)
    
    # Annotate with verpachtungsgrad and numeric casts for natural sorting
    # Prepare numeric versions of textual fields by stripping common non-digits
    def digits_only(field_expr):
        expr = Replace(field_expr, Value(' '), Value(''))
        expr = Replace(expr, Value('-'), Value(''))
        expr = Replace(expr, Value('.'), Value(''))
        expr = Replace(expr, Value('/'), Value(''))
        expr = Replace(expr, Value('L'), Value(''))
        return expr

    lands = lands.extra(
        select={'verpachtungsgrad': 'CASE WHEN groesse_qm > 0 THEN (verp_flaeche_aktuell / groesse_qm) * 100 ELSE 0 END'}
    ).annotate(
        lfd_nr_num=Cast(NullIf(digits_only(F('lfd_nr')), Value('')), IntegerField()),
        flur_num=Cast(NullIf(digits_only(F('flur')), Value('')), IntegerField()),
        flurstueck_num=Cast(NullIf(digits_only(F('flurstueck')), Value('')), IntegerField()),
    )

    # Sorting
    sort_map = {
        'lfd_nr': ['lfd_nr_num', 'lfd_nr'],
        'gemeinde': ['gemeinde'],
        'gemarkung': ['gemarkung'],
        'flur': ['flur_num', 'flur'],
        'flurstueck': ['flurstueck_num', 'flurstueck'],
        'groesse': ['groesse_qm'],
        'verp': ['verp_flaeche_aktuell'],
        'grad': ['verpachtungsgrad'],
    }
    if sort in sort_map:
        fields = sort_map[sort]
        if direction == 'desc':
            order_fields = [f'-{f}' for f in fields]
        else:
            order_fields = fields
        lands = lands.order_by(*order_fields)

    # Aggregated statistics for current filter set
    aggregates = lands.aggregate(
        sum_groesse_qm=Sum('groesse_qm'),
        sum_gruenland_qm=Sum('gruenland_qm'),
        sum_acker_qm=Sum('acker_qm'),
        sum_wald_qm=Sum('wald_qm'),
        sum_sonstiges_qm=Sum('sonstiges_qm'),
    )
    sum_gruenland_qm = float(aggregates.get('sum_gruenland_qm') or 0)
    sum_acker_qm = float(aggregates.get('sum_acker_qm') or 0)
    sum_wald_qm = float(aggregates.get('sum_wald_qm') or 0)
    sum_sonstiges_qm = float(aggregates.get('sum_sonstiges_qm') or 0)
    sum_total_use_qm = sum_gruenland_qm + sum_acker_qm + sum_wald_qm + sum_sonstiges_qm
    def pct(part, total):
        return round((part / total) * 100, 1) if total and part is not None else 0.0
    stats = {
        'sum_gruenland_qm': sum_gruenland_qm,
        'sum_acker_qm': sum_acker_qm,
        'sum_wald_qm': sum_wald_qm,
        'sum_sonstiges_qm': sum_sonstiges_qm,
        'sum_total_use_qm': sum_total_use_qm,
        'pct_gruenland': pct(sum_gruenland_qm, sum_total_use_qm),
        'pct_acker': pct(sum_acker_qm, sum_total_use_qm),
        'pct_wald': pct(sum_wald_qm, sum_total_use_qm),
    }

    # Prepare size chart data (top 30 by size)
    top_sizes = list(
        lands.order_by('-groesse_qm').values_list('lfd_nr', 'groesse_qm')[:30]
    )
    size_chart_labels = [label or '' for label, _ in top_sizes]
    size_chart_values = [float(val or 0) for _, val in top_sizes]
    
    paginator = Paginator(lands, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    # Get unique gemeinden for filter
    gemeinden = Land.objects.values_list('gemeinde', flat=True).distinct().order_by('gemeinde')
    
    context = {
        'page_obj': page_obj,
        'search_query': search_query,
        'gemeinde_filter': gemeinde_filter,
        'aktiv_filter': aktiv_filter,
        'gemeinden': gemeinden,
        'stats': stats,
        'size_chart_labels_json': json.dumps(size_chart_labels),
        'size_chart_values_json': json.dumps(size_chart_values),
        'sort': sort,
        'dir': direction,
    }
    return render(request, 'stiftung/land_list.html', context)

@login_required
def land_detail(request, pk):
    land = get_object_or_404(Land, pk=pk)
    
    # Alle mit dieser Länderei verknüpften Dokumente laden
    verknuepfte_dokumente = DokumentLink.objects.filter(
        land_id=land.pk
    ).order_by('kontext', 'titel')
    
    # Neue LandVerpachtungen laden (mit related data)
    neue_verpachtungen = land.neue_verpachtungen.select_related('paechter').order_by('-pachtbeginn')
    
    context = {
        'land': land,
        'verknuepfte_dokumente': verknuepfte_dokumente,
        'verpachtungen': neue_verpachtungen,  # Using only new system now
        'neue_verpachtungen': neue_verpachtungen,
    }
    return render(request, 'stiftung/land_detail.html', context)

@login_required
def land_create(request):
    if request.method == 'POST':
        form = LandForm(request.POST)
        if form.is_valid():
            land = form.save()
            messages.success(request, f'Länderei "{land}" wurde erfolgreich erstellt.')
            return redirect('stiftung:land_detail', pk=land.pk)
    else:
        form = LandForm()
    
    context = {'form': form, 'title': 'Neue Länderei erstellen'}
    return render(request, 'stiftung/land_form.html', context)

@login_required
def land_update(request, pk):
    land = get_object_or_404(Land, pk=pk)
    if request.method == 'POST':
        form = LandForm(request.POST, instance=land)
        if form.is_valid():
            land = form.save()
            messages.success(request, f'Länderei "{land}" wurde erfolgreich aktualisiert.')
            return redirect('stiftung:land_detail', pk=land.pk)
    else:
        form = LandForm(instance=land)
    
    context = {'form': form, 'land': land, 'title': f'Länderei bearbeiten: {land}'}
    return render(request, 'stiftung/land_form.html', context)

@login_required
def land_delete(request, pk):
    land = get_object_or_404(Land, pk=pk)
    if request.method == 'POST':
        land.delete()
        messages.success(request, f'Länderei "{land}" wurde erfolgreich gelöscht.')
        return redirect('stiftung:land_list')
    
    context = {'land': land}
    return render(request, 'stiftung/land_confirm_delete.html', context)

# Verpachtung Views
@login_required
def verpachtung_list(request):
    search_query = request.GET.get('search', '')
    status_filter = request.GET.get('status', '')
    gemeinde_filter = request.GET.get('gemeinde', '')
    sort = request.GET.get('sort', '')
    direction = request.GET.get('dir', 'asc')
    
    verpachtungen = LandVerpachtung.objects.select_related('land', 'paechter').all()
    
    if search_query:
        verpachtungen = verpachtungen.filter(
            Q(vertragsnummer__icontains=search_query) |
            Q(land__gemeinde__icontains=search_query) |
            Q(paechter__nachname__icontains=search_query) |
            Q(paechter__vorname__icontains=search_query)
        )
    
    if status_filter:
        verpachtungen = verpachtungen.filter(status=status_filter)
    
    if gemeinde_filter:
        verpachtungen = verpachtungen.filter(land__gemeinde=gemeinde_filter)
    
    # Sorting
    sort_map = {
        'vertragsnummer': ['vertragsnummer'],
        'land': ['land__gemeinde'],
        'paechter': ['paechter__nachname', 'paechter__vorname'],
        'beginn': ['pachtbeginn'],
        'ende': ['pachtende'],
        'flaeche': ['verpachtete_flaeche'],
        'pachtzins': ['pachtzins_jaehrlich'],
        'status': ['status'],
    }
    if sort in sort_map:
        fields = sort_map[sort]
        if direction == 'desc':
            order_fields = [f'-{f}' for f in fields]
        else:
            order_fields = fields
        verpachtungen = verpachtungen.order_by(*order_fields)
    
    paginator = Paginator(verpachtungen, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    # Calculate statistics for the summary cards
    # Get ALL verpachtungen (not filtered) for accurate statistics
    all_verpachtungen = LandVerpachtung.objects.select_related('land', 'paechter').all()
    
    # Active verpachtungen count
    aktive_verpachtungen = all_verpachtungen.filter(status='aktiv').count()
    
    # Total leased area (only active verpachtungen)
    gesamt_flaeche_result = all_verpachtungen.filter(status='aktiv').aggregate(
        total=Sum('verpachtete_flaeche')
    )
    gesamt_flaeche = gesamt_flaeche_result['total'] if gesamt_flaeche_result['total'] is not None else 0
    
    # Total annual rent (only active verpachtungen)
    jaehrlicher_pachtzins_result = all_verpachtungen.filter(status='aktiv').aggregate(
        total=Sum('pachtzins_jaehrlich')
    )
    jaehrlicher_pachtzins = jaehrlicher_pachtzins_result['total'] if jaehrlicher_pachtzins_result['total'] is not None else 0
    
    # Total count of all verpachtungen
    anzahl_verpachtungen = all_verpachtungen.count()
    
    # Get unique gemeinden and statuses for filters
    gemeinden = Land.objects.values_list('gemeinde', flat=True).distinct().order_by('gemeinde')
    status_choices = Verpachtung.STATUS_CHOICES
    
    context = {
        'page_obj': page_obj,
        'search_query': search_query,
        'status_filter': status_filter,
        'gemeinde_filter': gemeinde_filter,
        'gemeinden': gemeinden,
        'status_choices': status_choices,
        # Statistics for summary cards
        'aktive_verpachtungen': aktive_verpachtungen,
        'gesamt_flaeche': gesamt_flaeche,
        'jaehrlicher_pachtzins': jaehrlicher_pachtzins,
        'anzahl_verpachtungen': anzahl_verpachtungen,
        'sort': sort,
        'dir': direction,
    }
    return render(request, 'stiftung/verpachtung_list.html', context)

@login_required
@login_required
def land_verpachtung_detail(request, pk):
    """Detail view for LandVerpachtung"""
    verpachtung = get_object_or_404(LandVerpachtung, pk=pk)
    
    # Alle mit dieser Verpachtung verknüpften Dokumente laden
    verknuepfte_dokumente = DokumentLink.objects.filter(
        land_verpachtung_id=verpachtung.pk
    ).order_by('kontext', 'titel')
    
    context = {
        'verpachtung': verpachtung,
        'landverpachtung': verpachtung,  # Template expects this variable name
        'verknuepfte_dokumente': verknuepfte_dokumente,
    }
    return render(request, 'stiftung/land_verpachtung_detail.html', context)

@login_required
def land_verpachtung_update(request, pk):
    """Update an existing LandVerpachtung by its primary key"""
    verpachtung = get_object_or_404(LandVerpachtung, pk=pk)
    
    if request.method == 'POST':
        # Handle the update form submission
        vertragsnummer = request.POST.get('vertragsnummer')
        pachtbeginn = request.POST.get('pachtbeginn')
        pachtende = request.POST.get('pachtende')
        pachtzins_jaehrlich = request.POST.get('pachtzins_jaehrlich')
        
        if vertragsnummer:
            verpachtung.vertragsnummer = vertragsnummer
        if pachtbeginn:
            verpachtung.pachtbeginn = pachtbeginn
        if pachtende:
            verpachtung.pachtende = pachtende
        if pachtzins_jaehrlich:
            verpachtung.pachtzins_jaehrlich = pachtzins_jaehrlich
            
        verpachtung.save()
        messages.success(request, 'Verpachtung wurde erfolgreich aktualisiert.')
        return redirect('stiftung:land_verpachtung_detail', pk=verpachtung.pk)
    
    context = {
        'verpachtung': verpachtung,
        'landverpachtung': verpachtung,  # Template expects this variable name
        'is_edit': True,
        'is_update': True,  # Form template uses this flag
    }
    return render(request, 'stiftung/land_verpachtung_form.html', context)

@login_required  
def land_verpachtung_end_direct(request, pk):
    """End a LandVerpachtung directly by its primary key"""
    verpachtung = get_object_or_404(LandVerpachtung, pk=pk)
    
    if request.method == 'POST':
        verpachtung.status = 'beendet'
        verpachtung.pachtende = timezone.now().date()
        verpachtung.save()
        messages.success(request, 'Verpachtung wurde erfolgreich beendet.')
        return redirect('stiftung:land_detail', pk=verpachtung.land.pk)
    
    context = {
        'verpachtung': verpachtung,
    }
    return render(request, 'stiftung/land_verpachtung_end_confirm.html', context)

# Förderung Views
@login_required
def foerderung_list(request):
    """List all funding grants with filtering and pagination"""
    foerderungen = Foerderung.objects.select_related('destinataer', 'verwendungsnachweis').all()
    
    # Check for export request - handle both GET and POST
    export_format = request.POST.get('format') if request.method == 'POST' else request.GET.get('format', '')
    selected_ids_param = request.POST.get('selected_entries', '') if request.method == 'POST' else request.GET.get('selected_entries', '')
    selected_ids = [id for id in selected_ids_param.split(',') if id] if selected_ids_param else []
    
    # Filtering
    jahr = request.GET.get('jahr')
    kategorie = request.GET.get('kategorie')
    status = request.GET.get('status')
    destinataer = request.GET.get('destinataer')
    
    if jahr:
        foerderungen = foerderungen.filter(jahr=int(jahr))
    if kategorie:
        foerderungen = foerderungen.filter(kategorie=kategorie)
    if status:
        foerderungen = foerderungen.filter(status=status)
    if destinataer:
        foerderungen = foerderungen.filter(destinataer__nachname__icontains=destinataer)
    
    # Handle exports
    if export_format == 'csv':
        return export_foerderungen_csv(request, foerderungen, selected_ids)
    elif export_format == 'pdf':
        return export_foerderungen_pdf(request, foerderungen, selected_ids)
    
    # Pagination
    paginator = Paginator(foerderungen, 25)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    # Statistics
    total_betrag = foerderungen.aggregate(total=Sum('betrag'))['total'] or 0
    avg_betrag = foerderungen.aggregate(avg=Avg('betrag'))['avg'] or 0
    
    # Year choices for filters
    jahre = sorted(set(
        list(Foerderung.objects.values_list('jahr', flat=True))
    ), reverse=True)

    context = {
        'page_obj': page_obj,
        'foerderungen': foerderungen,  # Add for counting
        'total_betrag': total_betrag,
        'avg_betrag': avg_betrag,
        'kategorien': Foerderung.KATEGORIE_CHOICES,
        'status_choices': Foerderung.STATUS_CHOICES,
        'filter_jahr': jahr,
        'filter_kategorie': kategorie,
        'filter_status': status,
        'filter_person': destinataer,
        'jahre': jahre,
    }
    return render(request, 'stiftung/foerderung_list.html', context)

@login_required
def foerderung_detail(request, pk):
    """Show details of a specific funding grant"""
    foerderung = get_object_or_404(Foerderung.objects.select_related('person', 'verwendungsnachweis'), pk=pk)
    
    # Alle mit dieser Förderung verknüpften Dokumente laden
    verknuepfte_dokumente = DokumentLink.objects.filter(
        foerderung_id=foerderung.pk
    ).order_by('kontext', 'titel')
    
    context = {
        'foerderung': foerderung,
        'verknuepfte_dokumente': verknuepfte_dokumente,
        'title': f'Förderung: {foerderung}',
    }
    return render(request, 'stiftung/foerderung_detail.html', context)

@login_required
def foerderung_create(request):
    """Create a new funding grant"""
    # Get destinataer from URL parameter if provided
    destinataer_id = request.GET.get('destinataer')
    initial = {}
    if destinataer_id:
        initial['destinataer'] = destinataer_id
    
    if request.method == 'POST':
        form = FoerderungForm(request.POST)
        if form.is_valid():
            foerderung = form.save()
            messages.success(request, f'Förderung für {foerderung.destinataer} wurde erfolgreich erstellt.')
            return redirect('stiftung:foerderung_detail', pk=foerderung.pk)
    else:
        form = FoerderungForm(initial=initial)
    
    context = {
        'form': form,
        'title': 'Neue Förderung erstellen',
    }
    return render(request, 'stiftung/foerderung_form.html', context)

@login_required
def foerderung_update(request, pk):
    """Update an existing funding grant"""
    foerderung = get_object_or_404(Foerderung, pk=pk)
    
    if request.method == 'POST':
        form = FoerderungForm(request.POST, instance=foerderung)
        if form.is_valid():
            form.save()
            messages.success(request, f'Förderung für {foerderung.person} wurde erfolgreich aktualisiert.')
            return redirect('stiftung:foerderung_detail', pk=foerderung.pk)
    else:
        form = FoerderungForm(instance=foerderung)
    
    context = {
        'form': form,
        'foerderung': foerderung,
        'title': f'Förderung bearbeiten: {foerderung}',
    }
    return render(request, 'stiftung/foerderung_form.html', context)

@login_required
def foerderung_delete(request, pk):
    """Delete a funding grant"""
    foerderung = get_object_or_404(Foerderung, pk=pk)
    
    if request.method == 'POST':
        # Get the recipient name before deletion
        recipient_name = foerderung.destinataer.get_full_name() if foerderung.destinataer else (
            foerderung.person.get_full_name() if foerderung.person else "Unbekannter Empfänger"
        )
        
        foerderung.delete()
        messages.success(request, f'Förderung für {recipient_name} wurde erfolgreich gelöscht.')
        return redirect('stiftung:foerderung_list')
    
    context = {
        'foerderung': foerderung,
        'title': f'Förderung löschen: {foerderung}',
    }
    return render(request, 'stiftung/foerderung_confirm_delete.html', context)

# DokumentLink Views
@login_required
def dokument_list(request):
    """Zeigt alle verknüpften Dokumente an"""
    # Alle verknüpften Dokumente laden
    dokumente = DokumentLink.objects.all().order_by('-id')
    
    # Paperless-API-Konfiguration für verfügbare Dokumente
    from stiftung.utils.config import get_paperless_config
    import requests
    
    config = get_paperless_config()
    url = config['api_url']
    token = config['api_token']
    
    available_dokumente = []
    if url and token:
        try:
            base_url = url.rstrip('/api') if url.endswith('/api') else url
            headers = {'Authorization': f'Token {token}'}
            
            # Alle verfügbaren Dokumente abrufen (mit Paginierung)
            all_dokumente = []
            page = 1
            page_size = 100
            
            while True:
                response = requests.get(f"{base_url}/api/documents/?page={page}&page_size={page_size}", headers=headers, timeout=10)
                response.raise_for_status()
                data = response.json()
                
                all_dokumente.extend(data.get('results', []))
                
                if not data.get('next'):
                    break
                page += 1
            
            # Stiftung-Dokumente filtern
            for doc in all_dokumente:
                try:
                    tags = []
                    doc_tags = doc.get('tags', [])
                    
                    if isinstance(doc_tags, list):
                        for tag in doc_tags:
                            if isinstance(tag, dict) and 'name' in tag:
                                tags.append(tag['name'])
                            elif isinstance(tag, str):
                                tags.append(tag)
                            elif isinstance(tag, int):
                                tags.append(f"Tag_{tag}")
                    elif isinstance(doc_tags, str):
                        tags = [tag.strip() for tag in doc_tags.split(',')]
                    
                    if any(tag in [config['destinataere_tag'], config['land_tag'], config['admin_tag']] for tag in tags):
                        bereits_verknuepft = DokumentLink.objects.filter(
                            paperless_document_id=doc['id']
                        ).exists()
                        
                        if not bereits_verknuepft:
                            available_dokumente.append({
                                'id': doc['id'],
                                'title': doc.get('title', f'Dokument {doc["id"]}'),
                                'created_date': doc.get('created_date', ''),
                                'tags': tags,
                                'thumbnail_url': f"{base_url}/api/documents/{doc['id']}/thumb/",
                                'document_url': f"{base_url}/documents/{doc['id']}/",
                            })
                except Exception:
                    continue
            
            # Nach Erstellungsdatum sortieren
            available_dokumente.sort(key=lambda x: x['created_date'], reverse=True)
            
        except Exception:
            pass
    
    context = {
        'dokumente': dokumente,
        'available_dokumente': available_dokumente,
        'title': 'Alle verknüpften Dokumente',
    }
    return render(request, 'stiftung/dokument_list.html', context)

@login_required
def dokument_detail(request, pk):
    """Show details of a specific document link"""
    dokument = get_object_or_404(DokumentLink, pk=pk)
    
    context = {
        'dokument': dokument,
        'title': f'Dokument: {dokument}',
    }
    return render(request, 'stiftung/dokument_detail.html', context)

@login_required
def dokument_create(request):
    """Create a new document link"""
    if request.method == 'POST':
        form = DokumentLinkForm(request.POST)
        if form.is_valid():
            dokument = form.save()
            messages.success(request, f'Dokument "{dokument.titel}" wurde erfolgreich verknüpft.')
            
            # Zurück zur verknüpften Entität leiten
            if dokument.verpachtung_id:
                return redirect('stiftung:verpachtung_detail', pk=dokument.verpachtung_id)
            elif dokument.land_id:
                return redirect('stiftung:land_detail', pk=dokument.land_id)
            elif dokument.paechter_id:
                return redirect('stiftung:paechter_detail', pk=dokument.paechter_id)
            elif dokument.destinataer_id:
                return redirect('stiftung:destinataer_detail', pk=dokument.destinataer_id)
            elif dokument.foerderung_id:
                return redirect('stiftung:foerderung_detail', pk=dokument.foerderung_id)
            else:
                return redirect('stiftung:dokument_detail', pk=dokument.pk)
    else:
        # Initial-Werte aus GET-Parametern setzen
        initial_data = {}
        if request.GET.get('verpachtung'):
            initial_data['verpachtung_id'] = request.GET.get('verpachtung')
        if request.GET.get('land'):
            initial_data['land_id'] = request.GET.get('land')
        if request.GET.get('paechter'):
            initial_data['paechter_id'] = request.GET.get('paechter')
        if request.GET.get('destinataer'):
            initial_data['destinataer_id'] = request.GET.get('destinataer')
        if request.GET.get('foerderung'):
            initial_data['foerderung_id'] = request.GET.get('foerderung')
        
        form = DokumentLinkForm(initial=initial_data)
    
    context = {
        'form': form,
        'title': 'Neues Dokument verknüpfen',
    }
    return render(request, 'stiftung/dokument_form.html', context)

@login_required
def dokument_update(request, pk):
    """Update an existing document link"""
    dokument = get_object_or_404(DokumentLink, pk=pk)
    
    if request.method == 'POST':
        form = DokumentLinkForm(request.POST, instance=dokument)
        if form.is_valid():
            form.save()
            messages.success(request, f'Dokument "{dokument.titel}" wurde erfolgreich aktualisiert.')
            return redirect('stiftung:dokument_detail', pk=dokument.pk)
    else:
        form = DokumentLinkForm(instance=dokument)
    
    context = {
        'form': form,
        'dokument': dokument,
        'title': f'Dokument bearbeiten: {dokument}',
    }
    return render(request, 'stiftung/dokument_form.html', context)

@login_required
def dokument_delete(request, pk):
    """Delete a document link"""
    dokument = get_object_or_404(DokumentLink, pk=pk)
    
    if request.method == 'POST':
        dokument.delete()
        messages.success(request, f'Dokument "{dokument.titel}" wurde erfolgreich gelöscht.')
        return redirect('stiftung:dokument_list')
    
    context = {
        'dokument': dokument,
        'title': f'Dokument löschen: {dokument}',
    }
    return render(request, 'stiftung/dokument_confirm_delete.html', context)

# Legacy document views removed - use dokument_management instead

# Jahresbericht Views
@login_required
def bericht_list(request):
    """List available reports"""
    # Get available years from data
    jahre = sorted(set(
        list(Foerderung.objects.values_list('jahr', flat=True)) +
        list(LandVerpachtung.objects.values_list('pachtbeginn__year', flat=True))
    ), reverse=True)
    
    # Statistics for overview tiles (removed legacy Person and Verpachtung)
    total_destinataere = Destinataer.objects.count()
    total_laendereien = Land.objects.count()
    total_verpachtungen = LandVerpachtung.objects.count()
    total_foerderungen = Foerderung.objects.count()

    context = {
        'jahre': jahre,
        'title': 'Berichte',
        'total_destinataere': total_destinataere,
        'total_laendereien': total_laendereien,
        'total_verpachtungen': total_verpachtungen,
        'total_foerderungen': total_foerderungen,
    }
    return render(request, 'stiftung/bericht_list.html', context)

@login_required
def jahresbericht_generate(request, jahr):
    """Generate annual report for a specific year"""
    # Get data for the year
    foerderungen = Foerderung.objects.filter(jahr=jahr).select_related('person')
    verpachtungen = LandVerpachtung.objects.filter(
        pachtbeginn__year__lte=jahr,
        pachtende__year__gte=jahr
    ).select_related('land', 'paechter')
    
    # Calculate statistics
    total_foerderungen = foerderungen.aggregate(total=Sum('betrag'))['total'] or 0
    total_pachtzins = verpachtungen.aggregate(total=Sum('pachtzins_pauschal'))['total'] or 0
    
    context = {
        'jahr': jahr,
        'foerderungen': foerderungen,
        'verpachtungen': verpachtungen,
        'total_foerderungen': total_foerderungen,
        'total_pachtzins': total_pachtzins,
        'title': f'Jahresbericht {jahr}',
    }
    return render(request, 'stiftung/jahresbericht.html', context)

@login_required
def jahresbericht_generate_redirect(request):
    """Redirects the GET form without path param to the proper URL using the provided query param 'jahr'."""
    jahr = request.GET.get('jahr')
    if jahr and str(jahr).isdigit():
        return redirect('stiftung:jahresbericht_generate', jahr=int(jahr))
    messages.error(request, 'Bitte wählen Sie ein gültiges Jahr aus.')
    return redirect('stiftung:bericht_list')

@login_required
def jahresbericht_pdf(request, jahr):
    """Generate PDF version of annual report"""
    from django.http import HttpResponse
    from weasyprint import HTML
    from django.template.loader import render_to_string
    
    # Get data for the year
    foerderungen = Foerderung.objects.filter(jahr=jahr).select_related('person')
    verpachtungen = LandVerpachtung.objects.filter(
        pachtbeginn__year__lte=jahr,
        pachtende__year__gte=jahr
    ).select_related('land', 'paechter')
    
    # Calculate statistics
    total_foerderungen = foerderungen.aggregate(total=Sum('betrag'))['total'] or 0
    total_pachtzins = verpachtungen.aggregate(total=Sum('pachtzins_pauschal'))['total'] or 0
    
    context = {
        'jahr': jahr,
        'foerderungen': foerderungen,
        'verpachtungen': verpachtungen,
        'total_foerderungen': total_foerderungen,
        'total_pachtzins': total_pachtzins,
    }
    
    # Render HTML
    html_string = render_to_string('stiftung/jahresbericht.html', context)
    
    # Generate PDF
    pdf = HTML(string=html_string).write_pdf()
    
    # Create response
    response = HttpResponse(pdf, content_type='application/pdf')
    response['Content-Disposition'] = f'attachment; filename="jahresbericht_{jahr}.pdf"'
    
    return response

# Dashboard Views
@login_required
def dashboard(request):
    # Foerderung statistics (Person statistics removed - was legacy Verpachtung system)
    total_foerderungen = Foerderung.objects.aggregate(total=Sum('betrag'))['total'] or 0
    
    # Land statistics
    total_land = Land.objects.count()
    active_land = Land.objects.filter(aktiv=True).count()
    total_flaeche = Land.objects.aggregate(total=Sum('groesse_qm'))['total'] or 0
    
    # Calculate total verpachtet from active verpachtungen
    total_verpachtet = LandVerpachtung.objects.filter(status='aktiv').aggregate(
        total=Sum('verpachtete_flaeche')
    )['total'] or 0
    
    # Verpachtung statistics
    total_verpachtungen = LandVerpachtung.objects.count()
    active_verpachtungen = LandVerpachtung.objects.filter(status='aktiv').count()
    total_pachtzins = LandVerpachtung.objects.filter(status='aktiv').aggregate(
        total=Sum('pachtzins_pauschal')
    )['total'] or 0
    
    # Recent activities
    recent_lands = Land.objects.order_by('-erstellt_am')[:5]
    recent_verpachtungen = LandVerpachtung.objects.select_related('land', 'paechter').order_by('-erstellt_am')[:5]
    
    # Dokumentenübersicht
    dokumente_uebersicht = DokumentLink.objects.all().order_by('-id')[:10]
    
    # Verfügbare Paperless-Dokumente für Dashboard
    available_paperless_docs = []
    from stiftung.utils.config import get_paperless_config
    
    config = get_paperless_config()
    url = config['api_url']
    token = config['api_token']
    
    if url and token:
        try:
            base_url = url.rstrip('/api') if url.endswith('/api') else url
            headers = {'Authorization': f'Token {token}'}
            
            # Alle verfügbaren Dokumente abrufen (mit Paginierung)
            all_dokumente = []
            page = 1
            page_size = 100
            
            while True:
                response = requests.get(f"{base_url}/api/documents/?page={page}&page_size={page_size}", headers=headers, timeout=10)
                response.raise_for_status()
                data = response.json()
                
                all_dokumente.extend(data.get('results', []))
                
                if not data.get('next'):
                    break
                page += 1
            
            # Stiftung-Dokumente filtern
            for doc in all_dokumente:
                try:
                    tags = []
                    doc_tags = doc.get('tags', [])
                    
                    if isinstance(doc_tags, list):
                        for tag in doc_tags:
                            if isinstance(tag, dict) and 'name' in tag:
                                tags.append(tag['name'])
                            elif isinstance(tag, str):
                                tags.append(tag)
                            elif isinstance(tag, int):
                                tags.append(f"Tag_{tag}")
                    elif isinstance(doc_tags, str):
                        tags = [tag.strip() for tag in doc_tags.split(',')]
                    
                    if any(tag in [config['destinataere_tag'], config['land_tag'], config['admin_tag']] for tag in tags):
                        bereits_verknuepft = DokumentLink.objects.filter(
                            paperless_document_id=doc['id']
                        ).exists()
                        
                        if not bereits_verknuepft:
                            available_paperless_docs.append({
                                'id': doc['id'],
                                'title': doc.get('title', f'Dokument {doc["id"]}'),
                                'created_date': doc.get('created_date', ''),
                                'tags': tags,
                                'thumbnail_url': f"{base_url}/api/documents/{doc['id']}/thumb/",
                                'document_url': f"{base_url}/documents/{doc['id']}/",
                            })
                except Exception:
                    continue
            
            # Nach Erstellungsdatum sortieren (neueste zuerst)
            available_paperless_docs.sort(key=lambda x: x['created_date'], reverse=True)
            
        except Exception:
            pass
    
    context = {
        # Person statistics removed - was legacy Verpachtung system
        'total_foerderungen': total_foerderungen,
        'total_land': total_land,
        'active_land': active_land,
        'total_flaeche': total_flaeche,
        'total_verpachtet': total_verpachtet,
        'total_verpachtungen': total_verpachtungen,
        'active_verpachtungen': active_verpachtungen,
        'total_pachtzins': total_pachtzins,
        'recent_lands': recent_lands,
        'recent_verpachtungen': recent_verpachtungen,
        'dokumente_uebersicht': dokumente_uebersicht,
        'available_paperless_docs': available_paperless_docs,
    }
    return render(request, 'stiftung/dashboard.html', context)

# API Views for AJAX
@login_required
def land_stats_api(request):
    """API endpoint for land statistics"""
    if request.method == 'GET':
        gemeinde = request.GET.get('gemeinde', '')
        
        if gemeinde:
            lands = Land.objects.filter(gemeinde=gemeinde)
        else:
            lands = Land.objects.all()
        
        stats = {
            'total_count': lands.count(),
            'total_flaeche': float(lands.aggregate(total=Sum('groesse_qm'))['total'] or 0),
            'total_verpachtet': float(Verpachtung.objects.filter(status='aktiv', land__in=lands).aggregate(
                total=Sum('verpachtete_flaeche')
            )['total'] or 0),
            'avg_verpachtungsgrad': 0,
        }
        
        if stats['total_flaeche'] > 0:
            stats['avg_verpachtungsgrad'] = (stats['total_verpachtet'] / stats['total_flaeche']) * 100
        
        return JsonResponse(stats)
    
    return JsonResponse({'error': 'Invalid request method'}, status=400)

@api_view(['GET'])
def health(_request):
    return Response({'status': 'ok'})

@api_view(['GET'])
def paperless_ping(_request):
    from stiftung.utils.config import get_paperless_config
    
    config = get_paperless_config()
    url = config['api_url']
    token = config['api_token']
    if not url or not token:
        return Response({'ok': False, 'reason': 'Paperless API not configured'}, status=400)
    try:
        # Entferne /api vom Ende der URL falls vorhanden
        base_url = url.rstrip('/api') if url.endswith('/api') else url
        r = requests.get(f"{base_url}/api/tags/", headers={"Authorization": f"Token {token}"}, timeout=5)
        return Response({'ok': r.ok, 'status_code': r.status_code})
    except Exception as e:
        return Response({'ok': False, 'error': str(e)}, status=500)

@api_view(['GET'])
def paperless_documents(request):
    """Holt Dokumente aus Paperless mit den erforderlichen Tags.
    Optionales Polling: ?poll=1 wartet kurz und versucht erneut, damit frisch ingestete
    Dokumente in Paperless erscheinen, bevor die Liste zurückgegeben wird.
    """
    from stiftung.utils.config import get_paperless_config
    
    config = get_paperless_config()
    url = config['api_url']
    token = config['api_token']
    required_tag = config['destinataere_tag']
    land_tag = config['land_tag']
    admin_tag = config['admin_tag']
    destinaere_tag_id = config['destinataere_tag_id']
    land_tag_id = config['land_tag_id']
    admin_tag_id = config['admin_tag_id']
    
    if not url or not token:
        return Response({
            'error': 'Paperless API not configured',
            'message': 'Please set PAPERLESS_API_URL and PAPERLESS_API_TOKEN in your environment variables',
            'documents': [],
            'total_destinaere': 0,
            'total_land': 0,
            'total_admin': 0,
            'total_all': 0
        }, status=400)
    
    try:
        # Entferne /api vom Ende der URL falls vorhanden
        base_url = url.rstrip('/api') if url.endswith('/api') else url
        headers = {'Authorization': f'Token {token}'}

        def fetch_tagged():
            # mit ordering=-created neueste zuerst
            dest_resp = requests.get(
                f"{base_url}/api/documents/?tags__id={destinaere_tag_id}&ordering=-created",
                headers=headers, timeout=10
            )
            dest_resp.raise_for_status()
            dest_docs = dest_resp.json()

            land_resp = requests.get(
                f"{base_url}/api/documents/?tags__id={land_tag_id}&ordering=-created",
                headers=headers, timeout=10
            )
            land_resp.raise_for_status()
            land_docs = land_resp.json()

            admin_resp = requests.get(
                f"{base_url}/api/documents/?tags__id={admin_tag_id}&ordering=-created",
                headers=headers, timeout=10
            )
            admin_resp.raise_for_status()
            admin_docs = admin_resp.json()

            return dest_docs, land_docs, admin_docs

        dest_docs, land_docs, admin_docs = fetch_tagged()

        # Optionales kurzes Polling, wenn angefordert
        if request.GET.get('poll') in ('1', 'true', 'yes'):
            start_total = sum([
                dest_docs.get('count', 0),
                land_docs.get('count', 0),
                admin_docs.get('count', 0),
            ])
            deadline = time.time() + 6.0  # bis zu 6 Sekunden warten
            while time.time() < deadline:
                time.sleep(1.0)
                d2, l2, a2 = fetch_tagged()
                new_total = sum([d2.get('count', 0), l2.get('count', 0), a2.get('count', 0)])
                if new_total > start_total:
                    dest_docs, land_docs, admin_docs = d2, l2, a2
                    break

        # Alle Dokumente zusammenfassen
        all_documents = []
        for doc in dest_docs.get('results', []):
            doc['tag_category'] = 'destinaere'
            all_documents.append(doc)
        for doc in land_docs.get('results', []):
            doc['tag_category'] = 'land'
            all_documents.append(doc)
        for doc in admin_docs.get('results', []):
            doc['tag_category'] = 'admin'
            all_documents.append(doc)

        return Response({
            'documents': all_documents,
            'total_destinaere': dest_docs.get('count', 0),
            'total_land': land_docs.get('count', 0),
            'total_admin': admin_docs.get('count', 0),
            'total_all': len(all_documents)
        })
        
    except requests.exceptions.RequestException as e:
        return Response({
            'error': f'API-Fehler: {e}',
            'message': 'Could not connect to Paperless API. Please check your configuration.',
            'documents': [],
            'total_destinaere': 0,
            'total_land': 0,
            'total_admin': 0,
            'total_all': 0
        }, status=500)
    except Exception as e:
        return Response({
            'error': f'Unerwarteter Fehler: {e}',
            'message': 'An unexpected error occurred while fetching documents.',
            'documents': [],
            'total_destinaere': 0,
            'total_land': 0,
            'total_admin': 0,
            'total_all': 0
        }, status=500)

# Legacy dokument_integration view removed - use dokument_management instead

@api_view(['GET'])
def paperless_debug(request):
    """Debug-View für Paperless-Integration"""
    from stiftung.utils.config import get_paperless_config
    
    config = get_paperless_config()
    url = config['api_url']
    token = config['api_token']
    required_tag = config['destinataere_tag']
    land_tag = config['land_tag']
    admin_tag = config['admin_tag']
    destinaere_tag_id = config['destinataere_tag_id']
    land_tag_id = config['land_tag_id']
    admin_tag_id = config['admin_tag_id']
    
    if not url or not token:
        return Response({'error': 'Paperless API not configured'}, status=400)
    
    try:
        # Entferne /api vom Ende der URL falls vorhanden
        base_url = url.rstrip('/api') if url.endswith('/api') else url
        
        headers = {'Authorization': f'Token {token}'}
        
        # Alle Tags abrufen
        tags_response = requests.get(f"{base_url}/api/tags/?page_size=1000", headers=headers, timeout=10)
        tags_response.raise_for_status()
        tags_data = tags_response.json()
        
        # Alle Tags durchsuchen
        all_tags = tags_data.get('results', [])
        exact_match_destinaere = None
        exact_match_land = None
        exact_match_admin = None
        similar_tags = []
        
        # Nach den neuen Tag-Namen suchen (mit Unterstrichen)
        for tag in all_tags:
            tag_name = tag.get('name', '')
            tag_id = tag.get('id')
            
            # Suche nach den neuen Tag-Namen
            if tag_name == "Stiftung_Destinatäre":
                exact_match_destinaere = {'id': tag_id, 'name': tag_name}
            elif tag_name == "Stiftung_Land_und_Pächter":
                exact_match_land = {'id': tag_id, 'name': tag_name}
            elif tag_name == "Stiftung_Administration":
                exact_match_admin = {'id': tag_id, 'name': tag_name}
            
            # Ähnliche Tags finden
            if 'stiftung' in tag_name.lower() or 'destinat' in tag_name.lower() or 'land' in tag_name.lower() or 'admin' in tag_name.lower():
                similar_tags.append({'id': tag_id, 'name': tag_name})
        
        # Alle Tag-Namen sammeln
        all_tag_names = [tag.get('name', '') for tag in all_tags]
        
        # Dokumente abrufen
        documents_response = requests.get(f"{base_url}/api/documents/?page_size=10", headers=headers, timeout=10)
        documents_response.raise_for_status()
        documents_data = documents_response.json()
        
        # Stiftung-Dokumente finden (mit Tag 21 "Stiftung")
        stiftung_documents = []
        for doc in documents_data.get('results', []):
            doc_tags = doc.get('tags', [])
            if 21 in doc_tags:  # Tag 21 ist "Stiftung"
                stiftung_documents.append(doc)
        
        # Sample-Dokumente mit Tag-Namen anreichern
        sample_documents = documents_data.get('results', [])[:5]
        enriched_documents = []
        
        for doc in sample_documents:
            doc_copy = doc.copy()
            tag_names = []
            for tag_id in doc.get('tags', []):
                # Tag-Namen aus der Tag-Liste finden
                tag_name = next((tag.get('name', f'Unknown({tag_id})') for tag in all_tags if tag.get('id') == tag_id), f'Unknown({tag_id})')
                tag_names.append(tag_name)
            doc_copy['tag_names'] = tag_names
            enriched_documents.append(doc_copy)
        
        return Response({
            'paperless_url': url,
            'base_url': base_url,
            'required_tag': required_tag,
            'land_tag': land_tag,
            'admin_tag': admin_tag,
            'destinaere_tag_id': destinaere_tag_id,
            'land_tag_id': land_tag_id,
            'admin_tag_id': admin_tag_id,
            'exact_match_destinaere': exact_match_destinaere,
            'exact_match_land': exact_match_land,
            'exact_match_admin': exact_match_admin,
            'similar_tags': similar_tags,
            'all_tag_names': all_tag_names,
            'total_tags': len(all_tags),
            'total_documents': documents_data.get('count', 0),
            'sample_documents': sample_documents,
            'api_token_length': len(token) if token else 0,
            'enriched_documents': enriched_documents,
            'stiftung_documents': stiftung_documents
        })
        
    except requests.exceptions.RequestException as e:
        return Response({'error': f'API-Fehler: {e}'}, status=500)
    except Exception as e:
        return Response({'error': f'Unerwarteter Fehler: {e}'}, status=500)

@api_view(['GET'])
def paperless_tags_only(request):
    """Holt nur die Tag-Liste aus Paperless - ohne Dokumente"""
    from stiftung.utils.config import get_paperless_config
    
    config = get_paperless_config()
    url = config['api_url']
    token = config['api_token']
    
    if not url or not token:
        return Response({'error': 'Paperless API not configured'}, status=400)
    
    try:
        # Entferne /api vom Ende der URL falls vorhanden
        base_url = url.rstrip('/api') if url.endswith('/api') else url
        
        # Alle Tags abrufen (mit großer page_size)
        headers = {'Authorization': f'Token {token}'}
        
        # Erste Anfrage mit großer page_size
        tags_response = requests.get(f"{base_url}/api/tags/?page_size=1000", headers=headers, timeout=10)
        tags_response.raise_for_status()
        tags_data = tags_response.json()
        
        all_tags = []
        
        # Erste Seite verarbeiten
        for tag in tags_data.get('results', []):
            tag_detail = {
                'id': tag.get('id'),
                'name': tag.get('name', ''),
                'slug': tag.get('slug', ''),
                'color': tag.get('color', ''),
                'text_color': tag.get('text_color', ''),
                'match': tag.get('match', ''),
                'matching_algorithm': tag.get('matching_algorithm'),
                'is_inbox_tag': tag.get('is_inbox_tag'),
                'document_count': tag.get('document_count', 0)
            }
            all_tags.append(tag_detail)
        
        # Weitere Seiten abrufen falls vorhanden
        next_url = tags_data.get('next')
        while next_url:
            next_response = requests.get(next_url, headers=headers, timeout=10)
            next_response.raise_for_status()
            next_data = next_response.json()
            
            for tag in next_data.get('results', []):
                tag_detail = {
                    'id': tag.get('id'),
                    'name': tag.get('name', ''),
                    'slug': tag.get('slug', ''),
                    'color': tag.get('color', ''),
                    'text_color': tag.get('text_color', ''),
                    'match': tag.get('match', ''),
                    'matching_algorithm': tag.get('matching_algorithm'),
                    'is_inbox_tag': tag.get('is_inbox_tag'),
                    'document_count': tag.get('document_count', 0)
                }
                all_tags.append(tag_detail)
            
            next_url = next_data.get('next')
        
        # Nach ID sortieren
        all_tags.sort(key=lambda x: x['id'])
        
        return Response({
            'total_tags': len(all_tags),
            'tags': all_tags,
            'tag_ids': [tag['id'] for tag in all_tags],
            'tag_names': [tag['name'] for tag in all_tags],
            'api_info': {
                'page_size_used': 1000,
                'total_count_from_api': tags_data.get('count', 0)
            }
        })
        
    except requests.exceptions.RequestException as e:
        return Response({'error': f'API-Fehler: {e}'}, status=500)
    except Exception as e:
        return Response({'error': f'Unerwarteter Fehler: {e}'}, status=500)

@api_view(['GET'])
def link_document_search(request):
    """Sucht nach Datensätzen für die Dokument-Verknüpfung"""
    from django.db.models import Q
    
    query = request.GET.get('q', '')
    category = request.GET.get('category', 'all')
    
    results = {}
    
    if category in ['all', 'destinataer']:
        # Suche nach Destinatären
        destinataer_query = Q()
        if query and query != 'all':
            destinataer_query = (
                Q(nachname__icontains=query) | Q(vorname__icontains=query) |
                Q(email__icontains=query) | Q(telefon__icontains=query) |
                Q(strasse__icontains=query) | Q(ort__icontains=query) | Q(plz__icontains=query) |
                Q(institution__icontains=query) | Q(familienzweig__icontains=query) |
                Q(notizen__icontains=query)
            )
        
        destinataer_results = Destinataer.objects.filter(destinataer_query)[:25]
        results['destinataer'] = [
            {
                'id': d.id,
                'name': f"{d.vorname} {d.nachname}".strip() if d.vorname else (d.institution or d.nachname),
                'type': 'Destinatär',
                'details': f"{d.strasse or ''}{(', ' + d.plz + ' ' + d.ort) if d.plz and d.ort else (' ' + d.ort) if d.ort else ''} {('• ' + d.email) if d.email else ''} {('• ' + d.institution) if d.institution else ''} {('• ' + d.familienzweig) if d.familienzweig else ''}".strip()
            }
            for d in destinataer_results
        ]
    
    if category in ['all', 'land']:
        # Suche nach Ländereien
        land_query = Q()
        if query and query != 'all':
            # Extract numbers from search terms like "Flur 9" or "Flurstück 11"
            import re
            flur_match = re.search(r'flur\s*(\d+)', query, re.IGNORECASE)
            flurstuck_match = re.search(r'flurstück\s*(\d+)', query, re.IGNORECASE)
            
            land_query = (
                Q(gemarkung__icontains=query) | Q(gemeinde__icontains=query) | 
                Q(flur__icontains=query) | Q(flurstueck__icontains=query) |
                Q(lfd_nr__icontains=query) | Q(ew_nummer__icontains=query) |
                Q(notizen__icontains=query)
            )
            
            # Add specific searches for extracted numbers
            if flur_match:
                land_query |= Q(flur__exact=flur_match.group(1))
            if flurstuck_match:
                land_query |= Q(flurstueck__exact=flurstuck_match.group(1))
        
        land_results = Land.objects.filter(land_query)[:25]
        results['land'] = [
            {
                'id': l.id,
                'name': f"{l.gemarkung} - {l.gemeinde}, Flur {l.flur}, Flurstück {l.flurstueck or 'N/A'}",
                'type': 'Land',
                'details': f"Lfd.Nr: {l.lfd_nr or 'N/A'} • EW-Nr: {l.ew_nummer or 'N/A'} • Größe: {l.groesse_qm or 0} m²"
            }
            for l in land_results
        ]
    
    if category in ['all', 'verpachtung']:
        # Suche nach Verpachtungen (using new LandVerpachtung model)
        verpachtung_query = Q()
        if query and query != 'all':
            verpachtung_query = (
                Q(paechter__nachname__icontains=query) | Q(paechter__vorname__icontains=query) | 
                Q(paechter__ort__icontains=query) | Q(paechter__email__icontains=query) |
                Q(paechter__pachtnummer__icontains=query) |
                Q(land__gemarkung__icontains=query) | Q(land__gemeinde__icontains=query) |
                Q(land__flur__icontains=query) | Q(land__flurstueck__icontains=query) |
                Q(land__lfd_nr__icontains=query) |
                Q(vertragsnummer__icontains=query) | Q(pachtzins_pauschal__icontains=query) | Q(bemerkungen__icontains=query)
            )
        
        verpachtung_results = LandVerpachtung.objects.filter(verpachtung_query).select_related('paechter', 'land')[:25]
        results['verpachtung'] = [
            {
                'id': v.id,
                'name': f"{(v.paechter.vorname + ' ') if v.paechter and v.paechter.vorname else ''}{v.paechter.nachname if v.paechter else 'Unbekannt'} → {v.land.gemarkung}, Flur {v.land.flur}",
                'type': 'Verpachtung',
                'details': f"Vertrag: {v.vertragsnummer} • Flurstück: {v.land.flurstueck or 'N/A'} • Pachtzins: {v.pachtzins_pauschal or 'N/A'} €/Jahr • Zeitraum: {v.pachtbeginn.strftime('%Y') if v.pachtbeginn else '?'}-{v.pachtende.strftime('%Y') if v.pachtende else 'laufend'}"
            }
            for v in verpachtung_results
        ]

    if category in ['all', 'paechter']:
        # Suche nach Pächtern
        paechter_query = Q()
        if query and query != 'all':
            paechter_query = (
                Q(nachname__icontains=query) | Q(vorname__icontains=query) | 
                Q(ort__icontains=query) | Q(email__icontains=query) |
                Q(telefon__icontains=query) | Q(strasse__icontains=query) |
                Q(pachtnummer__icontains=query) | Q(plz__icontains=query) |
                Q(notizen__icontains=query)
            )
        paechter_results = Paechter.objects.filter(paechter_query)[:25]
        results['paechter'] = [
            {
                'id': p.id,
                'name': f"{(p.vorname + ' ') if p.vorname else ''}{p.nachname}" + (f" (#{p.pachtnummer})" if p.pachtnummer else ""),
                'type': 'Pächter',
                'details': f"{p.strasse or ''}{(', ' + p.plz + ' ' + p.ort) if p.plz and p.ort else (' ' + p.ort) if p.ort else ''} {('• ' + p.email) if p.email else ''} {('• Tel: ' + p.telefon) if p.telefon else ''}".strip()
            }
            for p in paechter_results
        ]
    
    if category in ['all', 'rentmeister']:
        # Suche nach Rentmeistern
        from stiftung.models import Rentmeister
        rentmeister_query = Q()
        if query and query != 'all':
            rentmeister_query = (
                Q(nachname__icontains=query) | Q(vorname__icontains=query) | 
                Q(ort__icontains=query) | Q(email__icontains=query) |
                Q(telefon__icontains=query) | Q(strasse__icontains=query) |
                Q(plz__icontains=query) | Q(notizen__icontains=query) |
                Q(titel__icontains=query) | Q(mobil__icontains=query)
            )
        rentmeister_results = Rentmeister.objects.filter(rentmeister_query)[:25]
        results['rentmeister'] = [
            {
                'id': r.id,
                'name': f"{(r.anrede + ' ') if r.anrede else ''}{(r.vorname + ' ') if r.vorname else ''}{r.nachname}" + (f" ({r.titel})" if r.titel else ""),
                'type': 'Rentmeister',
                'details': f"{r.strasse or ''}{(', ' + r.plz + ' ' + r.ort) if r.plz and r.ort else (' ' + r.ort) if r.ort else ''} {('• ' + r.email) if r.email else ''} {('• Tel: ' + r.telefon) if r.telefon else ''} {('• Mobil: ' + r.mobil) if r.mobil else ''}".strip()
            }
            for r in rentmeister_results
        ]

    if category in ['all', 'abrechnung']:
        # Suche nach Abrechnungen
        abrechnung_query = Q()
        if query and query != 'all':
            abrechnung_query = (
                Q(land__gemarkung__icontains=query) | Q(land__gemeinde__icontains=query) |
                Q(land__flur__icontains=query) | Q(land__flurstueck__icontains=query) |
                Q(land__lfd_nr__icontains=query) | Q(abrechnungsjahr__icontains=query) |
                Q(bemerkungen__icontains=query)
            )
        
        abrechnung_results = LandAbrechnung.objects.filter(abrechnung_query).select_related('land')[:25]
        results['abrechnung'] = [
            {
                'id': a.id,
                'name': f"Abrechnung {a.abrechnungsjahr} - {a.land.gemarkung}, Flur {a.land.flur}",
                'type': 'Abrechnung',
                'details': f"Flurstück: {a.land.flurstueck or 'N/A'} • Jahr: {a.abrechnungsjahr} • Grundsteuer: {a.grundsteuer_betrag or 0} € • Versicherung: {a.versicherungen_betrag or 0} €"
            }
            for a in abrechnung_results
        ]
    
    if category in ['all', 'foerderung']:
        # Suche nach Förderungen
        foerderung_query = Q()
        if query and query != 'all':
            foerderung_query = (
                Q(destinataer__nachname__icontains=query) | Q(destinataer__vorname__icontains=query) |
                Q(destinataer__institution__icontains=query) | Q(destinataer__email__icontains=query) |
                Q(jahr__icontains=query) | Q(betrag__icontains=query) |
                Q(kategorie__icontains=query) | Q(status__icontains=query) |
                Q(bemerkungen__icontains=query)
            )
        
        foerderung_results = Foerderung.objects.filter(foerderung_query).select_related('destinataer')[:25]
        results['foerderung'] = [
            {
                'id': str(f.id),  # Convert UUID to string for JSON serialization
                'name': f"{f.destinataer.get_full_name() if f.destinataer else 'Unbekannt'} - {f.jahr}",
                'type': 'Förderung',
                'details': f"Betrag: {f.betrag} € • Kategorie: {f.get_kategorie_display()} • Status: {f.get_status_display()} • Jahr: {f.jahr}"
            }
            for f in foerderung_results
        ]
    
    
    return Response(results)

def create_paechter_link_for_verpachtung(paperless_id, paperless_title, verpachtung_id):
    """Hilfsfunktion: Erstellt automatisch eine Pächter-Verknüpfung für eine Verpachtung"""
    try:
        # Hole die LandVerpachtung und den zugehörigen Pächter
        verpachtung = LandVerpachtung.objects.select_related('paechter').get(id=verpachtung_id)
        if verpachtung.paechter:
            # Prüfe, ob bereits eine Verknüpfung für dieses Dokument und diesen Pächter existiert
            existing_link = DokumentLink.objects.filter(
                paperless_document_id=paperless_id,
                paechter_id=verpachtung.paechter.id
            ).first()
            
            if not existing_link:
                # Erstelle automatische Pächter-Verknüpfung
                DokumentLink.objects.create(
                    paperless_document_id=paperless_id,
                    titel=paperless_title,
                    kontext='paechter',
                    paechter_id=verpachtung.paechter.id
                )
                return True
    except (LandVerpachtung.DoesNotExist, Exception):
        pass
    return False

@csrf_exempt
@api_view(['POST'])
def link_document_create(request):
    """Erstellt eine Verknüpfung zwischen einem Paperless-Dokument und einem Datensatz"""
    from django.db import transaction
    
    try:
        # Robust JSON parsing to tolerate Latin-1 encoded payloads (e.g., umlauts)
        try:
            payload = request.data
        except Exception:
            raw = request.body
            try:
                payload = json.loads(raw.decode('utf-8'))
            except UnicodeDecodeError:
                payload = json.loads(raw.decode('latin-1'))

        paperless_id = payload.get('paperless_id')
        paperless_title = payload.get('paperless_title')
        paperless_url = payload.get('paperless_url')
        link_type = payload.get('link_type')  # 'destinataer', 'land', 'verpachtung', 'paechter', 'abrechnung'
        link_id = payload.get('link_id')
        
        if not all([paperless_id, paperless_title, paperless_url, link_type, link_id]):
            return Response({'error': 'Alle Felder sind erforderlich'}, status=400)
        
        with transaction.atomic():
            # Erstelle den DokumentLink
            dokument_link = DokumentLink.objects.create(
                paperless_document_id=paperless_id,  # Korrigiert: 'paperless_document_id' statt 'paperless_id'
                titel=paperless_title,               # Korrigiert: 'titel' statt 'title'
                kontext='anderes'
            )
            
            # Setze die entsprechenden UUID-Felder basierend auf dem Link-Typ
            if link_type == 'destinataer':
                dokument_link.destinataer_id = link_id
            elif link_type == 'land':
                dokument_link.land_id = link_id
            elif link_type == 'verpachtung':
                # Use new LandVerpachtung field instead of legacy
                dokument_link.land_verpachtung_id = link_id
            elif link_type == 'paechter':
                dokument_link.paechter_id = link_id
            elif link_type == 'foerderung':
                dokument_link.foerderung_id = link_id
            elif link_type == 'rentmeister':
                dokument_link.rentmeister_id = link_id
            elif link_type == 'abrechnung':
                dokument_link.abrechnung_id = link_id
            
            dokument_link.save()
        
        # Log the document linking action
        from stiftung.audit import log_link
        try:
            # Get the linked entity name for logging
            entity_name = paperless_title
            if link_type == 'destinataer':
                from stiftung.models import Destinataer
                entity = Destinataer.objects.get(id=link_id)
                target_name = entity.get_full_name()
            elif link_type == 'land':
                from stiftung.models import Land
                entity = Land.objects.get(id=link_id)
                target_name = str(entity)
            elif link_type == 'paechter':
                from stiftung.models import Paechter
                entity = Paechter.objects.get(id=link_id)
                target_name = f"{entity.vorname} {entity.nachname}".strip()
            elif link_type == 'foerderung':
                from stiftung.models import Foerderung
                entity = Foerderung.objects.get(id=link_id)
                target_name = f"{entity.destinataer.get_full_name() if entity.destinataer else 'Unbekannt'} - {entity.jahr}"
            elif link_type == 'verpachtung':
                from stiftung.models import Verpachtung
                entity = Verpachtung.objects.get(id=link_id)
                target_name = str(entity)
            elif link_type == 'rentmeister':
                from stiftung.models import Rentmeister
                entity = Rentmeister.objects.get(id=link_id)
                target_name = entity.get_full_name()
            else:
                target_name = f"ID {link_id}"
            
            log_link(
                request=request,
                entity_type='dokumentlink',
                entity_id=str(dokument_link.id),
                entity_name=entity_name,
                target_type=link_type,
                target_name=target_name
            )
        except Exception as e:
            # Don't fail the main operation if logging fails
            print(f"Audit logging failed: {e}")
        
        # Automatische Pächter-Verknüpfung NACH der Haupttransaktion
        paechter_linked = False
        if link_type == 'verpachtung':
            paechter_linked = create_paechter_link_for_verpachtung(paperless_id, paperless_title, link_id)
        
        message = f'Dokument erfolgreich mit {link_type} verknüpft'
        if paechter_linked:
            message += ' (automatisch auch mit Pächter verknüpft)'
        
        return Response({
            'success': True,
            'message': message,
            'dokument_id': dokument_link.id
        })
            
    except Exception as e:
        return Response({'error': f'Fehler beim Erstellen der Verknüpfung: {str(e)}'}, status=500)

# Legacy dokument_verknuepfung view removed - use dokument_management instead

@api_view(['GET'])
def link_document_list(request):
    """Listet alle bestehenden Dokument-Verknüpfungen auf, gruppiert nach Paperless-Document-ID"""
    try:
        dokument_links = DokumentLink.objects.all().order_by('-id')
        
        # Group links by paperless_document_id to show multiple links per document
        links_by_document = {}
        
        for link in dokument_links:
            paperless_id = link.paperless_document_id
            
            if paperless_id not in links_by_document:
                links_by_document[paperless_id] = {
                    'paperless_id': paperless_id,
                    'title': link.titel,
                    'paperless_url': f"/api/paperless/documents/{paperless_id}/",
                    'links': []
                }
            
            # Create link info
            link_info = {
                'id': str(link.id),  # Ensure UUID is stringified
                'kontext': link.kontext,
                'link_type': None,
                'linked_object': None
            }
            
            # Determine link type and get linked object details
            if link.destinataer_id:
                link_info['link_type'] = 'destinataer'
                try:
                    dest = Destinataer.objects.get(id=link.destinataer_id)
                    link_info['linked_object'] = {
                        'id': str(dest.id),
                        'type': 'Destinatär',
                        'name': f"{dest.vorname} {dest.nachname}".strip() if dest.vorname else dest.institution,
                        'details': f"Institution: {dest.institution}" if dest.institution else f"Person: {dest.vorname} {dest.nachname}".strip()
                    }
                except Destinataer.DoesNotExist:
                    link_info['linked_object'] = {'type': 'Destinatär', 'name': 'Gelöscht', 'details': 'Datensatz nicht mehr verfügbar'}
            
            elif link.land_id:
                link_info['link_type'] = 'land'
                try:
                    land = Land.objects.get(id=link.land_id)
                    link_info['linked_object'] = {
                        'id': str(land.id),
                        'type': 'Land',
                        'name': f"{land.gemarkung} - {land.gemeinde}",
                        'details': f"Flur: {land.flur}, Größe: {land.groesse_qm or 0} m²"
                    }
                except Land.DoesNotExist:
                    link_info['linked_object'] = {'type': 'Land', 'name': 'Gelöscht', 'details': 'Datensatz nicht mehr verfügbar'}
            
            elif link.paechter_id:
                link_info['link_type'] = 'paechter'
                try:
                    p = Paechter.objects.get(id=link.paechter_id)
                    link_info['linked_object'] = {
                        'id': str(p.id),
                        'type': 'Pächter',
                        'name': f"{(p.vorname + ' ') if p.vorname else ''}{p.nachname}",
                        'details': f"{p.ort or ''}"
                    }
                except Paechter.DoesNotExist:
                    link_info['linked_object'] = {'type': 'Pächter', 'name': 'Gelöscht', 'details': 'Datensatz nicht mehr verfügbar'}

            elif link.land_verpachtung_id:
                link_info['link_type'] = 'verpachtung'
                try:
                    from stiftung.models import LandVerpachtung
                    verp = LandVerpachtung.objects.select_related('paechter', 'land').get(id=link.land_verpachtung_id)
                    link_info['linked_object'] = {
                        'id': str(verp.id),
                        'type': 'Verpachtung',
                        'name': f"Verpachtung {(verp.paechter.vorname + ' ') if verp.paechter and verp.paechter.vorname else ''}{verp.paechter.nachname if verp.paechter else 'Unbekannt'}",
                        'details': f"Land: {verp.land.gemarkung} - {verp.land.gemeinde}, Pächter: {(verp.paechter.vorname + ' ') if verp.paechter and verp.paechter.vorname else ''}{verp.paechter.nachname if verp.paechter else 'Unbekannt'}, Vertrag: {verp.vertragsnummer}"
                    }
                except LandVerpachtung.DoesNotExist:
                    link_info['linked_object'] = {'type': 'Verpachtung', 'name': 'Gelöscht', 'details': 'Datensatz nicht mehr verfügbar'}
            
            elif link.rentmeister_id:
                link_info['link_type'] = 'rentmeister'
                try:
                    from stiftung.models import Rentmeister
                    rentmeister = Rentmeister.objects.get(id=link.rentmeister_id)
                    link_info['linked_object'] = {
                        'id': str(rentmeister.id),
                        'type': 'Rentmeister',
                        'name': f"{(rentmeister.anrede + ' ') if rentmeister.anrede else ''}{(rentmeister.vorname + ' ') if rentmeister.vorname else ''}{rentmeister.nachname}" + (f" ({rentmeister.titel})" if rentmeister.titel else ""),
                        'details': f"Seit: {rentmeister.seit_datum.strftime('%d.%m.%Y') if rentmeister.seit_datum else 'Unbekannt'}" + (f", Tel: {rentmeister.telefon}" if rentmeister.telefon else "") + (f", {rentmeister.email}" if rentmeister.email else ""),
                        'url': f"/geschaeftsfuehrung/rentmeister/{rentmeister.id}/"
                    }
                except Rentmeister.DoesNotExist:
                    link_info['linked_object'] = {'type': 'Rentmeister', 'name': 'Gelöscht', 'details': 'Datensatz nicht mehr verfügbar'}
            
            elif link.abrechnung_id:
                link_info['link_type'] = 'abrechnung'
                try:
                    abrechnung = LandAbrechnung.objects.select_related('land').get(id=link.abrechnung_id)
                    link_info['linked_object'] = {
                        'id': str(abrechnung.id),
                        'type': 'Abrechnung',
                        'name': f"Abrechnung {abrechnung.abrechnungsjahr} - {abrechnung.land.gemarkung}",
                        'details': f"Land: {abrechnung.land.gemarkung} - {abrechnung.land.gemeinde}, Flur {abrechnung.land.flur}, Jahr {abrechnung.abrechnungsjahr}",
                        'url': f"/laendereien/abrechnungen/{abrechnung.id}/"
                    }
                except LandAbrechnung.DoesNotExist:
                    link_info['linked_object'] = {'type': 'Abrechnung', 'name': 'Gelöscht', 'details': 'Datensatz nicht mehr verfügbar'}
            
            links_by_document[paperless_id]['links'].append(link_info)
        
        # Convert to list format for frontend
        results = list(links_by_document.values())
        
        return Response({
            'total_documents': len(results),
            'total_links': sum(len(doc['links']) for doc in results),
            'links': results
        })
        
    except Exception as e:
        return Response({'error': f'Fehler beim Abrufen der Verknüpfungen: {str(e)}'}, status=500)


@csrf_exempt
@api_view(['POST'])
def link_document_update(request):
    """Aktualisiert die Verknüpfung eines Dokuments (Re-Linking auf anderen Datensatz/Kontext)."""
    from django.db import transaction
    
    try:
        # Robust JSON parsing to tolerate Latin-1 encoded payloads (e.g., umlauts)
        try:
            payload = request.data
        except Exception:
            raw = request.body
            try:
                payload = json.loads(raw.decode('utf-8'))
            except UnicodeDecodeError:
                payload = json.loads(raw.decode('latin-1'))
        
        link_id = payload.get('link_id')
        link_type = payload.get('link_type')  # 'destinataer' | 'land' | 'verpachtung' | 'paechter' | 'rentmeister'
        link_target_id = payload.get('link_id_target')
        if not all([link_id, link_type, link_target_id]):
            return Response({'error': 'link_id, link_type und link_id_target sind erforderlich'}, status=400)

        with transaction.atomic():
            link = DokumentLink.objects.get(id=link_id)
            old_verpachtung_id = link.verpachtung_id  # Merke alte Verpachtung für Cleanup
            paperless_id_for_cleanup = link.paperless_document_id
            titel_for_new_link = link.titel
            
            # Reset all associations first
            link.destinataer_id = None
            link.land_id = None
            link.verpachtung_id = None
            link.paechter_id = None
            link.foerderung_id = None
            link.rentmeister_id = None
            link.kontext = link_type

            if link_type == 'destinataer':
                link.destinataer_id = link_target_id
            elif link_type == 'land':
                link.land_id = link_target_id
            elif link_type == 'verpachtung':
                link.verpachtung_id = link_target_id
            elif link_type == 'paechter':
                link.paechter_id = link_target_id
            elif link_type == 'foerderung':
                link.foerderung_id = link_target_id
            elif link_type == 'rentmeister':
                link.rentmeister_id = link_target_id
            else:
                return Response({'error': 'Ungültiger link_type'}, status=400)

            link.save()
        
        # Automatische Pächter-Verknüpfung und Cleanup NACH der Haupttransaktion
        paechter_linked = False
        if link_type == 'verpachtung':
            paechter_linked = create_paechter_link_for_verpachtung(
                paperless_id_for_cleanup, titel_for_new_link, link_target_id
            )
        
        # Cleanup: Entferne verwaiste Pächter-Verknüpfungen wenn von Verpachtung weg geändert
        if old_verpachtung_id and link_type != 'verpachtung':
            try:
                old_verpachtung = Verpachtung.objects.select_related('paechter').get(id=old_verpachtung_id)
                if old_verpachtung.paechter:
                    # Prüfe ob noch andere Verpachtungs-Links für diesen Pächter existieren
                    other_verpachtung_links = DokumentLink.objects.filter(
                        paperless_document_id=paperless_id_for_cleanup,
                        verpachtung__paechter_id=old_verpachtung.paechter.id
                    ).exists()
                    
                    if not other_verpachtung_links:
                        # Entferne automatisch erstellte Pächter-Verknüpfung
                        DokumentLink.objects.filter(
                            paperless_document_id=paperless_id_for_cleanup,
                            paechter_id=old_verpachtung.paechter.id,
                            kontext='paechter'
                        ).delete()
            except (Verpachtung.DoesNotExist, Exception):
                pass
        
        message = 'Verknüpfung aktualisiert'
        if paechter_linked:
            message += ' (automatisch auch mit Pächter verknüpft)'
        
        return Response({'success': True, 'message': message})
    except DokumentLink.DoesNotExist:
        return Response({'error': 'Verknüpfung nicht gefunden'}, status=404)
    except Exception as e:
        return Response({'error': f'Unerwarteter Fehler: {e}'}, status=500)


@csrf_exempt
@api_view(['DELETE'])
def link_document_delete(request, link_id):
    """Löscht eine bestehende Verknüpfung."""
    from django.db import transaction
    
    try:
        with transaction.atomic():
            link = DokumentLink.objects.get(id=link_id)
            verpachtung_id_for_cleanup = link.verpachtung_id
            paperless_id_for_cleanup = link.paperless_document_id
            
            # Log the unlinking action before deletion
            from stiftung.audit import log_unlink
            try:
                # Determine what entity this was linked to
                target_type = "unknown"
                target_name = "Unknown"
                
                if link.destinataer_id:
                    target_type = "destinataer"
                    try:
                        entity = Destinataer.objects.get(id=link.destinataer_id)
                        target_name = entity.get_full_name()
                    except Destinataer.DoesNotExist:
                        target_name = f"Destinatär ID {link.destinataer_id}"
                elif link.land_id:
                    target_type = "land"
                    try:
                        entity = Land.objects.get(id=link.land_id)
                        target_name = str(entity)
                    except Land.DoesNotExist:
                        target_name = f"Land ID {link.land_id}"
                elif link.paechter_id:
                    target_type = "paechter"
                    try:
                        entity = Paechter.objects.get(id=link.paechter_id)
                        target_name = f"{entity.vorname} {entity.nachname}".strip()
                    except Paechter.DoesNotExist:
                        target_name = f"Pächter ID {link.paechter_id}"
                elif link.verpachtung_id:
                    target_type = "verpachtung"
                    try:
                        entity = Verpachtung.objects.get(id=link.verpachtung_id)
                        target_name = str(entity)
                    except Verpachtung.DoesNotExist:
                        target_name = f"Verpachtung ID {link.verpachtung_id}"
                elif link.rentmeister_id:
                    target_type = "rentmeister"
                    try:
                        from stiftung.models import Rentmeister
                        entity = Rentmeister.objects.get(id=link.rentmeister_id)
                        target_name = entity.get_full_name()
                    except Rentmeister.DoesNotExist:
                        target_name = f"Rentmeister ID {link.rentmeister_id}"
                
                log_unlink(
                    request=request,
                    entity_type='dokumentlink',
                    entity_id=str(link.id),
                    entity_name=link.titel,
                    target_type=target_type,
                    target_name=target_name
                )
            except Exception as e:
                # Don't fail the main operation if logging fails
                print(f"Audit logging failed: {e}")
            
            link.delete()
        
        # Cleanup NACH der Haupttransaktion: Wenn eine Verpachtungs-Verknüpfung gelöscht wurde, prüfe Pächter-Links
        if verpachtung_id_for_cleanup:
            try:
                verpachtung = Verpachtung.objects.select_related('paechter').get(id=verpachtung_id_for_cleanup)
                if verpachtung.paechter:
                    # Prüfe ob noch andere Verpachtungs-Links für diesen Pächter existieren
                    other_verpachtung_links = DokumentLink.objects.filter(
                        paperless_document_id=paperless_id_for_cleanup,
                        verpachtung__paechter_id=verpachtung.paechter.id
                    ).exists()
                    
                    if not other_verpachtung_links:
                        # Entferne automatisch erstellte Pächter-Verknüpfung
                        DokumentLink.objects.filter(
                            paperless_document_id=paperless_id_for_cleanup,
                            paechter_id=verpachtung.paechter.id,
                            kontext='paechter'
                        ).delete()
            except (Verpachtung.DoesNotExist, Exception):
                pass
        
        return Response({'success': True})
    except DokumentLink.DoesNotExist:
        return Response({'error': 'Verknüpfung nicht gefunden'}, status=404)
    except Exception as e:
        return Response({'error': f'Unerwarteter Fehler: {e}'}, status=500)


@api_view(['GET'])
def gramps_search_api(request):
    """Probe-Endpoint: Suche Personen in Gramps Web nach q (Nachname, Vorname)."""
    q = request.GET.get('q', '')
    if not q:
        return Response({'error': 'Parameter q erforderlich'}, status=400)
    client = get_gramps_client()
    result = client.search_people(q)
    return Response(result)


# Geschäftsführung Views
@login_required
def geschaeftsfuehrung(request):
    """Hauptansicht für die Geschäftsführung mit Übersicht"""
    from stiftung.models import StiftungsKonto, Verwaltungskosten, Rentmeister
    from django.db.models import Sum, Count
    from datetime import datetime, timedelta
    
    # Rentmeister-Übersicht
    rentmeister = Rentmeister.objects.filter(aktiv=True).order_by('nachname', 'vorname')
    
    # Konten-Übersicht
    konten = StiftungsKonto.objects.filter(aktiv=True).order_by('bank_name', 'kontoname')
    gesamtsaldo = konten.aggregate(total=Sum('saldo'))['total'] or 0
    
    # Aktuelle Kosten (letzten 30 Tage)
    heute = datetime.now().date()
    vor_30_tagen = heute - timedelta(days=30)
    
    aktuelle_kosten = Verwaltungskosten.objects.filter(
        datum__gte=vor_30_tagen
    ).order_by('-datum')[:10]
    
    # Statistiken
    kosten_summe_monat = Verwaltungskosten.objects.filter(
        datum__gte=vor_30_tagen
    ).aggregate(total=Sum('betrag'))['total'] or 0
    
    kosten_statistik = Verwaltungskosten.objects.filter(
        datum__gte=vor_30_tagen
    ).values('kategorie').annotate(
        summe=Sum('betrag'),
        anzahl=Count('id')
    ).order_by('-summe')
    
    context = {
        'rentmeister': rentmeister,
        'konten': konten,
        'gesamtsaldo': gesamtsaldo,
        'aktuelle_kosten': aktuelle_kosten,
        'kosten_summe_monat': kosten_summe_monat,
        'kosten_statistik': kosten_statistik,
    }
    
    return render(request, 'stiftung/geschaeftsfuehrung.html', context)


@login_required
def konto_list(request):
    """Liste aller Stiftungskonten"""
    from stiftung.models import StiftungsKonto
    from django.db.models import Sum
    
    konten = StiftungsKonto.objects.all().order_by('bank_name', 'kontoname')
    gesamtsaldo = konten.aggregate(total=Sum('saldo'))['total'] or 0
    
    context = {
        'konten': konten,
        'gesamtsaldo': gesamtsaldo,
    }
    
    return render(request, 'stiftung/konto_list.html', context)


@login_required 
def verwaltungskosten_list(request):
    """Liste aller Verwaltungskosten"""
    from stiftung.models import Verwaltungskosten
    from django.core.paginator import Paginator
    
    kosten = Verwaltungskosten.objects.all().order_by('-datum', '-erstellt_am')
    
    # Filter nach Kategorie
    kategorie_filter = request.GET.get('kategorie')
    if kategorie_filter:
        kosten = kosten.filter(kategorie=kategorie_filter)
    
    # Filter nach Status
    status_filter = request.GET.get('status')
    if status_filter:
        kosten = kosten.filter(status=status_filter)
    
    # Pagination
    paginator = Paginator(kosten, 25)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    # Für Filter-Dropdowns
    kategorien = Verwaltungskosten.KATEGORIE_CHOICES
    status_choices = Verwaltungskosten.STATUS_CHOICES
    
    context = {
        'page_obj': page_obj,
        'kategorien': kategorien,
        'status_choices': status_choices,
        'kategorie_filter': kategorie_filter,
        'status_filter': status_filter,
    }
    
    return render(request, 'stiftung/verwaltungskosten_list.html', context)


@login_required
def rentmeister_list(request):
    """Liste aller Rentmeister"""
    from stiftung.models import Rentmeister
    
    rentmeister = Rentmeister.objects.all().order_by('nachname', 'vorname')
    
    # Aktive/Inaktive aufteilen
    aktive_rentmeister = rentmeister.filter(aktiv=True)
    ehemalige_rentmeister = rentmeister.filter(aktiv=False)
    
    context = {
        'aktive_rentmeister': aktive_rentmeister,
        'ehemalige_rentmeister': ehemalige_rentmeister,
        'total_count': rentmeister.count(),
    }
    
    return render(request, 'stiftung/rentmeister_list.html', context)


@login_required
def rentmeister_detail(request, pk):
    """Detailansicht eines Rentmeisters mit seinen Ausgaben"""
    from stiftung.models import Rentmeister, Verwaltungskosten
    from django.db.models import Sum, Count, Q
    from datetime import datetime, timedelta
    
    rentmeister = get_object_or_404(Rentmeister, pk=pk)
    
    # Ausgaben des Rentmeisters
    ausgaben = Verwaltungskosten.objects.filter(rentmeister=rentmeister).order_by('-datum')
    
    # Statistiken
    heute = datetime.now().date()
    aktueller_monat = heute.replace(day=1)
    aktuelles_jahr = heute.replace(month=1, day=1)
    
    stats = {
        'gesamt_ausgaben': ausgaben.aggregate(total=Sum('betrag'))['total'] or 0,
        'monat_ausgaben': ausgaben.filter(datum__gte=aktueller_monat).aggregate(total=Sum('betrag'))['total'] or 0,
        'jahr_ausgaben': ausgaben.filter(datum__gte=aktuelles_jahr).aggregate(total=Sum('betrag'))['total'] or 0,
        'anzahl_ausgaben': ausgaben.count(),
        'offene_ausgaben': ausgaben.exclude(status='bezahlt').count(),
    }
    
    # Kategorie-Aufschlüsselung
    kategorie_stats = ausgaben.values('kategorie').annotate(
        summe=Sum('betrag'),
        anzahl=Count('id')
    ).order_by('-summe')
    
    # Aktuelle Ausgaben (letzten 30 Tage)
    vor_30_tagen = heute - timedelta(days=30)
    aktuelle_ausgaben = ausgaben.filter(datum__gte=vor_30_tagen)[:10]
    
    # Verknüpfte Dokumente laden
    from stiftung.models import DokumentLink
    verknuepfte_dokumente = DokumentLink.objects.filter(
        rentmeister_id=rentmeister.id
    ).order_by('-id')[:10]  # Neueste 10 Dokumente
    
    context = {
        'rentmeister': rentmeister,
        'ausgaben': ausgaben[:20],  # Nur erste 20 für Übersicht
        'stats': stats,
        'kategorie_stats': kategorie_stats,
        'aktuelle_ausgaben': aktuelle_ausgaben,
        'verknuepfte_dokumente': verknuepfte_dokumente,
    }
    
    return render(request, 'stiftung/rentmeister_detail.html', context)


@login_required
def rentmeister_ausgaben(request, pk):
    """Vollständige Ausgabenliste eines Rentmeisters mit PDF Export"""
    from stiftung.models import Rentmeister, Verwaltungskosten
    from django.core.paginator import Paginator
    from django.db.models import Sum, Count, Q
    from django.db import models
    
    rentmeister = get_object_or_404(Rentmeister, pk=pk)
    
    # Handle PDF export request
    if request.method == 'POST' and 'export_pdf' in request.POST:
        selected_ids = request.POST.getlist('selected_expenses')
        if selected_ids:
            # Update status to 'in_bearbeitung' and log each change
            from stiftung.audit import log_action
            expenses_to_update = Verwaltungskosten.objects.filter(
                id__in=selected_ids, 
                rentmeister=rentmeister
            )
            
            updated_count = 0
            for expense in expenses_to_update:
                old_status = expense.status
                expense.status = 'in_bearbeitung'
                expense.save()
                updated_count += 1
                
                # Log the status change
                log_action(
                    request=request,
                    action='update',
                    entity_type='verwaltungskosten',
                    entity_id=str(expense.pk),
                    entity_name=expense.bezeichnung,
                    description=f'Ausgaben-Status für PDF-Export geändert von "{old_status}" zu "in_bearbeitung"',
                    changes={'status': {'old': old_status, 'new': 'in_bearbeitung'}}
                )
                
            messages.success(request, f'{updated_count} Ausgaben wurden zur Bearbeitung markiert und sind bereit für PDF Export.')
            return redirect('stiftung:rentmeister_ausgaben_pdf', pk=pk, expense_ids=','.join(selected_ids))
    
    # Get expenses grouped by status
    ausgaben_by_status = {}
    for status_code, status_name in Verwaltungskosten.STATUS_CHOICES:
        ausgaben_by_status[status_code] = {
            'name': status_name,
            'ausgaben': Verwaltungskosten.objects.filter(
                rentmeister=rentmeister, 
                status=status_code
            ).order_by('-datum', '-erstellt_am'),
            'total': Verwaltungskosten.objects.filter(
                rentmeister=rentmeister, 
                status=status_code
            ).aggregate(total=Sum('betrag'))['total'] or 0
        }
    
    # Get statistics
    stats = Verwaltungskosten.objects.filter(rentmeister=rentmeister).aggregate(
        total_count=Count('id'),
        total_amount=Sum('betrag'),
        geplant_count=Count('id', filter=Q(status='geplant')),
        geplant_amount=Sum('betrag', filter=Q(status='geplant')),
        in_bearbeitung_count=Count('id', filter=Q(status='in_bearbeitung')),
        in_bearbeitung_amount=Sum('betrag', filter=Q(status='in_bearbeitung')),
        bezahlt_count=Count('id', filter=Q(status='bezahlt')),
        bezahlt_amount=Sum('betrag', filter=Q(status='bezahlt')),
    )
    
    context = {
        'rentmeister': rentmeister,
        'ausgaben_by_status': ausgaben_by_status,
        'stats': stats,
        'kategorien': Verwaltungskosten.KATEGORIE_CHOICES,
        'status_choices': Verwaltungskosten.STATUS_CHOICES,
    }
    
    return render(request, 'stiftung/rentmeister_ausgaben.html', context)


@login_required
def rentmeister_create(request):
    """Erstelle einen neuen Rentmeister"""
    from stiftung.forms import RentmeisterForm
    
    if request.method == 'POST':
        form = RentmeisterForm(request.POST)
        if form.is_valid():
            rentmeister = form.save()
            messages.success(request, f'Rentmeister {rentmeister.get_full_name()} wurde erfolgreich angelegt.')
            return redirect('stiftung:rentmeister_detail', pk=rentmeister.pk)
    else:
        form = RentmeisterForm()
    
    context = {
        'form': form,
        'title': 'Neuen Rentmeister anlegen',
        'submit_text': 'Rentmeister anlegen',
    }
    
    return render(request, 'stiftung/rentmeister_form.html', context)


@login_required
def rentmeister_edit(request, pk):
    """Bearbeite einen bestehenden Rentmeister"""
    from stiftung.forms import RentmeisterForm
    from stiftung.models import Rentmeister
    
    rentmeister = get_object_or_404(Rentmeister, pk=pk)
    
    if request.method == 'POST':
        form = RentmeisterForm(request.POST, instance=rentmeister)
        if form.is_valid():
            rentmeister = form.save()
            messages.success(request, f'Rentmeister {rentmeister.get_full_name()} wurde erfolgreich aktualisiert.')
            return redirect('stiftung:rentmeister_detail', pk=rentmeister.pk)
    else:
        form = RentmeisterForm(instance=rentmeister)
    
    context = {
        'form': form,
        'rentmeister': rentmeister,
        'title': f'{rentmeister.get_full_name()} bearbeiten',
        'submit_text': 'Änderungen speichern',
    }
    
    return render(request, 'stiftung/rentmeister_form.html', context)


@login_required
def konto_create(request):
    """Erstelle ein neues Stiftungskonto"""
    from stiftung.forms import StiftungsKontoForm
    
    if request.method == 'POST':
        form = StiftungsKontoForm(request.POST)
        if form.is_valid():
            konto = form.save()
            messages.success(request, f'Konto {konto.kontoname} wurde erfolgreich angelegt.')
            return redirect('stiftung:konto_list')
    else:
        form = StiftungsKontoForm()
    
    context = {
        'form': form,
        'title': 'Neues Konto anlegen',
        'submit_text': 'Konto anlegen',
    }
    
    return render(request, 'stiftung/konto_form.html', context)


@login_required
def konto_edit(request, pk):
    """Bearbeite ein bestehendes Stiftungskonto"""
    from stiftung.forms import StiftungsKontoForm
    from stiftung.models import StiftungsKonto
    
    konto = get_object_or_404(StiftungsKonto, pk=pk)
    
    if request.method == 'POST':
        form = StiftungsKontoForm(request.POST, instance=konto)
        if form.is_valid():
            konto = form.save()
            messages.success(request, f'Konto {konto.kontoname} wurde erfolgreich aktualisiert.')
            return redirect('stiftung:konto_list')
    else:
        form = StiftungsKontoForm(instance=konto)
    
    context = {
        'form': form,
        'konto': konto,
        'title': f'Konto {konto.kontoname} bearbeiten',
        'submit_text': 'Änderungen speichern',
    }
    
    return render(request, 'stiftung/konto_form.html', context)


@login_required
def konto_detail(request, pk):
    """Zeige Details eines Stiftungskontos"""
    from stiftung.models import StiftungsKonto, BankTransaction
    from django.db.models import Sum, Count, Max, Q
    from django.db import models
    
    konto = get_object_or_404(StiftungsKonto, pk=pk)
    
    # Get transaction statistics
    transactions = BankTransaction.objects.filter(konto=konto)
    transaction_stats = transactions.aggregate(
        total_count=Count('id'),
        total_eingang=Sum('betrag', filter=Q(betrag__gt=0)),
        total_ausgang=Sum('betrag', filter=Q(betrag__lt=0)),
        last_transaction_date=Max('datum')
    )
    
    # Recent transactions
    recent_transactions = transactions.order_by('-datum', '-importiert_am')[:10]
    
    context = {
        'konto': konto,
        'transaction_stats': transaction_stats,
        'recent_transactions': recent_transactions,
    }
    
    return render(request, 'stiftung/konto_detail.html', context)


@login_required
def verwaltungskosten_create(request):
    """Erstelle neue Verwaltungskosten"""
    from stiftung.forms import VerwaltungskostenForm
    from stiftung.models import Rentmeister
    
    # Check if we're coming from a specific Rentmeister
    rentmeister_id = request.GET.get('rentmeister')
    initial_data = {}
    redirect_url = 'stiftung:verwaltungskosten_list'
    
    if rentmeister_id:
        try:
            rentmeister = Rentmeister.objects.get(pk=rentmeister_id)
            initial_data['rentmeister'] = rentmeister
            redirect_url = 'stiftung:rentmeister_detail'
            redirect_args = [rentmeister_id]
        except Rentmeister.DoesNotExist:
            pass
    
    if request.method == 'POST':
        form = VerwaltungskostenForm(request.POST)
        if form.is_valid():
            kosten = form.save()
            messages.success(request, f'Verwaltungskosten "{kosten.bezeichnung}" wurden erfolgreich angelegt.')
            if rentmeister_id:
                return redirect(redirect_url, pk=rentmeister_id)
            return redirect('stiftung:verwaltungskosten_list')
    else:
        form = VerwaltungskostenForm(initial=initial_data)
    
    context = {
        'form': form,
        'title': 'Neue Verwaltungskosten anlegen',
        'submit_text': 'Kosten anlegen',
    }
    
    return render(request, 'stiftung/verwaltungskosten_form.html', context)


@login_required
def verwaltungskosten_edit(request, pk):
    """Bearbeite bestehende Verwaltungskosten"""
    from stiftung.forms import VerwaltungskostenForm
    from stiftung.models import Verwaltungskosten
    
    verwaltungskosten = get_object_or_404(Verwaltungskosten, pk=pk)
    
    if request.method == 'POST':
        form = VerwaltungskostenForm(request.POST, instance=verwaltungskosten)
        if form.is_valid():
            verwaltungskosten = form.save()
            messages.success(request, f'Verwaltungskosten "{verwaltungskosten.bezeichnung}" wurden erfolgreich aktualisiert.')
            return redirect('stiftung:verwaltungskosten_list')
    else:
        form = VerwaltungskostenForm(instance=verwaltungskosten)
    
    context = {
        'form': form,
        'verwaltungskosten': verwaltungskosten,
        'title': f'Verwaltungskosten bearbeiten: {verwaltungskosten.bezeichnung}',
        'submit_text': 'Änderungen speichern',
    }
    
    return render(request, 'stiftung/verwaltungskosten_form.html', context)


@login_required
def mark_expense_paid(request):
    """Markiere eine Ausgabe als bezahlt"""
    if request.method == 'POST':
        expense_id = request.POST.get('expense_id')
        if expense_id:
            try:
                from stiftung.models import Verwaltungskosten
                expense = Verwaltungskosten.objects.get(pk=expense_id)
                old_status = expense.status
                expense.status = 'bezahlt'
                expense.save()
                
                # Log the status change
                from stiftung.audit import log_action
                log_action(
                    request=request,
                    action='update',
                    entity_type='verwaltungskosten',
                    entity_id=str(expense.pk),
                    entity_name=expense.bezeichnung,
                    description=f'Ausgaben-Status geändert von "{old_status}" zu "bezahlt"',
                    changes={'status': {'old': old_status, 'new': 'bezahlt'}}
                )
                
                messages.success(request, f'Ausgabe "{expense.bezeichnung}" wurde als bezahlt markiert.')
                return redirect('stiftung:rentmeister_ausgaben', pk=expense.rentmeister.pk)
            except Verwaltungskosten.DoesNotExist:
                messages.error(request, 'Ausgabe nicht gefunden.')
    
    return redirect('stiftung:verwaltungskosten_list')


# =============================================================================
# ADMINISTRATION VIEWS 
# =============================================================================

@login_required
def administration(request):
    """Administration Dashboard"""
    from stiftung.models import AuditLog, BackupJob
    from django.db.models import Count
    from datetime import datetime, timedelta
    
    # Recent audit activity
    recent_audit = AuditLog.objects.all()[:10]
    
    # Audit statistics
    heute = datetime.now().date()
    stats = {
        'total_logs': AuditLog.objects.count(),
        'logs_today': AuditLog.objects.filter(timestamp__date=heute).count(),
        'logs_week': AuditLog.objects.filter(timestamp__gte=heute - timedelta(days=7)).count(),
        'recent_backups': BackupJob.objects.all()[:5],
        'last_backup': BackupJob.objects.filter(status='completed').first(),
    }
    
    # User activity summary
    user_activity = AuditLog.objects.values('username').annotate(
        count=Count('id')
    ).order_by('-count')[:10]
    
    context = {
        'recent_audit': recent_audit,
        'stats': stats,
        'user_activity': user_activity,
    }
    
    return render(request, 'stiftung/administration.html', context)


@login_required
def unterstuetzungen_list(request):
    """Liste der Destinatärunterstützungen (Administration)."""
    status = request.GET.get('status', '')
    export_format = request.POST.get('format') if request.method == 'POST' else request.GET.get('format', '')
    selected_ids_param = request.POST.get('selected_entries', '') if request.method == 'POST' else request.GET.get('selected_entries', '')
    selected_ids = [id for id in selected_ids_param.split(',') if id] if selected_ids_param else []
    
    qs = DestinataerUnterstuetzung.objects.select_related(
        'destinataer', 'konto', 'ausgezahlt_von', 'wiederkehrend_von'
    ).order_by('-faellig_am', 'destinataer__nachname')
    
    if status:
        qs = qs.filter(status=status)
    
    # Enhanced CSV export with field selection
    if export_format == 'csv':
        return export_unterstuetzungen_csv(request, qs, selected_ids)
    
    # Enhanced PDF export with corporate identity
    elif export_format == 'pdf':
        return export_unterstuetzungen_pdf(request, qs, selected_ids)
    context = {
        'unterstuetzungen': qs,
        'status_filter': status,
    }
    return render(request, 'stiftung/unterstuetzungen_list.html', context)


def export_unterstuetzungen_csv(request, queryset, selected_ids=None):
    """Enhanced CSV export with field selection"""
    import csv
    from django.http import HttpResponse
    from datetime import datetime
    
    # If specific entries are selected, filter to only those
    if selected_ids:
        queryset = queryset.filter(id__in=selected_ids)
    
    # Get selected fields from request (default to all if none specified)
    selected_fields_param = request.POST.get('selected_fields', '') if request.method == 'POST' else request.GET.get('selected_fields', '')
    selected_fields = selected_fields_param.split(',') if selected_fields_param else []
    
    if not selected_fields:
        # Default field set
        selected_fields = [
            'destinataer_name', 'betrag', 'faellig_am', 'status', 
            'empfaenger_iban', 'empfaenger_name', 'beschreibung'
        ]
    
    # Field definitions with headers and data extraction
    field_definitions = {
        # Core payment fields
        'id': ('ID', lambda u: str(u.id)),
        'betrag': ('Betrag (€)', lambda u: f"{u.betrag:.2f}"),
        'faellig_am': ('Fällig am', lambda u: u.faellig_am.strftime('%d.%m.%Y') if u.faellig_am else ''),
        'status': ('Status', lambda u: u.get_status_display()),
        'beschreibung': ('Beschreibung', lambda u: u.beschreibung or ''),
        'ausgezahlt_am': ('Ausgezahlt am', lambda u: u.ausgezahlt_am.strftime('%d.%m.%Y') if u.ausgezahlt_am else ''),
        'erstellt_am': ('Erstellt am', lambda u: u.erstellt_am.strftime('%d.%m.%Y %H:%M') if u.erstellt_am else ''),
        'aktualisiert_am': ('Aktualisiert am', lambda u: u.aktualisiert_am.strftime('%d.%m.%Y %H:%M') if u.aktualisiert_am else ''),
        
        # Destinataer fields
        'destinataer_name': ('Destinatär Name', lambda u: u.destinataer.get_full_name() if u.destinataer else ''),
        'destinataer_vorname': ('Vorname', lambda u: u.destinataer.vorname if u.destinataer else ''),
        'destinataer_nachname': ('Nachname', lambda u: u.destinataer.nachname if u.destinataer else ''),
        'familienzweig': ('Familienzweig', lambda u: u.destinataer.familienzweig if u.destinataer else ''),
        'geburtsdatum': ('Geburtsdatum', lambda u: u.destinataer.geburtsdatum.strftime('%d.%m.%Y') if u.destinataer and u.destinataer.geburtsdatum else ''),
        'email': ('E-Mail', lambda u: u.destinataer.email if u.destinataer else ''),
        'telefon': ('Telefon', lambda u: u.destinataer.telefon if u.destinataer else ''),
        'destinataer_iban': ('Destinatär IBAN', lambda u: u.destinataer.iban if u.destinataer else ''),
        'strasse': ('Straße', lambda u: u.destinataer.strasse if u.destinataer else ''),
        'plz': ('PLZ', lambda u: u.destinataer.plz if u.destinataer else ''),
        'ort': ('Ort', lambda u: u.destinataer.ort if u.destinataer else ''),
        'adresse': ('Adresse', lambda u: f"{u.destinataer.strasse}, {u.destinataer.plz} {u.destinataer.ort}".strip(', ') if u.destinataer else ''),
        'berufsgruppe': ('Berufsgruppe', lambda u: u.destinataer.berufsgruppe if u.destinataer else ''),
        'ausbildungsstand': ('Ausbildungsstand', lambda u: u.destinataer.ausbildungsstand if u.destinataer else ''),
        'institution': ('Institution', lambda u: u.destinataer.institution if u.destinataer else ''),
        'jaehrliches_einkommen': ('Jährliches Einkommen (€)', lambda u: f"{u.destinataer.jaehrliches_einkommen:.2f}" if u.destinataer and u.destinataer.jaehrliches_einkommen else ''),
        'haushaltsgroesse': ('Haushaltsgröße', lambda u: str(u.destinataer.haushaltsgroesse) if u.destinataer and u.destinataer.haushaltsgroesse else ''),
        'monatliche_bezuege': ('Monatliche Bezüge (€)', lambda u: f"{u.destinataer.monatliche_bezuege:.2f}" if u.destinataer and u.destinataer.monatliche_bezuege else ''),
        'vermoegen': ('Vermögen (€)', lambda u: f"{u.destinataer.vermoegen:.2f}" if u.destinataer and u.destinataer.vermoegen else ''),
        
        # Payment details
        'empfaenger_iban': ('Empfänger IBAN', lambda u: u.empfaenger_iban or ''),
        'empfaenger_name': ('Empfänger Name', lambda u: u.empfaenger_name or ''),
        'verwendungszweck': ('Verwendungszweck', lambda u: u.verwendungszweck or ''),
        
        # Account fields
        'konto_name': ('Konto', lambda u: str(u.konto) if u.konto else ''),
        'konto_bank': ('Bank', lambda u: u.konto.bank_name if u.konto else ''),
        'konto_iban': ('Konto IBAN', lambda u: u.konto.iban if u.konto else ''),
        
        # System fields
        'ausgezahlt_von': ('Ausgezahlt von', lambda u: u.ausgezahlt_von.get_full_name() if u.ausgezahlt_von else ''),
        'ist_wiederkehrend': ('Wiederkehrend', lambda u: 'Ja' if u.wiederkehrend_von else 'Nein'),
    }
    
    # Create CSV response
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    filename = f'unterstuetzungen_{timestamp}.csv'
    
    response = HttpResponse(content_type='text/csv; charset=utf-8')
    response['Content-Disposition'] = f'attachment; filename="{filename}"'
    
    writer = csv.writer(response, delimiter=';', quoting=csv.QUOTE_ALL)
    
    # Write headers
    headers = [field_definitions[field][0] for field in selected_fields if field in field_definitions]
    writer.writerow(headers)
    
    # Write data rows
    for u in queryset:
        row = []
        for field in selected_fields:
            if field in field_definitions:
                try:
                    value = field_definitions[field][1](u)
                    row.append(value)
                except Exception:
                    row.append('')  # Fallback for any errors
            else:
                row.append('')  # Unknown field
        writer.writerow(row)
    
    return response


def export_unterstuetzungen_pdf(request, queryset, selected_ids=None):
    """Enhanced PDF export with corporate identity and field selection"""
    # If specific entries are selected, filter to only those
    if selected_ids:
        queryset = queryset.filter(id__in=selected_ids)
    
    # Get selected fields from request (default to key fields if none specified)
    selected_fields_param = request.POST.get('selected_fields', '') if request.method == 'POST' else request.GET.get('selected_fields', '')
    selected_fields = selected_fields_param.split(',') if selected_fields_param else []
    
    if not selected_fields:
        # Default field set for PDF (fewer fields than CSV for better readability)
        selected_fields = [
            'destinataer_name', 'betrag', 'faellig_am', 'status', 
            'beschreibung', 'ausgezahlt_am'
        ]
    
    # Field definitions with display names (reuse from CSV but select PDF-appropriate subset)
    field_definitions = {
        # Core payment fields
        'destinataer_name': 'Destinatär',
        'betrag': 'Betrag (€)',
        'faellig_am': 'Fällig am',
        'status': 'Status',
        'beschreibung': 'Beschreibung',
        'ausgezahlt_am': 'Ausgezahlt am',
        'erstellt_am': 'Erstellt am',
        'empfaenger_iban': 'Empfänger IBAN',
        'empfaenger_name': 'Empfänger',
        'verwendungszweck': 'Verwendungszweck',
        'konto_name': 'Konto',
        'ist_wiederkehrend': 'Wiederkehrend',
    }
    
    # Filter to only include fields that are both selected and defined
    filtered_fields = {k: v for k, v in field_definitions.items() if k in selected_fields}
    
    # Prepare data with field extraction logic
    data_for_pdf = []
    for item in queryset:
        row_data = {}
        for field_key in filtered_fields.keys():
            try:
                if field_key == 'destinataer_name':
                    row_data[field_key] = item.destinataer.get_full_name() if item.destinataer else ''
                elif field_key == 'betrag':
                    row_data[field_key] = f"€{item.betrag:.2f}" if item.betrag else ''
                elif field_key == 'faellig_am':
                    row_data[field_key] = item.faellig_am.strftime('%d.%m.%Y') if item.faellig_am else ''
                elif field_key == 'status':
                    row_data[field_key] = item.get_status_display()
                elif field_key == 'beschreibung':
                    row_data[field_key] = item.beschreibung or ''
                elif field_key == 'ausgezahlt_am':
                    row_data[field_key] = item.ausgezahlt_am.strftime('%d.%m.%Y') if item.ausgezahlt_am else ''
                elif field_key == 'erstellt_am':
                    row_data[field_key] = item.erstellt_am.strftime('%d.%m.%Y') if item.erstellt_am else ''
                elif field_key == 'empfaenger_iban':
                    row_data[field_key] = item.empfaenger_iban or ''
                elif field_key == 'empfaenger_name':
                    row_data[field_key] = item.empfaenger_name or ''
                elif field_key == 'verwendungszweck':
                    row_data[field_key] = item.verwendungszweck or ''
                elif field_key == 'konto_name':
                    row_data[field_key] = str(item.konto) if item.konto else ''
                elif field_key == 'ist_wiederkehrend':
                    row_data[field_key] = 'Ja' if item.wiederkehrend_von else 'Nein'
                else:
                    # Generic field access
                    row_data[field_key] = getattr(item, field_key, '') or ''
            except Exception:
                row_data[field_key] = ''  # Fallback for any errors
        
        data_for_pdf.append(row_data)
    
    # Use PDF generator
    pdf_gen = get_pdf_generator()
    return pdf_gen.export_data_list_pdf(
        data=data_for_pdf,
        fields_config=filtered_fields,
        title="Unterstützungen Export",
        filename_prefix="unterstuetzungen",
        request_user=request.user
    )


def export_foerderungen_csv(request, queryset, selected_ids=None):
    """Enhanced CSV export for Förderungen with field selection"""
    import csv
    from django.http import HttpResponse
    from datetime import datetime
    
    # If specific entries are selected, filter to only those
    if selected_ids:
        queryset = queryset.filter(id__in=selected_ids)
    
    # Get selected fields from request (default to all if none specified)
    selected_fields_param = request.POST.get('selected_fields', '') if request.method == 'POST' else request.GET.get('selected_fields', '')
    selected_fields = selected_fields_param.split(',') if selected_fields_param else []
    
    if not selected_fields:
        # Default field set
        selected_fields = [
            'destinataer_name', 'jahr', 'betrag', 'kategorie', 'status', 
            'antragsdatum', 'beschreibung'
        ]
    
    # Field definitions with headers and data extraction
    field_definitions = {
        # Core fields
        'id': ('ID', lambda f: str(f.id)),
        'destinataer_name': ('Destinatär Name', lambda f: f.destinataer.get_full_name() if f.destinataer else ''),
        'jahr': ('Jahr', lambda f: str(f.jahr)),
        'betrag': ('Betrag (€)', lambda f: f"{f.betrag:.2f}"),
        'kategorie': ('Kategorie', lambda f: f.get_kategorie_display()),
        'status': ('Status', lambda f: f.get_status_display()),
        'antragsdatum': ('Antragsdatum', lambda f: f.antragsdatum.strftime('%d.%m.%Y') if f.antragsdatum else ''),
        'bewilligungsdatum': ('Bewilligungsdatum', lambda f: f.bewilligungsdatum.strftime('%d.%m.%Y') if f.bewilligungsdatum else ''),
        'auszahlungsdatum': ('Auszahlungsdatum', lambda f: f.auszahlungsdatum.strftime('%d.%m.%Y') if f.auszahlungsdatum else ''),
        'beschreibung': ('Beschreibung', lambda f: f.beschreibung or ''),
        'begruendung': ('Begründung', lambda f: f.begruendung or ''),
        'verwendungsnachweis_datum': ('Verwendungsnachweis Datum', lambda f: f.verwendungsnachweis_datum.strftime('%d.%m.%Y') if f.verwendungsnachweis_datum else ''),
        'verwendungsnachweis_status': ('Verwendungsnachweis Status', lambda f: f.get_verwendungsnachweis_status_display() if f.verwendungsnachweis_status else ''),
        
        # Destinataer fields
        'destinataer_vorname': ('Vorname', lambda f: f.destinataer.vorname if f.destinataer else ''),
        'destinataer_nachname': ('Nachname', lambda f: f.destinataer.nachname if f.destinataer else ''),
        'familienzweig': ('Familienzweig', lambda f: f.destinataer.familienzweig if f.destinataer else ''),
        'email': ('E-Mail', lambda f: f.destinataer.email if f.destinataer else ''),
        'telefon': ('Telefon', lambda f: f.destinataer.telefon if f.destinataer else ''),
        'adresse': ('Adresse', lambda f: f"{f.destinataer.strasse}, {f.destinataer.plz} {f.destinataer.ort}".strip(', ') if f.destinataer else ''),
        'berufsgruppe': ('Berufsgruppe', lambda f: f.destinataer.berufsgruppe if f.destinataer else ''),
        'ausbildungsstand': ('Ausbildungsstand', lambda f: f.destinataer.ausbildungsstand if f.destinataer else ''),
        'institution': ('Institution', lambda f: f.destinataer.institution if f.destinataer else ''),
        
        # System fields
        'erstellt_am': ('Erstellt am', lambda f: f.erstellt_am.strftime('%d.%m.%Y %H:%M') if f.erstellt_am else ''),
        'aktualisiert_am': ('Aktualisiert am', lambda f: f.aktualisiert_am.strftime('%d.%m.%Y %H:%M') if f.aktualisiert_am else ''),
    }
    
    # Create CSV response
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    filename = f'foerderungen_{timestamp}.csv'
    
    response = HttpResponse(content_type='text/csv; charset=utf-8')
    response['Content-Disposition'] = f'attachment; filename="{filename}"'
    
    writer = csv.writer(response, delimiter=';', quoting=csv.QUOTE_ALL)
    
    # Write headers
    headers = [field_definitions[field][0] for field in selected_fields if field in field_definitions]
    writer.writerow(headers)
    
    # Write data rows
    for f in queryset:
        row = []
        for field in selected_fields:
            if field in field_definitions:
                try:
                    value = field_definitions[field][1](f)
                    row.append(value)
                except Exception:
                    row.append('')  # Fallback for any errors
            else:
                row.append('')  # Unknown field
        writer.writerow(row)
    
    return response


def export_foerderungen_pdf(request, queryset, selected_ids=None):
    """Enhanced PDF export for Förderungen with corporate identity and field selection"""
    # If specific entries are selected, filter to only those
    if selected_ids:
        queryset = queryset.filter(id__in=selected_ids)
    
    # Get selected fields from request (default to key fields if none specified)
    selected_fields_param = request.POST.get('selected_fields', '') if request.method == 'POST' else request.GET.get('selected_fields', '')
    selected_fields = selected_fields_param.split(',') if selected_fields_param else []
    
    if not selected_fields:
        # Default field set for PDF (fewer fields than CSV for better readability)
        selected_fields = [
            'destinataer_name', 'jahr', 'betrag', 'kategorie', 'status', 
            'antragsdatum'
        ]
    
    # Field definitions with display names
    field_definitions = {
        'destinataer_name': 'Destinatär',
        'jahr': 'Jahr',
        'betrag': 'Betrag (€)',
        'kategorie': 'Kategorie',
        'status': 'Status',
        'antragsdatum': 'Antragsdatum',
        'bewilligungsdatum': 'Bewilligungsdatum',
        'auszahlungsdatum': 'Auszahlungsdatum',
        'beschreibung': 'Beschreibung',
        'begruendung': 'Begründung',
        'verwendungsnachweis_status': 'Verwendungsnachweis',
    }
    
    # Filter to only include fields that are both selected and defined
    filtered_fields = {k: v for k, v in field_definitions.items() if k in selected_fields}
    
    # Prepare data with field extraction logic
    data_for_pdf = []
    for item in queryset:
        row_data = {}
        for field_key in filtered_fields.keys():
            try:
                if field_key == 'destinataer_name':
                    row_data[field_key] = item.destinataer.get_full_name() if item.destinataer else ''
                elif field_key == 'jahr':
                    row_data[field_key] = str(item.jahr)
                elif field_key == 'betrag':
                    row_data[field_key] = f"€{item.betrag:.2f}" if item.betrag else ''
                elif field_key == 'kategorie':
                    row_data[field_key] = item.get_kategorie_display()
                elif field_key == 'status':
                    row_data[field_key] = item.get_status_display()
                elif field_key == 'antragsdatum':
                    row_data[field_key] = item.antragsdatum.strftime('%d.%m.%Y') if item.antragsdatum else ''
                elif field_key == 'bewilligungsdatum':
                    row_data[field_key] = item.bewilligungsdatum.strftime('%d.%m.%Y') if item.bewilligungsdatum else ''
                elif field_key == 'auszahlungsdatum':
                    row_data[field_key] = item.auszahlungsdatum.strftime('%d.%m.%Y') if item.auszahlungsdatum else ''
                elif field_key == 'beschreibung':
                    row_data[field_key] = (item.beschreibung or '')[:100] + ('...' if len(item.beschreibung or '') > 100 else '')
                elif field_key == 'begruendung':
                    row_data[field_key] = (item.begruendung or '')[:100] + ('...' if len(item.begruendung or '') > 100 else '')
                elif field_key == 'verwendungsnachweis_status':
                    row_data[field_key] = item.get_verwendungsnachweis_status_display() if item.verwendungsnachweis_status else ''
                else:
                    # Generic field access
                    row_data[field_key] = getattr(item, field_key, '') or ''
            except Exception:
                row_data[field_key] = ''  # Fallback for any errors
        
        data_for_pdf.append(row_data)
    
    # Use PDF generator
    pdf_gen = get_pdf_generator()
    return pdf_gen.export_data_list_pdf(
        data=data_for_pdf,
        fields_config=filtered_fields,
        title="Förderungen Export",
        filename_prefix="foerderungen",
        request_user=request.user
    )


@login_required
def unterstuetzung_edit(request, pk):
    obj = get_object_or_404(DestinataerUnterstuetzung, pk=pk)
    if request.method == 'POST':
        form = DestinataerUnterstuetzungForm(request.POST, instance=obj)
        if form.is_valid():
            form.save()
            messages.success(request, 'Unterstützung aktualisiert.')
            return redirect('stiftung:unterstuetzungen_list')
    else:
        form = DestinataerUnterstuetzungForm(instance=obj)
    return render(request, 'stiftung/unterstuetzung_form.html', {'form': form, 'title': 'Unterstützung bearbeiten'})


@login_required
def unterstuetzung_delete(request, pk):
    obj = get_object_or_404(DestinataerUnterstuetzung, pk=pk)
    
    # Check if this will also delete the recurring template
    will_delete_template = False
    if obj.wiederkehrend_von:
        andere_zahlungen = DestinataerUnterstuetzung.objects.filter(
            wiederkehrend_von=obj.wiederkehrend_von
        ).exclude(pk=pk).exists()
        will_delete_template = not andere_zahlungen
    
    if request.method == 'POST':
        # Check if this support payment is linked to a recurring payment template
        wiederkehrend_template = obj.wiederkehrend_von
        
        # Delete the support payment
        obj.delete()
        
        # If this was generated from a recurring template and there are no other
        # payments from this template, delete the template too
        if wiederkehrend_template:
            # Check if there are other payments from this recurring template
            andere_zahlungen = DestinataerUnterstuetzung.objects.filter(
                wiederkehrend_von=wiederkehrend_template
            ).exists()
            
            # If no other payments exist from this template, delete the template too
            if not andere_zahlungen:
                wiederkehrend_template.delete()
                messages.success(request, 'Unterstützung und wiederkehrende Zahlungsvorlage gelöscht.')
            else:
                messages.success(request, 'Unterstützung gelöscht.')
        else:
            messages.success(request, 'Unterstützung gelöscht.')
            
        return redirect('stiftung:unterstuetzungen_list')
    
    context = {
        'obj': obj,
        'will_delete_template': will_delete_template,
    }
    return render(request, 'stiftung/unterstuetzung_confirm_delete.html', context)


@login_required
def destinataer_notiz_create(request, pk):
    destinataer = get_object_or_404(Destinataer, pk=pk)
    if request.method == 'POST':
        form = DestinataerNotizForm(request.POST, request.FILES)
        if form.is_valid():
            note = form.save(commit=False)
            note.destinataer = destinataer
            note.erstellt_von = request.user
            note.save()
            messages.success(request, 'Notiz wurde gespeichert.')
            return redirect('stiftung:destinataer_detail', pk=destinataer.pk)
        else:
            # Debug: show what validation failed
            for field, errors in form.errors.items():
                messages.error(request, f'Fehler in {field}: {", ".join(errors)}')
    else:
        form = DestinataerNotizForm()
    return render(request, 'stiftung/destinataer_notiz_form.html', {'form': form, 'destinataer': destinataer, 'title': 'Notiz hinzufügen'})


@login_required
def destinataer_export(request, pk):
    """Export complete Destinatär data as ZIP with documents"""
    import zipfile
    import json
    import tempfile
    import os
    from django.http import HttpResponse
    
    destinataer = get_object_or_404(Destinataer, pk=pk)
    
    # Create a temporary file for the ZIP
    temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.zip')
    
    try:
        with zipfile.ZipFile(temp_file.name, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # 1. Entity data as JSON
            entity_data = {
                'id': str(destinataer.id),
                'vorname': destinataer.vorname,
                'nachname': destinataer.nachname,
                'geburtsdatum': destinataer.geburtsdatum.isoformat() if destinataer.geburtsdatum else None,
                'email': destinataer.email,
                'telefon': destinataer.telefon,
                'iban': destinataer.iban,
                'strasse': destinataer.strasse,
                'plz': destinataer.plz,
                'ort': destinataer.ort,
                'familienzweig': destinataer.get_familienzweig_display(),
                'berufsgruppe': destinataer.get_berufsgruppe_display(),
                'ausbildungsstand': destinataer.ausbildungsstand,
                'institution': destinataer.institution,
                'projekt_beschreibung': destinataer.projekt_beschreibung,
                'jaehrliches_einkommen': str(destinataer.jaehrliches_einkommen) if destinataer.jaehrliches_einkommen else None,
                'finanzielle_notlage': destinataer.finanzielle_notlage,
                'ist_abkoemmling': destinataer.ist_abkoemmling,
                'haushaltsgroesse': destinataer.haushaltsgroesse,
                'monatliche_bezuege': str(destinataer.monatliche_bezuege) if destinataer.monatliche_bezuege else None,
                'vermoegen': str(destinataer.vermoegen) if destinataer.vermoegen else None,
                'unterstuetzung_bestaetigt': destinataer.unterstuetzung_bestaetigt,
                'vierteljaehrlicher_betrag': str(destinataer.vierteljaehrlicher_betrag) if destinataer.vierteljaehrlicher_betrag else None,
                'standard_konto': str(destinataer.standard_konto) if destinataer.standard_konto else None,
                'studiennachweis_erforderlich': destinataer.studiennachweis_erforderlich,
                'letzter_studiennachweis': destinataer.letzter_studiennachweis.isoformat() if destinataer.letzter_studiennachweis else None,
                'notizen': destinataer.notizen,
                'aktiv': destinataer.aktiv,
                'export_datum': timezone.now().isoformat(),
                'export_user': request.user.username,
            }
            zipf.writestr('destinataer_data.json', json.dumps(entity_data, indent=2, ensure_ascii=False))
            
            # 2. Notes with attachments
            notizen = DestinataerNotiz.objects.filter(destinataer=destinataer).order_by('-erstellt_am')
            notes_data = []
            for note in notizen:
                note_data = {
                    'titel': note.titel,
                    'text': note.text,
                    'erstellt_am': note.erstellt_am.isoformat(),
                    'erstellt_von': note.erstellt_von.username if note.erstellt_von else None,
                    'datei_name': note.datei.name if note.datei else None,
                }
                notes_data.append(note_data)
                
                # Add attachment file if exists
                if note.datei and os.path.exists(note.datei.path):
                    zipf.write(note.datei.path, f'notizen_anhaenge/{os.path.basename(note.datei.name)}')
            
            if notes_data:
                zipf.writestr('notizen.json', json.dumps(notes_data, indent=2, ensure_ascii=False))
            
            # 3. Linked documents from Paperless
            dokumente = DokumentLink.objects.filter(destinataer_id=destinataer.pk)
            docs_data = []
            for doc in dokumente:
                doc_data = {
                    'paperless_id': doc.paperless_document_id,
                    'titel': doc.titel,
                    'kontext': doc.get_kontext_display(),
                    'beschreibung': doc.beschreibung,
                }
                docs_data.append(doc_data)
                
                # Try to download document from Paperless
                try:
                    if hasattr(settings, 'PAPERLESS_API_URL') and settings.PAPERLESS_API_URL:
                        doc_url = f"{settings.PAPERLESS_API_URL}/api/documents/{doc.paperless_document_id}/download/"
                        headers = {}
                        if hasattr(settings, 'PAPERLESS_API_TOKEN') and settings.PAPERLESS_API_TOKEN:
                            headers['Authorization'] = f'Token {settings.PAPERLESS_API_TOKEN}'
                        
                        response = requests.get(doc_url, headers=headers, timeout=30)
                        if response.status_code == 200:
                            # Determine file extension from Content-Type or use .pdf as fallback
                            content_type = response.headers.get('content-type', '')
                            if 'pdf' in content_type:
                                ext = '.pdf'
                            elif 'jpeg' in content_type or 'jpg' in content_type:
                                ext = '.jpg'
                            elif 'png' in content_type:
                                ext = '.png'
                            else:
                                ext = '.pdf'  # fallback
                            
                            safe_filename = f"dokument_{doc.paperless_document_id}_{doc.titel.replace('/', '_')[:50]}{ext}"
                            zipf.writestr(f'dokumente/{safe_filename}', response.content)
                            doc_data['downloaded'] = True
                        else:
                            doc_data['download_error'] = f'HTTP {response.status_code}'
                except Exception as e:
                    doc_data['download_error'] = str(e)
            
            if docs_data:
                zipf.writestr('dokumente.json', json.dumps(docs_data, indent=2, ensure_ascii=False))
        
        # Prepare response
        with open(temp_file.name, 'rb') as f:
            response = HttpResponse(f.read(), content_type='application/zip')
            filename = f"destinataer_{destinataer.nachname}_{destinataer.vorname}_{timezone.now().strftime('%Y%m%d_%H%M%S')}.zip"
            response['Content-Disposition'] = f'attachment; filename="{filename}"'
            return response
    
    finally:
        # Clean up temp file
        try:
            os.unlink(temp_file.name)
        except:
            pass


@login_required
def paechter_export(request, pk):
    """Export complete Pächter data as ZIP with documents"""
    import zipfile
    import json
    import tempfile
    import os
    from django.http import HttpResponse
    
    paechter = get_object_or_404(Paechter, pk=pk)
    
    # Create a temporary file for the ZIP
    temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.zip')
    
    try:
        with zipfile.ZipFile(temp_file.name, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # 1. Entity data as JSON
            entity_data = {
                'id': str(paechter.id),
                'vorname': paechter.vorname,
                'nachname': paechter.nachname,
                'geburtsdatum': paechter.geburtsdatum.isoformat() if paechter.geburtsdatum else None,
                'email': paechter.email,
                'telefon': paechter.telefon,
                'iban': paechter.iban,
                'strasse': paechter.strasse,
                'plz': paechter.plz,
                'ort': paechter.ort,
                'personentyp': paechter.get_personentyp_display(),
                'pachtnummer': paechter.pachtnummer,
                'pachtbeginn_erste': paechter.pachtbeginn_erste.isoformat() if paechter.pachtbeginn_erste else None,
                'pachtende_letzte': paechter.pachtende_letzte.isoformat() if paechter.pachtende_letzte else None,
                'pachtzins_aktuell': str(paechter.pachtzins_aktuell) if paechter.pachtzins_aktuell else None,
                'landwirtschaftliche_ausbildung': paechter.landwirtschaftliche_ausbildung,
                'berufserfahrung_jahre': paechter.berufserfahrung_jahre,
                'spezialisierung': paechter.spezialisierung,
                'notizen': paechter.notizen,
                'aktiv': paechter.aktiv,
                'gesamt_pachtflaeche': float(paechter.get_gesamt_pachtflaeche()),
                'gesamt_pachtzins': float(paechter.get_gesamt_pachtzins()),
                'export_datum': timezone.now().isoformat(),
                'export_user': request.user.username,
            }
            zipf.writestr('paechter_data.json', json.dumps(entity_data, indent=2, ensure_ascii=False))
            
            # 2. Linked documents from Paperless
            dokumente = DokumentLink.objects.filter(paechter_id=paechter.pk)
            docs_data = []
            for doc in dokumente:
                doc_data = {
                    'paperless_id': doc.paperless_document_id,
                    'titel': doc.titel,
                    'kontext': doc.get_kontext_display(),
                    'beschreibung': doc.beschreibung,
                }
                docs_data.append(doc_data)
                
                # Try to download document from Paperless
                try:
                    if hasattr(settings, 'PAPERLESS_API_URL') and settings.PAPERLESS_API_URL:
                        doc_url = f"{settings.PAPERLESS_API_URL}/api/documents/{doc.paperless_document_id}/download/"
                        headers = {}
                        if hasattr(settings, 'PAPERLESS_API_TOKEN') and settings.PAPERLESS_API_TOKEN:
                            headers['Authorization'] = f'Token {settings.PAPERLESS_API_TOKEN}'
                        
                        response = requests.get(doc_url, headers=headers, timeout=30)
                        if response.status_code == 200:
                            content_type = response.headers.get('content-type', '')
                            if 'pdf' in content_type:
                                ext = '.pdf'
                            elif 'jpeg' in content_type or 'jpg' in content_type:
                                ext = '.jpg'
                            elif 'png' in content_type:
                                ext = '.png'
                            else:
                                ext = '.pdf'
                            
                            safe_filename = f"dokument_{doc.paperless_document_id}_{doc.titel.replace('/', '_')[:50]}{ext}"
                            zipf.writestr(f'dokumente/{safe_filename}', response.content)
                            doc_data['downloaded'] = True
                        else:
                            doc_data['download_error'] = f'HTTP {response.status_code}'
                except Exception as e:
                    doc_data['download_error'] = str(e)
            
            if docs_data:
                zipf.writestr('dokumente.json', json.dumps(docs_data, indent=2, ensure_ascii=False))
        
        # Prepare response
        with open(temp_file.name, 'rb') as f:
            response = HttpResponse(f.read(), content_type='application/zip')
            filename = f"paechter_{paechter.nachname}_{paechter.vorname}_{timezone.now().strftime('%Y%m%d_%H%M%S')}.zip"
            response['Content-Disposition'] = f'attachment; filename="{filename}"'
            return response
    
    finally:
        try:
            os.unlink(temp_file.name)
        except:
            pass


@login_required
def land_export(request, pk):
    """Export complete Land data as ZIP with documents"""
    import zipfile
    import json
    import tempfile
    import os
    from django.http import HttpResponse
    
    land = get_object_or_404(Land, pk=pk)
    
    # Create a temporary file for the ZIP
    temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.zip')
    
    try:
        with zipfile.ZipFile(temp_file.name, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # 1. Entity data as JSON
            entity_data = {
                'id': str(land.id),
                'lfd_nr': land.lfd_nr,
                'ew_nummer': land.ew_nummer,
                'amtsgericht': land.amtsgericht,
                'gemeinde': land.gemeinde,
                'gemarkung': land.gemarkung,
                'flur': land.flur,
                'flurstueck': land.flurstueck,
                'groesse_qm': str(land.groesse_qm),
                'gruenland_qm': str(land.gruenland_qm),
                'acker_qm': str(land.acker_qm),
                'wald_qm': str(land.wald_qm),
                'sonstiges_qm': str(land.sonstiges_qm),
                'verpachtete_gesamtflaeche': str(land.verpachtete_gesamtflaeche),
                'flaeche_alte_liste': str(land.flaeche_alte_liste) if land.flaeche_alte_liste else None,
                'verp_flaeche_aktuell': str(land.verp_flaeche_aktuell),
                'anteil_grundsteuer': str(land.anteil_grundsteuer) if land.anteil_grundsteuer else None,
                'anteil_lwk': str(land.anteil_lwk) if land.anteil_lwk else None,
                'aktiv': land.aktiv,
                'notizen': land.notizen,
                'erstellt_am': land.erstellt_am.isoformat(),
                'aktualisiert_am': land.aktualisiert_am.isoformat(),
                'gesamtflaeche_berechnet': float(land.get_gesamtflaeche()),
                'verpachtungsgrad': float(land.get_verpachtungsgrad()),
                'export_datum': timezone.now().isoformat(),
                'export_user': request.user.username,
            }
            zipf.writestr('land_data.json', json.dumps(entity_data, indent=2, ensure_ascii=False))
            
            # 2. Linked documents from Paperless
            dokumente = DokumentLink.objects.filter(land_id=land.pk)
            docs_data = []
            for doc in dokumente:
                doc_data = {
                    'paperless_id': doc.paperless_document_id,
                    'titel': doc.titel,
                    'kontext': doc.get_kontext_display(),
                    'beschreibung': doc.beschreibung,
                }
                docs_data.append(doc_data)
                
                # Try to download document from Paperless
                try:
                    if hasattr(settings, 'PAPERLESS_API_URL') and settings.PAPERLESS_API_URL:
                        doc_url = f"{settings.PAPERLESS_API_URL}/api/documents/{doc.paperless_document_id}/download/"
                        headers = {}
                        if hasattr(settings, 'PAPERLESS_API_TOKEN') and settings.PAPERLESS_API_TOKEN:
                            headers['Authorization'] = f'Token {settings.PAPERLESS_API_TOKEN}'
                        
                        response = requests.get(doc_url, headers=headers, timeout=30)
                        if response.status_code == 200:
                            content_type = response.headers.get('content-type', '')
                            if 'pdf' in content_type:
                                ext = '.pdf'
                            elif 'jpeg' in content_type or 'jpg' in content_type:
                                ext = '.jpg'
                            elif 'png' in content_type:
                                ext = '.png'
                            else:
                                ext = '.pdf'
                            
                            safe_filename = f"dokument_{doc.paperless_document_id}_{doc.titel.replace('/', '_')[:50]}{ext}"
                            zipf.writestr(f'dokumente/{safe_filename}', response.content)
                            doc_data['downloaded'] = True
                        else:
                            doc_data['download_error'] = f'HTTP {response.status_code}'
                except Exception as e:
                    doc_data['download_error'] = str(e)
            
            if docs_data:
                zipf.writestr('dokumente.json', json.dumps(docs_data, indent=2, ensure_ascii=False))
        
        # Prepare response
        with open(temp_file.name, 'rb') as f:
            response = HttpResponse(f.read(), content_type='application/zip')
            filename = f"land_{land.gemeinde}_{land.gemarkung}_flur{land.flur}_{timezone.now().strftime('%Y%m%d_%H%M%S')}.zip"
            response['Content-Disposition'] = f'attachment; filename="{filename}"'
            return response
    
    finally:
        try:
            os.unlink(temp_file.name)
        except:
            pass


@login_required
def verpachtung_export(request, pk):
    """Export complete Verpachtung data as ZIP with documents"""
    import zipfile
    import json
    import tempfile
    import os
    from django.http import HttpResponse
    
    verpachtung = get_object_or_404(Verpachtung, pk=pk)
    
    # Create a temporary file for the ZIP
    temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.zip')
    
    try:
        with zipfile.ZipFile(temp_file.name, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # 1. Entity data as JSON
            entity_data = {
                'id': str(verpachtung.id),
                'vertragsnummer': verpachtung.vertragsnummer,
                'land': str(verpachtung.land),
                'land_id': str(verpachtung.land.id),
                'paechter': str(verpachtung.paechter),
                'paechter_id': str(verpachtung.paechter.id),
                'pachtbeginn': verpachtung.pachtbeginn.isoformat(),
                'pachtende': verpachtung.pachtende.isoformat(),
                'verlaengerung': verpachtung.verlaengerung.isoformat() if verpachtung.verlaengerung else None,
                'pachtzins_pro_qm': str(verpachtung.pachtzins_pro_qm),
                'pachtzins_jaehrlich': str(verpachtung.pachtzins_jaehrlich),
                'verpachtete_flaeche': str(verpachtung.verpachtete_flaeche),
                'status': verpachtung.get_status_display(),
                'verwendungsnachweis': str(verpachtung.verwendungsnachweis) if verpachtung.verwendungsnachweis else None,
                'bemerkungen': verpachtung.bemerkungen,
                'erstellt_am': verpachtung.erstellt_am.isoformat(),
                'aktualisiert_am': verpachtung.aktualisiert_am.isoformat(),
                'vertragsdauer_tage': verpachtung.get_vertragsdauer_tage(),
                'restlaufzeit_tage': verpachtung.get_restlaufzeit_tage(),
                'ist_aktiv': verpachtung.is_aktiv(),
                'export_datum': timezone.now().isoformat(),
                'export_user': request.user.username,
            }
            zipf.writestr('verpachtung_data.json', json.dumps(entity_data, indent=2, ensure_ascii=False))
            
            # 2. Linked documents from Paperless
            dokumente = DokumentLink.objects.filter(verpachtung_id=verpachtung.pk)
            docs_data = []
            for doc in dokumente:
                doc_data = {
                    'paperless_id': doc.paperless_document_id,
                    'titel': doc.titel,
                    'kontext': doc.get_kontext_display(),
                    'beschreibung': doc.beschreibung,
                }
                docs_data.append(doc_data)
                
                # Try to download document from Paperless
                try:
                    if hasattr(settings, 'PAPERLESS_API_URL') and settings.PAPERLESS_API_URL:
                        doc_url = f"{settings.PAPERLESS_API_URL}/api/documents/{doc.paperless_document_id}/download/"
                        headers = {}
                        if hasattr(settings, 'PAPERLESS_API_TOKEN') and settings.PAPERLESS_API_TOKEN:
                            headers['Authorization'] = f'Token {settings.PAPERLESS_API_TOKEN}'
                        
                        response = requests.get(doc_url, headers=headers, timeout=30)
                        if response.status_code == 200:
                            content_type = response.headers.get('content-type', '')
                            if 'pdf' in content_type:
                                ext = '.pdf'
                            elif 'jpeg' in content_type or 'jpg' in content_type:
                                ext = '.jpg'
                            elif 'png' in content_type:
                                ext = '.png'
                            else:
                                ext = '.pdf'
                            
                            safe_filename = f"dokument_{doc.paperless_document_id}_{doc.titel.replace('/', '_')[:50]}{ext}"
                            zipf.writestr(f'dokumente/{safe_filename}', response.content)
                            doc_data['downloaded'] = True
                        else:
                            doc_data['download_error'] = f'HTTP {response.status_code}'
                except Exception as e:
                    doc_data['download_error'] = str(e)
            
            if docs_data:
                zipf.writestr('dokumente.json', json.dumps(docs_data, indent=2, ensure_ascii=False))
        
        # Prepare response
        with open(temp_file.name, 'rb') as f:
            response = HttpResponse(f.read(), content_type='application/zip')
            filename = f"verpachtung_{verpachtung.vertragsnummer}_{timezone.now().strftime('%Y%m%d_%H%M%S')}.zip"
            response['Content-Disposition'] = f'attachment; filename="{filename}"'
            return response
    
    finally:
        try:
            os.unlink(temp_file.name)
        except:
            pass


@login_required
def audit_log_list(request):
    """Liste aller Audit Log Einträge"""
    from stiftung.models import AuditLog
    from django.core.paginator import Paginator
    
    logs = AuditLog.objects.all()
    
    # Filter
    user_filter = request.GET.get('user')
    if user_filter:
        logs = logs.filter(username__icontains=user_filter)
    
    action_filter = request.GET.get('action')
    if action_filter:
        logs = logs.filter(action=action_filter)
    
    entity_filter = request.GET.get('entity_type')
    if entity_filter:
        logs = logs.filter(entity_type=entity_filter)
    
    date_from = request.GET.get('date_from')
    if date_from:
        logs = logs.filter(timestamp__date__gte=date_from)
    
    date_to = request.GET.get('date_to')
    if date_to:
        logs = logs.filter(timestamp__date__lte=date_to)
    
    # Pagination
    paginator = Paginator(logs, 50)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    context = {
        'page_obj': page_obj,
        'action_choices': AuditLog.ACTION_TYPES,
        'entity_choices': AuditLog.ENTITY_TYPES,
        'user_filter': user_filter,
        'action_filter': action_filter,
        'entity_filter': entity_filter,
        'date_from': date_from,
        'date_to': date_to,
    }
    
    return render(request, 'stiftung/audit_log_list.html', context)


@login_required
def backup_management(request):
    """Backup Management Interface"""
    from stiftung.models import BackupJob
    from django.core.paginator import Paginator
    
    # Handle backup creation
    if request.method == 'POST':
        backup_type = request.POST.get('backup_type', 'full')
        
        # Create backup job
        backup_job = BackupJob.objects.create(
            backup_type=backup_type,
            created_by=request.user
        )
        
        # Log the backup initiation
        from stiftung.audit import log_system_action
        log_system_action(
            request=request,
            action='backup',
            description=f"Backup-Job erstellt: {backup_job.get_backup_type_display()}",
            details={'backup_job_id': str(backup_job.id), 'backup_type': backup_type}
        )
        
        # Start backup process asynchronously (we'll create a simple version for now)
        import threading
        from stiftung.backup_utils import run_backup
        backup_thread = threading.Thread(target=run_backup, args=(str(backup_job.id),))
        backup_thread.start()
        
        messages.success(request, f'Backup-Job "{backup_job.get_backup_type_display()}" wurde gestartet.')
        return redirect('stiftung:backup_management')
    
    # List backup jobs
    backup_jobs = BackupJob.objects.all()
    
    # Pagination
    paginator = Paginator(backup_jobs, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    context = {
        'page_obj': page_obj,
        'backup_types': BackupJob.TYPE_CHOICES,
    }
    
    return render(request, 'stiftung/backup_management.html', context)


@login_required
def backup_download(request, backup_id):
    """Download a backup file"""
    from stiftung.models import BackupJob
    from django.http import FileResponse, Http404
    import os
    
    try:
        backup_job = BackupJob.objects.get(id=backup_id, status='completed')
    except BackupJob.DoesNotExist:
        raise Http404("Backup nicht gefunden oder nicht vollständig")
    
    backup_path = os.path.join('/app/backups', backup_job.backup_filename)
    if not os.path.exists(backup_path):
        raise Http404("Backup-Datei nicht gefunden")
    
    # Log download
    from stiftung.audit import log_system_action
    log_system_action(
        request=request,
        action='export',
        description=f"Backup heruntergeladen: {backup_job.backup_filename}",
        details={'backup_job_id': str(backup_job.id)}
    )
    
    response = FileResponse(
        open(backup_path, 'rb'),
        as_attachment=True,
        filename=backup_job.backup_filename
    )
    return response


@login_required
def backup_restore(request):
    """Restore from backup"""
    if request.method == 'POST':
        from stiftung.models import BackupJob
        backup_file = request.FILES.get('backup_file')
        
        if not backup_file:
            messages.error(request, 'Bitte wählen Sie eine Backup-Datei aus.')
            return redirect('stiftung:backup_management')
        
        # Validate file
        if not backup_file.name.endswith('.tar.gz'):
            messages.error(request, 'Ungültiges Backup-Format. Nur .tar.gz Dateien sind erlaubt.')
            return redirect('stiftung:backup_management')
        
        # Save uploaded file
        import os
        import tempfile
        
        temp_dir = tempfile.mkdtemp()
        backup_path = os.path.join(temp_dir, backup_file.name)
        
        with open(backup_path, 'wb+') as destination:
            for chunk in backup_file.chunks():
                destination.write(chunk)
        
        # Create restore job
        restore_job = BackupJob.objects.create(
            backup_type='full',
            created_by=request.user,
            backup_filename=backup_file.name
        )
        
        # Log restore initiation
        from stiftung.audit import log_system_action
        log_system_action(
            request=request,
            action='restore',
            description=f"Wiederherstellung gestartet von: {backup_file.name}",
            details={'restore_job_id': str(restore_job.id), 'filename': backup_file.name}
        )
        
        # Start restore process
        import threading
        from stiftung.backup_utils import run_restore
        restore_thread = threading.Thread(target=run_restore, args=(str(restore_job.id), backup_path))
        restore_thread.start()
        
        messages.success(request, f'Wiederherstellung von "{backup_file.name}" wurde gestartet.')
        return redirect('stiftung:backup_management')
    
    return redirect('stiftung:backup_management')


# =============================================================================
# USER MANAGEMENT VIEWS
# =============================================================================

@login_required
def user_management(request):
    """User Management Dashboard"""
    from django.contrib.auth.models import User
    from django.core.paginator import Paginator
    from django.db.models import Q
    
    # Check permission
    if not request.user.has_perm('stiftung.manage_users'):
        messages.error(request, 'Sie haben keine Berechtigung für die Benutzerverwaltung.')
        return redirect('stiftung:administration')
    
    users = User.objects.all().order_by('username')
    
    # Search functionality
    search = request.GET.get('search')
    if search:
        users = users.filter(
            Q(username__icontains=search) |
            Q(email__icontains=search) |
            Q(first_name__icontains=search) |
            Q(last_name__icontains=search)
        )
    
    # Filter by status
    status_filter = request.GET.get('status')
    if status_filter == 'active':
        users = users.filter(is_active=True)
    elif status_filter == 'inactive':
        users = users.filter(is_active=False)
    elif status_filter == 'staff':
        users = users.filter(is_staff=True)
    
    # Pagination
    paginator = Paginator(users, 20)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    # Statistics
    stats = {
        'total_users': User.objects.count(),
        'active_users': User.objects.filter(is_active=True).count(),
        'staff_users': User.objects.filter(is_staff=True).count(),
        'inactive_users': User.objects.filter(is_active=False).count(),
    }
    
    context = {
        'page_obj': page_obj,
        'stats': stats,
        'search': search,
        'status_filter': status_filter,
    }
    
    return render(request, 'stiftung/user_management.html', context)


@login_required
def user_create(request):
    """Create a new user"""
    from stiftung.forms import UserCreationForm
    from django.contrib.auth.models import User
    
    # Check permission
    if not request.user.has_perm('stiftung.manage_users'):
        messages.error(request, 'Sie haben keine Berechtigung für die Benutzerverwaltung.')
        return redirect('stiftung:administration')
    
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            # Create user
            user = User.objects.create_user(
                username=form.cleaned_data['username'],
                email=form.cleaned_data['email'],
                password=form.cleaned_data['password1'],
                first_name=form.cleaned_data['first_name'],
                last_name=form.cleaned_data['last_name'],
                is_active=form.cleaned_data['is_active'],
                is_staff=form.cleaned_data['is_staff']
            )
            
            # Log user creation
            from stiftung.audit import log_action
            log_action(
                request=request,
                action='create',
                entity_type='user',
                entity_id=str(user.pk),
                entity_name=user.username,
                description=f'Neuer Benutzer "{user.username}" wurde erstellt'
            )
            
            messages.success(request, f'Benutzer "{user.username}" wurde erfolgreich erstellt.')
            return redirect('stiftung:user_detail', pk=user.pk)
    else:
        form = UserCreationForm()
    
    context = {
        'form': form,
        'title': 'Neuen Benutzer erstellen'
    }
    
    return render(request, 'stiftung/user_form.html', context)


@login_required
def user_detail(request, pk):
    """User detail view"""
    from django.contrib.auth.models import User
    
    # Check permission
    if not request.user.has_perm('stiftung.manage_users'):
        messages.error(request, 'Sie haben keine Berechtigung für die Benutzerverwaltung.')
        return redirect('stiftung:administration')
    
    user = get_object_or_404(User, pk=pk)
    
    # Get user's permissions
    user_permissions = user.get_all_permissions()
    stiftung_permissions = [perm for perm in user_permissions if perm.startswith('stiftung.')]
    
    # Get recent audit activity
    from stiftung.models import AuditLog
    recent_activity = AuditLog.objects.filter(user=user).order_by('-timestamp')[:10]
    
    context = {
        'user_obj': user,  # Use user_obj to avoid conflict with request.user
        'stiftung_permissions': stiftung_permissions,
        'recent_activity': recent_activity,
    }
    
    return render(request, 'stiftung/user_detail.html', context)


@login_required
def user_edit(request, pk):
    """Edit user"""
    from stiftung.forms import UserUpdateForm
    from django.contrib.auth.models import User
    
    # Check permission
    if not request.user.has_perm('stiftung.manage_users'):
        messages.error(request, 'Sie haben keine Berechtigung für die Benutzerverwaltung.')
        return redirect('stiftung:administration')
    
    user = get_object_or_404(User, pk=pk)
    
    if request.method == 'POST':
        form = UserUpdateForm(request.POST, instance=user)
        if form.is_valid():
            # Track changes
            from stiftung.audit import track_model_changes, log_action
            old_user = User.objects.get(pk=user.pk)
            
            updated_user = form.save()
            
            # Log changes
            changes = track_model_changes(old_user, updated_user)
            if changes:
                log_action(
                    request=request,
                    action='update',
                    entity_type='user',
                    entity_id=str(updated_user.pk),
                    entity_name=updated_user.username,
                    description=f'Benutzer "{updated_user.username}" wurde aktualisiert',
                    changes=changes
                )
            
            messages.success(request, f'Benutzer "{updated_user.username}" wurde erfolgreich aktualisiert.')
            return redirect('stiftung:user_detail', pk=updated_user.pk)
    else:
        form = UserUpdateForm(instance=user)
    
    context = {
        'form': form,
        'user_obj': user,
        'title': f'Benutzer "{user.username}" bearbeiten'
    }
    
    return render(request, 'stiftung/user_form.html', context)


@login_required
def user_change_password(request, pk):
    """Change user password"""
    from stiftung.forms import PasswordChangeForm
    from django.contrib.auth.models import User
    
    # Check permission
    if not request.user.has_perm('stiftung.manage_users'):
        messages.error(request, 'Sie haben keine Berechtigung für die Benutzerverwaltung.')
        return redirect('stiftung:administration')
    
    user = get_object_or_404(User, pk=pk)
    
    if request.method == 'POST':
        form = PasswordChangeForm(request.POST)
        if form.is_valid():
            user.set_password(form.cleaned_data['new_password1'])
            user.save()
            
            # Log password change
            from stiftung.audit import log_action
            log_action(
                request=request,
                action='update',
                entity_type='user',
                entity_id=str(user.pk),
                entity_name=user.username,
                description=f'Passwort für Benutzer "{user.username}" wurde geändert'
            )
            
            messages.success(request, f'Passwort für Benutzer "{user.username}" wurde erfolgreich geändert.')
            return redirect('stiftung:user_detail', pk=user.pk)
    else:
        form = PasswordChangeForm()
    
    context = {
        'form': form,
        'user_obj': user,
        'title': f'Passwort für "{user.username}" ändern'
    }
    
    return render(request, 'stiftung/user_change_password.html', context)


@login_required
def user_permissions(request, pk):
    """Manage user permissions"""
    from stiftung.forms import UserPermissionForm
    from django.contrib.auth.models import User, Permission
    
    # Check permission
    if not request.user.has_perm('stiftung.manage_permissions'):
        messages.error(request, 'Sie haben keine Berechtigung für die Berechtigungsverwaltung.')
        return redirect('stiftung:administration')
    
    user = get_object_or_404(User, pk=pk)
    
    if request.method == 'POST':
        form = UserPermissionForm(request.POST, user=user)
        if form.is_valid():
            # Get selected permissions
            selected_perms = []
            for field_name, value in form.cleaned_data.items():
                if field_name.startswith('perm_') and value:
                    perm_id = field_name.replace('perm_', '')
                    selected_perms.append(int(perm_id))
            
            # Get current stiftung permissions
            current_perms = user.user_permissions.filter(content_type__app_label='stiftung')
            current_perm_ids = set(current_perms.values_list('id', flat=True))
            selected_perm_ids = set(selected_perms)
            
            # Remove permissions that are no longer selected
            to_remove = current_perm_ids - selected_perm_ids
            if to_remove:
                user.user_permissions.remove(*Permission.objects.filter(id__in=to_remove))
            
            # Add new permissions
            to_add = selected_perm_ids - current_perm_ids
            if to_add:
                user.user_permissions.add(*Permission.objects.filter(id__in=to_add))
            
            # Log permission changes
            from stiftung.audit import log_action
            if to_remove or to_add:
                changes = {
                    'removed_permissions': list(Permission.objects.filter(id__in=to_remove).values_list('name', flat=True)),
                    'added_permissions': list(Permission.objects.filter(id__in=to_add).values_list('name', flat=True))
                }
                log_action(
                    request=request,
                    action='update',
                    entity_type='user',
                    entity_id=str(user.pk),
                    entity_name=user.username,
                    description=f'Berechtigungen für Benutzer "{user.username}" wurden aktualisiert',
                    changes=changes
                )
            
            messages.success(request, f'Berechtigungen für Benutzer "{user.username}" wurden erfolgreich aktualisiert.')
            return redirect('stiftung:user_detail', pk=user.pk)
    else:
        form = UserPermissionForm(user=user)
    
    context = {
        'form': form,
        'user_obj': user,
        'permission_groups': form.get_permission_groups(),
        'title': f'Berechtigungen für "{user.username}"'
    }
    
    return render(request, 'stiftung/user_permissions.html', context)


@login_required 
def user_delete(request, pk):
    """Delete user"""
    from django.contrib.auth.models import User
    
    # Check permission
    if not request.user.has_perm('stiftung.manage_users'):
        messages.error(request, 'Sie haben keine Berechtigung für die Benutzerverwaltung.')
        return redirect('stiftung:administration')
    
    user = get_object_or_404(User, pk=pk)
    
    # Prevent deletion of current user
    if user == request.user:
        messages.error(request, 'Sie können sich nicht selbst löschen.')
        return redirect('stiftung:user_detail', pk=pk)
    
    if request.method == 'POST':
        username = user.username
        
        # Log deletion before deleting
        from stiftung.audit import log_action
        log_action(
            request=request,
            action='delete',
            entity_type='user',
            entity_id=str(user.pk),
            entity_name=username,
            description=f'Benutzer "{username}" wurde gelöscht'
        )
        
        user.delete()
        
        messages.success(request, f'Benutzer "{username}" wurde erfolgreich gelöscht.')
        return redirect('stiftung:user_management')
    
    context = {
        'user_obj': user,
        'title': f'Benutzer "{user.username}" löschen'
    }
    
    return render(request, 'stiftung/user_delete.html', context)


# =============================================================================
# AUTHENTICATION VIEWS
# =============================================================================

def user_login(request):
    """User login view"""
    from django.contrib.auth import authenticate, login
    from django.contrib.auth.forms import AuthenticationForm
    
    if request.user.is_authenticated:
        return redirect('stiftung:dashboard')
    
    if request.method == 'POST':
        form = AuthenticationForm(request, data=request.POST)
        if form.is_valid():
            username = form.cleaned_data.get('username')
            password = form.cleaned_data.get('password')
            user = authenticate(username=username, password=password)
            if user is not None:
                login(request, user)
                
                # Log the login
                from stiftung.audit import log_login
                log_login(request, user)
                
                messages.success(request, f'Willkommen zurück, {user.username}!')
                
                # Redirect to safe next URL path or dashboard
                next_param = request.GET.get('next') or request.POST.get('next')
                if next_param and next_param.startswith('/'):
                    return redirect(next_param)
                return redirect('stiftung:dashboard')
            else:
                messages.error(request, 'Ungültige Anmeldedaten.')
        else:
            messages.error(request, 'Bitte korrigieren Sie die Fehler im Formular.')
    else:
        form = AuthenticationForm()
    
    context = {
        'form': form,
        'next': request.GET.get('next', '')
    }
    
    return render(request, 'stiftung/login.html', context)


@login_required
def user_logout(request):
    """User logout view"""
    from django.contrib.auth import logout
    
    # Log the logout before actually logging out
    from stiftung.audit import log_logout
    log_logout(request, request.user)
    
    username = request.user.username
    logout(request)
    
    messages.success(request, f'Sie wurden erfolgreich abgemeldet, {username}.')
    return redirect('stiftung:login')


# ============================================================================
# LANDABRECHNUNGS VIEWS
# ============================================================================

@login_required
def land_abrechnung_list(request):
    """Liste aller Landabrechnungen"""
    abrechnungen = LandAbrechnung.objects.select_related('land').all()
    
    # Filter
    jahr_filter = request.GET.get('jahr')
    land_filter = request.GET.get('land')
    
    if jahr_filter:
        abrechnungen = abrechnungen.filter(abrechnungsjahr=jahr_filter)
    if land_filter:
        abrechnungen = abrechnungen.filter(land__pk=land_filter)
    
    # Pagination
    paginator = Paginator(abrechnungen, 20)
    page_number = request.GET.get('page')
    abrechnungen = paginator.get_page(page_number)
    
    # Statistiken
    stats = LandAbrechnung.objects.aggregate(
        total_einnahmen=Sum('pacht_vereinnahmt'),
        total_ausgaben=Sum('grundsteuer_betrag'),
        anzahl_abrechnungen=Count('id')
    )
    
    context = {
        'abrechnungen': abrechnungen,
        'stats': stats,
        'jahre': LandAbrechnung.objects.values_list('abrechnungsjahr', flat=True).distinct().order_by('-abrechnungsjahr'),
        'laendereien': Land.objects.filter(aktiv=True).order_by('gemeinde', 'gemarkung'),
        'jahr_filter': jahr_filter,
        'land_filter': land_filter,
    }
    
    return render(request, 'stiftung/land_abrechnung_list.html', context)


@login_required
def land_abrechnung_detail(request, pk):
    """Detail-Ansicht einer Landabrechnung"""
    abrechnung = get_object_or_404(LandAbrechnung, pk=pk)
    
    context = {
        'abrechnung': abrechnung,
        'land': abrechnung.land,
    }
    
    return render(request, 'stiftung/land_abrechnung_detail.html', context)


@login_required
def land_abrechnung_create(request):
    """Neue Landabrechnung erstellen"""
    from .forms import LandAbrechnungForm
    
    land_pk = request.GET.get('land')
    initial = {}
    land = None
    
    if land_pk:
        land = get_object_or_404(Land, pk=land_pk)
        initial['land'] = land
        initial['abrechnungsjahr'] = datetime.now().year
        
        # Automatische Vorausfüllung aus Verpachtungsdaten
        if land.pachtzins_pauschal:
            initial['pacht_vereinnahmt'] = land.pachtzins_pauschal
    
    if request.method == 'POST':
        form = LandAbrechnungForm(request.POST, request.FILES)
        if form.is_valid():
            abrechnung = form.save()
            messages.success(request, f'Landabrechnung für {abrechnung.land} ({abrechnung.abrechnungsjahr}) wurde erfolgreich erstellt.')
            return redirect('stiftung:land_abrechnung_detail', pk=abrechnung.pk)
    else:
        form = LandAbrechnungForm(initial=initial)
    
    context = {
        'form': form,
        'title': 'Neue Landabrechnung',
        'land': land,
    }
    
    return render(request, 'stiftung/land_abrechnung_form.html', context)


@login_required
def land_abrechnung_update(request, pk):
    """Landabrechnung bearbeiten"""
    from .forms import LandAbrechnungForm
    
    abrechnung = get_object_or_404(LandAbrechnung, pk=pk)
    
    if request.method == 'POST':
        form = LandAbrechnungForm(request.POST, request.FILES, instance=abrechnung)
        if form.is_valid():
            abrechnung = form.save()
            messages.success(request, f'Landabrechnung für {abrechnung.land} ({abrechnung.abrechnungsjahr}) wurde erfolgreich aktualisiert.')
            return redirect('stiftung:land_abrechnung_detail', pk=abrechnung.pk)
    else:
        form = LandAbrechnungForm(instance=abrechnung)
    
    context = {
        'form': form,
        'abrechnung': abrechnung,
        'title': f'Abrechnung bearbeiten - {abrechnung.land} ({abrechnung.abrechnungsjahr})',
    }
    
    return render(request, 'stiftung/land_abrechnung_form.html', context)


@login_required
def land_abrechnung_delete(request, pk):
    """Landabrechnung löschen"""
    abrechnung = get_object_or_404(LandAbrechnung, pk=pk)
    land = abrechnung.land
    
    if request.method == 'POST':
        abrechnung.delete()
        messages.success(request, f'Landabrechnung für {land} ({abrechnung.abrechnungsjahr}) wurde erfolgreich gelöscht.')
        return redirect('stiftung:land_detail', pk=land.pk)
    
    context = {
        'abrechnung': abrechnung,
        'land': land,
    }
    
    return render(request, 'stiftung/land_abrechnung_confirm_delete.html', context)


# ============================================================================
# VEREINHEITLICHTE VERPACHTUNGS VIEWS
# ============================================================================

@login_required
def land_verpachtung_create(request, land_pk):
    """Erstelle eine neue Verpachtung direkt im Land-Model"""
    from datetime import datetime as dt
    
    land = get_object_or_404(Land, pk=land_pk)
    
    if request.method == 'POST':
        # Einfaches Formular für die wichtigsten Verpachtungsfelder
        aktueller_paechter_id = request.POST.get('aktueller_paechter')
        pachtbeginn = request.POST.get('pachtbeginn')
        pachtende = request.POST.get('pachtende')
        pachtzins_pauschal = request.POST.get('pachtzins_pauschal')
        zahlungsweise = request.POST.get('zahlungsweise')
        ust_option = request.POST.get('ust_option') == 'on'
        
        if aktueller_paechter_id and pachtbeginn:
            paechter = get_object_or_404(Paechter, pk=aktueller_paechter_id)
            verpachtete_flaeche = request.POST.get('verpachtete_flaeche')
            
            # Validiere verpachtete Fläche
            if not verpachtete_flaeche:
                verpachtete_flaeche = land.groesse_qm  # Standard: gesamte Fläche
            else:
                verpachtete_flaeche = float(verpachtete_flaeche)
                if verpachtete_flaeche > land.groesse_qm:
                    messages.error(request, f'Die verpachtete Fläche ({verpachtete_flaeche} qm) kann nicht größer als die Gesamtfläche ({land.groesse_qm} qm) sein.')
                    # Erstelle context für Fehlerfall
                    paechter_list = Paechter.objects.filter(aktiv=True).order_by('nachname', 'vorname')
                    verfuegbare_flaeche = land.groesse_qm
                    if land.verp_flaeche_aktuell and land.verp_flaeche_aktuell > 0:
                        verfuegbare_flaeche = land.groesse_qm - land.verp_flaeche_aktuell
                    
                    context = {
                        'land': land,
                        'paechter_list': paechter_list,
                        'current_year': dt.now().year,
                        'is_edit': False,
                        'verfuegbare_flaeche': verfuegbare_flaeche,
                    }
                    return render(request, 'stiftung/land_verpachtung_form.html', context)
            
            # Land aktualisieren
            land.aktueller_paechter = paechter
            land.paechter_name = paechter.get_full_name()
            land.paechter_anschrift = f"{paechter.strasse or ''}\n{paechter.plz or ''} {paechter.ort or ''}".strip()
            land.pachtbeginn = pachtbeginn
            land.pachtende = pachtende if pachtende else None
            land.pachtzins_pauschal = pachtzins_pauschal if pachtzins_pauschal else None
            land.zahlungsweise = zahlungsweise
            land.ust_option = ust_option
            land.verp_flaeche_aktuell = verpachtete_flaeche
            land.verpachtete_gesamtflaeche = verpachtete_flaeche
            land.save()
            
            # Erstelle LandVerpachtung-Objekt für bessere Nachverfolgung
            land_verpachtung = LandVerpachtung.objects.create(
                land=land,
                paechter=paechter,
                vertragsnummer=f"V-{land.lfd_nr}-{dt.now().year}",
                pachtbeginn=pachtbeginn,
                pachtende=pachtende if pachtende else None,
                verpachtete_flaeche=verpachtete_flaeche,
                pachtzins_pauschal=pachtzins_pauschal if pachtzins_pauschal else 0,
                zahlungsweise=zahlungsweise,
                ust_option=ust_option,
                status='aktiv'
            )
            
            # Erstelle automatisch eine Abrechnung für das aktuelle Jahr
            current_year = dt.now().year
            
            # Berechne erwartete jährliche Pacht basierend auf Zahlungsweise
            expected_annual_rent = pachtzins_pauschal if pachtzins_pauschal else 0
            
            abrechnung, created = LandAbrechnung.objects.get_or_create(
                land=land,
                abrechnungsjahr=current_year,
                defaults={
                    'pacht_vereinnahmt': expected_annual_rent,  # Setze erwartete Jahrespacht
                    'umlagen_vereinnahmt': 0,
                    'grundsteuer_betrag': 0,
                    'versicherungen_betrag': 0,
                }
            )
            
            # Falls Abrechnung bereits existiert, aktualisiere die Pacht wenn höher
            if not created and expected_annual_rent > abrechnung.pacht_vereinnahmt:
                abrechnung.pacht_vereinnahmt = expected_annual_rent
                abrechnung.save()
            
            success_msg = f'Verpachtung von {land} an {paechter.get_full_name()} wurde erfolgreich erstellt.'
            if created:
                success_msg += f' Abrechnung für {current_year} wurde automatisch angelegt'
                if expected_annual_rent > 0:
                    success_msg += f' (Erwartete Jahrespacht: {expected_annual_rent}€)'
                success_msg += '.'
            elif expected_annual_rent > 0:
                success_msg += f' Erwartete Jahrespacht in Abrechnung {current_year} wurde aktualisiert ({expected_annual_rent}€).'
            
            messages.success(request, success_msg)
            return redirect('stiftung:land_detail', pk=land.pk)
        else:
            messages.error(request, 'Bitte füllen Sie alle Pflichtfelder aus.')
    
    # Verfügbare Pächter
    paechter_list = Paechter.objects.filter(aktiv=True).order_by('nachname', 'vorname')
    
    # Berechne verfügbare Fläche (Gesamtfläche minus bereits verpachtete Fläche)
    verfuegbare_flaeche = land.groesse_qm
    if land.verp_flaeche_aktuell and land.verp_flaeche_aktuell > 0:
        verfuegbare_flaeche = land.groesse_qm - land.verp_flaeche_aktuell
    
    context = {
        'land': land,
        'paechter_list': paechter_list,
        'current_year': dt.now().year,
        'is_edit': False,
        'verfuegbare_flaeche': verfuegbare_flaeche,
    }
    
    return render(request, 'stiftung/land_verpachtung_form.html', context)


@login_required 
def land_verpachtung_end(request, land_pk):
    """Beende die aktuelle Verpachtung eines Landes"""
    land = get_object_or_404(Land, pk=land_pk)
    
    if request.method == 'POST':
        # Verpachtung beenden
        land.aktueller_paechter = None
        land.paechter_name = None
        land.paechter_anschrift = None
        land.pachtende = datetime.now().date()
        land.save()
        
        messages.success(request, f'Verpachtung von {land} wurde beendet.')
        return redirect('stiftung:land_detail', pk=land.pk)
    
    context = {
        'land': land,
    }
    
    return render(request, 'stiftung/land_verpachtung_end.html', context)


@login_required
def land_verpachtung_edit(request, land_pk):
    """Bearbeite eine bestehende Verpachtung direkt im Land-Model"""
    land = get_object_or_404(Land, pk=land_pk)
    
    if request.method == 'POST':
        # Einfaches Formular für die wichtigsten Verpachtungsfelder
        aktueller_paechter_id = request.POST.get('aktueller_paechter')
        pachtbeginn = request.POST.get('pachtbeginn')
        pachtende = request.POST.get('pachtende')
        pachtzins_pauschal = request.POST.get('pachtzins_pauschal')
        zahlungsweise = request.POST.get('zahlungsweise')
        ust_option = request.POST.get('ust_option') == 'on'
        verpachtete_flaeche = request.POST.get('verpachtete_flaeche')
        
        if aktueller_paechter_id and pachtbeginn:
            paechter = get_object_or_404(Paechter, pk=aktueller_paechter_id)
            
            # Land aktualisieren
            land.aktueller_paechter = paechter
            land.paechter_name = paechter.get_full_name()
            land.paechter_anschrift = f"{paechter.strasse or ''}\n{paechter.plz or ''} {paechter.ort or ''}".strip()
            land.pachtbeginn = pachtbeginn
            land.pachtende = pachtende if pachtende else None
            land.pachtzins_pauschal = pachtzins_pauschal if pachtzins_pauschal else None
            land.zahlungsweise = zahlungsweise
            land.ust_option = ust_option
            if verpachtete_flaeche:
                land.verp_flaeche_aktuell = verpachtete_flaeche
            land.save()
            
            messages.success(request, f'Verpachtung von {land} an {paechter.get_full_name()} wurde erfolgreich aktualisiert.')
            return redirect('stiftung:land_detail', pk=land.pk)
        else:
            messages.error(request, 'Bitte füllen Sie alle Pflichtfelder aus.')
    
    # Verfügbare Pächter
    paechter_list = Paechter.objects.filter(aktiv=True).order_by('nachname', 'vorname')
    
    # Berechne verfügbare Fläche (Gesamtfläche minus bereits verpachtete Fläche)
    verfuegbare_flaeche = land.groesse_qm
    if land.verp_flaeche_aktuell and land.verp_flaeche_aktuell > 0:
        verfuegbare_flaeche = land.groesse_qm - land.verp_flaeche_aktuell
    
    context = {
        'land': land,
        'paechter_list': paechter_list,
        'current_year': datetime.now().year,
        'is_edit': True,
        'verfuegbare_flaeche': verfuegbare_flaeche,
    }
    
    return render(request, 'stiftung/land_verpachtung_form.html', context)


# Settings Management Views
@login_required
def app_settings(request):
    """Application settings management interface"""
    
    # Group settings by category
    categories = {}
    for setting in AppConfiguration.objects.filter(is_active=True).order_by('category', 'order', 'display_name'):
        if setting.category not in categories:
            categories[setting.category] = []
        categories[setting.category].append(setting)
    
    if request.method == 'POST':
        # Handle form submission
        updated_count = 0
        for key, value in request.POST.items():
            if key.startswith('setting_'):
                setting_key = key.replace('setting_', '')
                try:
                    setting = AppConfiguration.objects.get(key=setting_key, is_active=True)
                    if not setting.is_system and setting.value != value:
                        setting.value = value
                        setting.save()
                        updated_count += 1
                except AppConfiguration.DoesNotExist:
                    continue
        
        if updated_count > 0:
            messages.success(request, f'Successfully updated {updated_count} settings!')
        else:
            messages.info(request, 'No changes were made.')
        
        return redirect('stiftung:app_settings')
    
    context = {
        'categories': categories,
        'title': 'Application Settings',
    }
    return render(request, 'stiftung/app_settings.html', context)


# Unterstützungen Views (Destinataer-focused)
@login_required
def unterstuetzungen_all(request):
    """List all support payments - destinataer-focused view"""
    status = request.GET.get('status')
    destinataer_id = request.GET.get('destinataer')
    export = request.GET.get('format', '')
    selected_ids = request.POST.getlist('selected_entries') if request.method == 'POST' else []
    
    unterstuetzungen = DestinataerUnterstuetzung.objects.select_related(
        'destinataer', 'konto', 'ausgezahlt_von', 'wiederkehrend_von'
    ).order_by('-faellig_am')
    
    # Filtering
    if status:
        unterstuetzungen = unterstuetzungen.filter(status=status)
    if destinataer_id:
        unterstuetzungen = unterstuetzungen.filter(destinataer_id=destinataer_id)
    
    # Enhanced CSV export with field selection
    if export == 'csv':
        return export_unterstuetzungen_csv(request, unterstuetzungen, selected_ids)
    
    # PDF export (simple table via WeasyPrint; graceful fallback if missing)
    if export == 'pdf':
        try:
            from django.template.loader import render_to_string
            from weasyprint import HTML
            html = render_to_string('stiftung/unterstuetzungen_pdf.html', {'unterstuetzungen': unterstuetzungen})
            from django.http import HttpResponse
            pdf = HTML(string=html).write_pdf()
            resp = HttpResponse(pdf, content_type='application/pdf')
            resp['Content-Disposition'] = 'inline; filename=unterstuetzungen.pdf'
            return resp
        except Exception:
            pass
    
    # Statistics
    total_betrag = unterstuetzungen.aggregate(total=Sum('betrag'))['total'] or 0
    avg_betrag = unterstuetzungen.aggregate(avg=Avg('betrag'))['avg'] or 0
    
    # Available destinataer for filter
    destinataer = Destinataer.objects.all().order_by('nachname', 'vorname')
    
    context = {
        'page_obj': unterstuetzungen,  # Use directly for now (pagination can be added later)
        'unterstuetzungen': unterstuetzungen,
        'title': 'Alle Unterstützungen',
        'status_filter': status,
        'total_betrag': total_betrag,
        'avg_betrag': avg_betrag,
        'status_choices': DestinataerUnterstuetzung.STATUS_CHOICES,
        'destinataer': destinataer,
    }
    return render(request, 'stiftung/unterstuetzungen_all.html', context)


@login_required  
def unterstuetzung_create(request):
    """Create a new support payment"""
    # Get destinataer from URL parameter if provided
    destinataer_id = request.GET.get('destinataer')
    initial = {}
    if destinataer_id:
        initial['destinataer'] = destinataer_id
        # Pre-populate IBAN and name if destinataer is specified
        try:
            destinataer = Destinataer.objects.get(pk=destinataer_id)
            if hasattr(destinataer, 'iban') and destinataer.iban:
                initial['empfaenger_iban'] = destinataer.iban
            initial['empfaenger_name'] = destinataer.get_full_name()
        except Destinataer.DoesNotExist:
            pass
    
    if request.method == 'POST':
        form = UnterstuetzungForm(request.POST)
        if form.is_valid():
            ist_wiederkehrend = form.cleaned_data.get('ist_wiederkehrend', False)
            
            if ist_wiederkehrend:
                # Create recurring payment template
                wiederkehrend = UnterstuetzungWiederkehrend.objects.create(
                    destinataer=form.cleaned_data['destinataer'],
                    konto=form.cleaned_data['konto'],
                    betrag=form.cleaned_data['betrag'],
                    intervall=form.cleaned_data['intervall'],
                    beschreibung=form.cleaned_data['beschreibung'],
                    empfaenger_iban=form.cleaned_data['empfaenger_iban'],
                    empfaenger_name=form.cleaned_data['empfaenger_name'],
                    verwendungszweck=form.cleaned_data['verwendungszweck'],
                    erste_zahlung_am=form.cleaned_data['faellig_am'],
                    letzte_zahlung_am=form.cleaned_data.get('letzte_zahlung_am'),
                    naechste_generierung=form.cleaned_data['faellig_am'],
                    erstellt_von=request.user
                )
                
                # Create the first payment
                unterstuetzung = form.save(commit=False)
                unterstuetzung.wiederkehrend_von = wiederkehrend
                unterstuetzung.save()
                
                messages.success(request, f'Wiederkehrende Unterstützung für {unterstuetzung.destinataer} wurde erfolgreich erstellt. Die erste Zahlung ist am {unterstuetzung.faellig_am} fällig.')
            else:
                # Create single payment
                unterstuetzung = form.save()
                messages.success(request, f'Unterstützung für {unterstuetzung.destinataer} wurde erfolgreich erstellt.')
            
            return redirect('stiftung:unterstuetzung_detail', pk=unterstuetzung.pk)
    else:
        form = UnterstuetzungForm(initial=initial)
    
    context = {
        'form': form,
        'title': 'Neue Unterstützung erstellen',
    }
    return render(request, 'stiftung/unterstuetzung_form.html', context)


@login_required
def get_destinataer_info(request, destinataer_id):
    """AJAX endpoint to get Destinataer IBAN and name information"""
    try:
        destinataer = Destinataer.objects.get(pk=destinataer_id)
        data = {
            'success': True,
            'name': destinataer.get_full_name(),
            'iban': getattr(destinataer, 'iban', '') or '',
        }
    except Destinataer.DoesNotExist:
        data = {
            'success': False,
            'error': 'Destinataer not found'
        }
    
    return JsonResponse(data)


@login_required
def unterstuetzung_detail(request, pk):
    """View support payment details"""
    unterstuetzung = get_object_or_404(DestinataerUnterstuetzung, pk=pk)
    
    # Check if this payment can be marked as paid
    can_mark_paid = unterstuetzung.can_be_marked_paid()
    
    context = {
        'unterstuetzung': unterstuetzung,
        'title': f'Unterstützung für {unterstuetzung.destinataer.get_full_name()}',
        'can_mark_paid': can_mark_paid,
    }
    return render(request, 'stiftung/unterstuetzung_detail.html', context)


@login_required
def unterstuetzung_mark_paid(request, pk):
    """Mark a support payment as paid"""
    unterstuetzung = get_object_or_404(DestinataerUnterstuetzung, pk=pk)
    
    if not unterstuetzung.can_be_marked_paid():
        messages.error(request, 'Diese Unterstützung kann nicht als bezahlt markiert werden.')
        return redirect('stiftung:unterstuetzung_detail', pk=pk)
    
    if request.method == 'POST':
        form = UnterstuetzungMarkAsPaidForm(request.POST)
        if form.is_valid():
            unterstuetzung.status = 'ausgezahlt'
            unterstuetzung.ausgezahlt_am = form.cleaned_data['ausgezahlt_am']
            unterstuetzung.ausgezahlt_von = request.user
            
            # Add optional note to description
            bemerkung = form.cleaned_data.get('bemerkung')
            if bemerkung:
                if unterstuetzung.beschreibung:
                    unterstuetzung.beschreibung += f' | Zahlung: {bemerkung}'
                else:
                    unterstuetzung.beschreibung = f'Zahlung: {bemerkung}'
            
            unterstuetzung.save()
            messages.success(request, f'Unterstützung wurde als bezahlt markiert.')
            return redirect('stiftung:unterstuetzung_detail', pk=pk)
    else:
        form = UnterstuetzungMarkAsPaidForm()
    
    context = {
        'form': form,
        'unterstuetzung': unterstuetzung,
        'title': f'Zahlung markieren - {unterstuetzung.destinataer.get_full_name()}',
    }
    return render(request, 'stiftung/unterstuetzung_mark_paid.html', context)


@login_required
def wiederkehrende_unterstuetzungen(request):
    """List all recurring support payment templates"""
    from django.db.models import Count
    
    # Check for cleanup request
    if request.GET.get('cleanup') == '1':
        # Find templates with no associated payments
        verwaiste_templates = UnterstuetzungWiederkehrend.objects.annotate(
            zahlung_count=Count('destinataerunterstuetzung')
        ).filter(zahlung_count=0)
        
        if verwaiste_templates.exists():
            anzahl_geloescht = verwaiste_templates.count()
            template_namen = list(verwaiste_templates.values_list('destinataer__nachname', flat=True))
            verwaiste_templates.delete()
            messages.success(
                request, 
                f'{anzahl_geloescht} verwaiste Zahlungsvorlagen bereinigt: {", ".join(template_namen[:5])}{"..." if len(template_namen) > 5 else ""}'
            )
        else:
            messages.info(request, 'Keine verwaisten Zahlungsvorlagen gefunden.')
        
        return redirect('stiftung:wiederkehrende_unterstuetzungen')
    
    # Get all templates with payment counts
    templates = UnterstuetzungWiederkehrend.objects.select_related(
        'destinataer', 'konto'
    ).annotate(
        aktive_zahlungen=Count('destinataerunterstuetzung')
    ).all()
    
    context = {
        'templates': templates,
        'title': 'Wiederkehrende Unterstützungen',
    }
    return render(request, 'stiftung/wiederkehrende_unterstuetzungen.html', context)


@login_required
def edit_help_box(request):
    """Bearbeite oder erstelle eine Hilfs-Infobox"""
    from .models import HelpBox
    
    # Nur root oder Superuser dürfen bearbeiten
    if request.user.username != 'root' and not request.user.is_superuser:
        messages.error(request, 'Sie haben keine Berechtigung, Hilfsboxen zu bearbeiten.')
        return redirect('stiftung:dashboard')
    
    if request.method == 'POST':
        page_key = request.POST.get('page_key')
        title = request.POST.get('title')
        content = request.POST.get('content')
        is_active = request.POST.get('is_active') == 'on'
        
        if not page_key or not title or not content:
            messages.error(request, 'Alle Felder sind erforderlich.')
            return redirect(request.META.get('HTTP_REFERER', 'stiftung:dashboard'))
        
        # Hilfsbox erstellen oder aktualisieren
        help_box, created = HelpBox.objects.get_or_create(
            page_key=page_key,
            defaults={
                'title': title,
                'content': content,
                'is_active': is_active,
                'created_by': request.user.username,
                'updated_by': request.user.username,
            }
        )
        
        if not created:
            # Existierende Hilfsbox aktualisieren
            help_box.title = title
            help_box.content = content
            help_box.is_active = is_active
            help_box.updated_by = request.user.username
            help_box.save()
            
            messages.success(request, f'Hilfsbox "{title}" wurde aktualisiert.')
        else:
            messages.success(request, f'Hilfsbox "{title}" wurde erstellt.')
        
        # Zurück zur vorherigen Seite
        return redirect(request.META.get('HTTP_REFERER', 'stiftung:dashboard'))
    
    # GET Request - Zeige Admin-Übersicht der Hilfsboxen
    help_boxes = HelpBox.objects.all().order_by('page_key', '-updated_at')
    
    # Statistiken berechnen
    active_count = help_boxes.filter(is_active=True).count()
    inactive_count = help_boxes.filter(is_active=False).count()
    existing_pages = set(help_boxes.values_list('page_key', flat=True))
    
    # Verfügbare Seiten aus dem Model holen
    available_pages = HelpBox.PAGE_CHOICES
    
    context = {
        'help_boxes': help_boxes,
        'active_count': active_count,
        'inactive_count': inactive_count,
        'existing_pages': existing_pages,
        'available_pages': available_pages,
        'title': 'Hilfs-Infoboxen verwalten',
    }
    return render(request, 'stiftung/help_boxes_admin.html', context)
