import logging

from celery import shared_task

from apps.core.notifications import channels as notification_channels
from apps.core.notifications.models import Notification, NotificationPreference

logger = logging.getLogger(__name__)

CHANNEL_HANDLERS = {
    NotificationPreference.Channel.IN_APP: notification_channels.InAppChannel,
    NotificationPreference.Channel.EMAIL: notification_channels.EmailChannel,
    NotificationPreference.Channel.SMS: notification_channels.SMSChannel,
}


@shared_task(
    bind=True,
    autoretry_for=(Exception,),
    retry_backoff=True,
    retry_kwargs={"max_retries": 3},
    retry_backoff_max=600,
)
def dispatch_notification_channel(self, notification_id: int, channel: str, context: dict):
    try:
        notification = Notification.objects.select_related("recipient").get(pk=notification_id)
    except Notification.DoesNotExist:
        logger.warning("notification %s missing", notification_id)
        return

    handler = CHANNEL_HANDLERS.get(channel)
    if not handler:
        logger.warning("unknown channel %s", channel)
        return

    if channel == NotificationPreference.Channel.EMAIL and notification.email_sent:
        return

    handler.deliver(notification, context)
