"""
Custom Celery Beat scheduler to fix Python 3.12 zoneinfo compatibility issue.
This patches the TzAwareCrontab class to work with zoneinfo.ZoneInfo instead of pytz.

The error occurs because django-celery-beat assumes pytz timezone objects
which have a `normalize()` method that zoneinfo.ZoneInfo doesn't have.
"""
import functools


# Flag to track if patch has been applied
_patch_applied = False


def apply_tzcrontab_patch():
    """
    Apply monkey-patch to django_celery_beat.tzcrontab.TzAwareCrontab
    to fix zoneinfo.ZoneInfo compatibility.
    
    This should be called at Celery app initialization.
    """
    from django_celery_beat import tzcrontab
    
    original_init = tzcrontab.TzAwareCrontab.__init__
    
    @functools.wraps(original_init)
    def patched_init(self, *args, **kwargs):
        # Get the tz argument, default to None
        tz = kwargs.get('tz', None)
        
        # Check if it's a zoneinfo.ZoneInfo (no 'normalize' attribute)
        if tz is not None and not hasattr(tz, 'normalize'):
            # Replace with a patched nowfun that works with zoneinfo
            def zoneinfo_aware_nowfunc():
                """Get current time in the scheduler's timezone using Django's timezone utility."""
                from django.utils import timezone as django_timezone
                now = django_timezone.now()
                return now.astimezone(self.tz)
            
            # Store the zoneinfo-compatible nowfun
            self._zoneinfo_nowfun = zoneinfo_aware_nowfunc
        
        # Call original init
        original_init(self, *args, **kwargs)
        
        # If we detected zoneinfo, override the nowfun
        if hasattr(self, '_zoneinfo_nowfun'):
            self.nowfun = self._zoneinfo_nowfun
    
    tzcrontab.TzAwareCrontab.__init__ = patched_init


class PatchedDatabaseScheduler:
    """
    Wrapper class that applies the zoneinfo patch before importing the real scheduler.
    
    This class is referenced in CELERY_BEAT_SCHEDULER setting and lazily imports
    the actual DatabaseScheduler after applying the patch.
    """
    
    def __new__(cls, *args, **kwargs):
        """Apply patch and return the actual DatabaseScheduler instance."""
        global _patch_applied
        
        if not _patch_applied:
            apply_tzcrontab_patch()
            _patch_applied = True
        
        from django_celery_beat.schedulers import DatabaseScheduler
        return DatabaseScheduler(*args, **kwargs)
