"""
Calendar service for aggregating date-based events from the foundation management system
"""
from datetime import date, timedelta
import calendar as cal
try:
    from django.utils import timezone
except ImportError:
    from datetime import datetime as timezone
    timezone.now = datetime.now

try:
    from stiftung.models import (
        DestinataerUnterstuetzung, 
        LandVerpachtung, 
        Destinataer,
        StiftungsKalenderEintrag
    )
except ImportError:
    # Fallback for when Django apps aren't ready
    DestinataerUnterstuetzung = None
    LandVerpachtung = None
    Destinataer = None
    StiftungsKalenderEintrag = None


class StiftungsKalenderService:
    """Service to aggregate calendar events from various models"""
    
    def __init__(self):
        self.today = timezone.now().date()
    
    def get_calendar_events(self, start_date=None, end_date=None):
        """
        Get custom calendar entries only within date range
        Returns list of event objects
        """
        if not start_date:
            start_date = self.today
        if not end_date:
            end_date = start_date + timedelta(days=30)
            
        return self._get_custom_calendar_events(start_date, end_date)
    
    def get_all_events(self, start_date=None, end_date=None):
        """
        Get all calendar events from all sources within date range
        Returns list of event dictionaries
        """
        if not start_date:
            start_date = self.today
        if not end_date:
            end_date = start_date + timedelta(days=30)
            
        events = []
        
        # Add support payment due dates
        events.extend(self.get_support_payment_events(start_date, end_date))
        
        # Add lease expiration dates
        events.extend(self.get_lease_events(start_date, end_date))
        
        # Add birthdays
        events.extend(self.get_birthday_events(start_date, end_date))
        
        # Add custom calendar entries
        events.extend(self.get_calendar_events(start_date, end_date))
        
        # Sort by date
        events.sort(key=lambda x: (x.date, getattr(x, 'time', '00:00')))
        
        return events
    
    def get_support_payment_events(self, start_date, end_date):
        """Get support payment due dates"""
        if not DestinataerUnterstuetzung:
            return []
            
        events = []
        
        payments = DestinataerUnterstuetzung.objects.filter(
            faellig_am__range=[start_date, end_date],
            status__in=['geplant', 'faellig']
        ).select_related('destinataer')
        
        for payment in payments:
            is_overdue = payment.is_overdue() if hasattr(payment, 'is_overdue') else False
            
            class PaymentEvent:
                def __init__(self, payment_obj, overdue):
                    self.id = f'payment_{payment_obj.id}'
                    self.title = f'Zahlung an {payment_obj.destinataer.get_full_name()}'
                    self.description = f'€{payment_obj.betrag} - {payment_obj.beschreibung}'
                    self.date = payment_obj.faellig_am
                    self.time = None
                    self.category = 'zahlung'
                    self.category_display = 'Zahlung'
                    self.priority = 'hoch' if overdue else 'normal'
                    self.priority_display = 'Hoch' if overdue else 'Normal'
                    self.icon = 'fas fa-euro-sign'
                    self.color = 'danger' if overdue else 'warning'
                    self.source = 'payment'
                    self.overdue = overdue
                    self.completed = False
            
            events.append(PaymentEvent(payment, is_overdue))
        
        return events
    
    def get_lease_events(self, start_date, end_date):
        """Get lease start/end dates"""
        if not LandVerpachtung:
            return []
            
        events = []
        
        # Lease expirations
        leases = LandVerpachtung.objects.filter(
            pachtende__range=[start_date, end_date],
            status='aktiv'
        ).select_related('paechter', 'land')
        
        for lease in leases:
            # Check if expiring soon (within 90 days)
            days_until_expiry = (lease.pachtende - self.today).days if lease.pachtende else 999
            priority = 'hoch' if days_until_expiry <= 30 else 'mittel' if days_until_expiry <= 90 else 'normal'
            
            class LeaseEvent:
                def __init__(self, lease_obj, priority_val):
                    self.id = f'lease_end_{lease_obj.id}'
                    self.title = f'Pachtende: {lease_obj.paechter.get_full_name()}'
                    self.description = f'{lease_obj.land.bezeichnung} - {lease_obj.verpachtete_flaeche}m²'
                    self.date = lease_obj.pachtende
                    self.time = None
                    self.category = 'vertrag'
                    self.category_display = 'Vertrag'
                    self.priority = priority_val
                    self.priority_display = 'Hoch' if priority_val == 'hoch' else 'Mittel' if priority_val == 'mittel' else 'Normal'
                    self.icon = 'fas fa-file-contract'
                    self.color = 'danger' if priority_val == 'hoch' else 'warning' if priority_val == 'mittel' else 'info'
                    self.source = 'lease'
                    self.overdue = False
                    self.completed = False
            
            events.append(LeaseEvent(lease, priority))
        
        return events
    
    def get_birthday_events(self, start_date, end_date):
        """Get birthdays within date range"""
        if not Destinataer:
            return []
            
        events = []
        
        # Get all destinatäre with birth dates
        destinataere = Destinataer.objects.filter(
            geburtsdatum__isnull=False
        )
        
        for destinataer in destinataere:
            # Calculate birthday for each year in range
            birth_date = destinataer.geburtsdatum
            for year in range(start_date.year, end_date.year + 1):
                try:
                    birthday_this_year = birth_date.replace(year=year)
                    if start_date <= birthday_this_year <= end_date:
                        age = year - birth_date.year
                        
                        class BirthdayEvent:
                            def __init__(self, person, birthday_date, age_val):
                                self.id = f'birthday_{person.id}_{year}'
                                self.title = f'🎂 {person.get_full_name()}'
                                self.description = f'{age_val}. Geburtstag'
                                self.date = birthday_date
                                self.time = None
                                self.category = 'geburtstag'
                                self.category_display = 'Geburtstag'
                                self.priority = 'normal'
                                self.priority_display = 'Normal'
                                self.icon = 'fas fa-birthday-cake'
                                self.color = 'success'
                                self.source = 'birthday'
                                self.overdue = False
                                self.completed = False
                        
                        events.append(BirthdayEvent(destinataer, birthday_this_year, age))
                except ValueError:
                    # Handle leap year edge case (Feb 29)
                    pass
        
        return events
    
    def _get_custom_calendar_events(self, start_date, end_date):
        """Get custom calendar entries"""
        if not StiftungsKalenderEintrag:
            return []
            
        events = []
        
        calendar_entries = StiftungsKalenderEintrag.objects.filter(
            datum__range=[start_date, end_date]
        ).select_related('destinataer', 'verpachtung')
        
        for entry in calendar_entries:
            class CustomEvent:
                def __init__(self, entry_obj, today_date):
                    self.id = entry_obj.id
                    self.title = entry_obj.titel
                    self.description = entry_obj.beschreibung
                    self.date = entry_obj.datum
                    self.time = entry_obj.uhrzeit
                    self.category = entry_obj.kategorie
                    self.category_display = entry_obj.get_kategorie_display()
                    self.priority = entry_obj.prioritaet
                    self.priority_display = entry_obj.get_prioritaet_display()
                    self.icon = self._get_kategorie_icon(entry_obj.kategorie)
                    self.color = self._get_prioritaet_color(entry_obj.prioritaet)
                    self.source = 'custom'
                    self.completed = entry_obj.erledigt
                    self.overdue = entry_obj.datum < today_date if entry_obj.datum else False
                
                def _get_kategorie_icon(self, kategorie):
                    icons = {
                        'termin': 'fas fa-calendar-alt',
                        'zahlung': 'fas fa-euro-sign',
                        'deadline': 'fas fa-exclamation-triangle',
                        'geburtstag': 'fas fa-birthday-cake',
                        'vertrag': 'fas fa-file-contract',
                        'pruefung': 'fas fa-search',
                    }
                    return icons.get(kategorie, 'fas fa-calendar')
                
                def _get_prioritaet_color(self, prioritaet):
                    colors = {
                        'niedrig': 'secondary',
                        'normal': 'primary',
                        'mittel': 'warning',
                        'hoch': 'danger',
                    }
                    return colors.get(prioritaet, 'primary')
            
            events.append(CustomEvent(entry, self.today))
        
        return events
    
    def get_upcoming_events(self, days=7):
        """Get upcoming events within specified days"""
        end_date = self.today + timedelta(days=days)
        return self.get_calendar_events(self.today, end_date)
    
    def get_overdue_events(self):
        """Get overdue/past due events"""
        events = self.get_calendar_events(
            start_date=self.today - timedelta(days=30),
            end_date=self.today - timedelta(days=1)
        )
        
        return [event for event in events if event.get('overdue', False)]
    
    def get_events_for_month(self, year, month):
        """Get all events for a specific month"""
        from calendar import monthrange
        
        start_date = date(year, month, 1)
        _, last_day = monthrange(year, month)
        end_date = date(year, month, last_day)
        
        return self.get_calendar_events(start_date, end_date)