"""
Celery configuration for Stream Processor Django project.

This module configures Celery for handling background tasks such as:
- Stream capture and processing
- Jingle detection and ad break analysis
- Telegram notification sending
- Periodic maintenance tasks
- File system monitoring

Celery allows the application to process time-consuming tasks asynchronously,
improving user experience and system responsiveness.
"""

import os
from celery import Celery
from django.conf import settings

# Set the default Django settings module for the 'celery' program
# This ensures Celery uses the same settings as the Django application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')

# Create Celery application instance
# The name should match the Django project name for consistency
app = Celery('core')

# Configure Celery using Django settings
# Use the CELERY namespace to avoid conflicts with Django settings
app.config_from_object('django.conf:settings', namespace='CELERY')

# Task discovery configuration
# Automatically discover tasks from all registered Django apps
app.autodiscover_tasks()

# Task routing configuration
# Route specific tasks to specific queues for better resource management
app.conf.task_routes = {
    # Stream processing tasks - high priority queue
    'apps.streams.tasks.*': {'queue': 'stream_processing'},
    # Jingle detection tasks - medium priority queue
    'apps.jingles.tasks.*': {'queue': 'jingle_detection'},
    # Notification tasks - low priority queue
    'apps.notifications.tasks.*': {'queue': 'notifications'},
    # Monitoring tasks - maintenance queue
    'apps.monitoring.tasks.*': {'queue': 'monitoring'},
}

# Queue configuration
# Define different queues for different types of tasks
app.conf.task_default_queue = 'default'
app.conf.task_queues = {
    # High priority queue for stream processing
    'stream_processing': {
        'exchange': 'stream_processing',
        'routing_key': 'stream_processing',
    },
    # Medium priority queue for jingle detection
    'jingle_detection': {
        'exchange': 'jingle_detection',
        'routing_key': 'jingle_detection',
    },
    # Low priority queue for notifications
    'notifications': {
        'exchange': 'notifications',
        'routing_key': 'notifications',
    },
    # Maintenance queue for monitoring tasks
    'monitoring': {
        'exchange': 'monitoring',
        'routing_key': 'monitoring',
    },
}

# Task execution configuration
# Set default task execution parameters
app.conf.update(
    # Task result expiration time (1 hour)
    result_expires=3600,
    # Task time limit (10 minutes)
    task_time_limit=600,
    # Task soft time limit (8 minutes)
    task_soft_time_limit=480,
    # Enable task result compression
    result_compression='gzip',
    # Task serializer format
    task_serializer='json',
    # Result serializer format
    result_serializer='json',
    # Accept content types
    accept_content=['json'],
    # Timezone settings
    timezone=settings.TIME_ZONE,
    enable_utc=True,
    # Worker configuration
    worker_prefetch_multiplier=1,
    worker_max_tasks_per_child=1000,
    # Task acknowledgment configuration
    task_acks_late=True,
    task_reject_on_worker_lost=True,
)

# Error handling configuration
# Configure task retry and error handling behavior
app.conf.task_annotations = {
    # Stream capture tasks configuration
    'apps.streams.tasks.capture_stream': {
        'rate_limit': '10/m',  # Maximum 10 captures per minute
        'max_retries': 10,
        'default_retry_delay': 15,  # 15 seconds delay between retries
    },
    # Jingle detection tasks configuration
    'apps.jingles.tasks.detect_jingle': {
        'rate_limit': '50/m',  # Maximum 50 detections per minute
        'max_retries': 10,
        'default_retry_delay': 15,  # 15 seconds delay between retries
    },
    # Notification tasks configuration
    'apps.notifications.tasks.send_telegram_message': {
        'rate_limit': '100/m',  # Maximum 100 messages per minute
        'max_retries': 10,
        'default_retry_delay': 10,  # 10 seconds delay between retries
    },
}

# Monitoring and logging configuration
# Enable task monitoring and result tracking
app.conf.worker_send_task_events = True
app.conf.task_send_sent_event = True

# Beat schedule configuration (imported from Django settings)
# Periodic tasks are defined in Django settings and imported here
if hasattr(settings, 'CELERY_BEAT_SCHEDULE'):
    app.conf.beat_schedule = settings.CELERY_BEAT_SCHEDULE


@app.task(bind=True)
def debug_task(self):
    """
    Debug task for testing Celery configuration.
    
    This task can be used to verify that Celery is properly configured
    and can execute tasks. It's primarily used for debugging and testing.
    
    Args:
        self: The task instance (automatically provided by bind=True)
        
    Returns:
        str: Debug information about the task execution
    """
    print(f'Request: {self.request!r}')
    return f'Debug task executed successfully at {self.request.id}'


# Signal handlers for task monitoring
@app.task(bind=True)
def task_failure_handler(self, task_id, error, traceback):
    """
    Handle task failures for monitoring and alerting.
    
    This task is called when other tasks fail, allowing for centralized
    error handling, logging, and notification of failures.
    
    Args:
        self: The task instance
        task_id (str): ID of the failed task
        error (str): Error message from the failed task
        traceback (str): Stack trace of the failure
        
    Returns:
        bool: True if failure handling was successful
    """
    from apps.notifications.tasks import send_telegram_message
    
    # Log the failure
    print(f'Task {task_id} failed: {error}')
    
    # Send notification about the failure (if enabled)
    if settings.TELEGRAM_CONFIG.get('ENABLED'):
        send_telegram_message.delay(
            f'🚨 Task Failure Alert 🚨\n'
            f'Task ID: {task_id}\n'
            f'Error: {error}'
        )
    
    return True
