import logging
from django.db import models

from account.models import CustomUser
from vontor_cz.models import SoftDeleteModel

logger = logging.getLogger(__name__)


class Notification(SoftDeleteModel):
    class Type(models.TextChoices):
        SYSTEM = "system", "Systém"
        ORDER = "order", "Objednávka"
        PAYMENT = "payment", "Platba"
        SOCIAL = "social", "Sociální"
        CHAT = "chat", "Chat"
        ADVERTISEMENT = "advertisement", "Inzerát"

    title = models.CharField(max_length=200, help_text="Předmět oznámení.")
    text = models.TextField(help_text="Obsah oznámení.")

    notification_type = models.CharField(
        max_length=20,
        choices=Type.choices,
        default=Type.SYSTEM,
        help_text="Kategorie oznámení — používá se pro ikonky a filtrování na frontendu.",
    )
    action_url = models.CharField(
        max_length=500,
        null=True,
        blank=True,
        help_text="Volitelný odkaz na detail (např. '/objednavky/123/').",
    )

    created_at = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(
        CustomUser, on_delete=models.CASCADE, null=True, related_name='notifications',
        help_text="Příjemce oznámení.",
    )
    bulk = models.BooleanField(
        default=False,
        help_text="True, pokud bylo oznámení vytvořeno hromadně pro více uživatelů.",
    )

    is_read = models.BooleanField(default=False)
    read_at = models.DateTimeField(null=True, blank=True)

    send_email = models.BooleanField(
        default=False,
        help_text="True, pokud byl zároveň odeslán e-mail.",
    )
    email_subject = models.CharField(max_length=255, null=True, blank=True)
    email_template_path = models.CharField(max_length=255, null=True, blank=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return self.title

    @classmethod
    def notify(cls, user=None, title=None, text=None, *, users=None,
               notification_type=None, action_url=None,
               email_subject=None, template_path=None,
               email_context=None, attachments=None, bulk=False):
        """Create an in-app notification and optionally send an email + WebSocket push.

        Modes:
          • Single  — user=<CustomUser>   → returns Notification
          • Bulk    — users=<list|qs>     → returns list[Notification]

        notification_type controls the frontend icon/colour (default: system).
        action_url is an optional relative path the bell badge links to.
        If template_path is set, an email is dispatched (Celery if CELERY_ENABLED, else sync).
        """
        if users is not None:
            return [
                cls.notify(
                    user=u, title=title, text=text,
                    notification_type=notification_type, action_url=action_url,
                    email_subject=email_subject, template_path=template_path,
                    email_context=email_context, attachments=attachments,
                    bulk=True,
                )
                for u in users
            ]

        if user is None:
            raise ValueError("Notification.notify() requires either 'user' or 'users'.")

        notification = cls.objects.create(
            user=user,
            title=title,
            text=text,
            notification_type=notification_type or cls.Type.SYSTEM,
            action_url=action_url,
            bulk=bulk,
            send_email=bool(template_path),
            email_subject=email_subject,
            email_template_path=template_path,
        )

        # Real-time push via WebSocket
        try:
            from channels.layers import get_channel_layer
            from asgiref.sync import async_to_sync
            channel_layer = get_channel_layer()
            if channel_layer:
                async_to_sync(channel_layer.group_send)(
                    f"notifications_{user.pk}",
                    {
                        "type": "notification.new",
                        "id": notification.pk,
                        "title": notification.title,
                        "text": notification.text,
                        "notification_type": notification.notification_type,
                        "action_url": notification.action_url,
                        "created_at": notification.created_at.isoformat(),
                    },
                )
        except Exception as exc:
            logger.warning("[Notification.notify] WebSocket push failed for user %s: %s", user.pk, exc)

        if template_path and getattr(user, 'email', None):
            try:
                from django.conf import settings
                from notifications.tasks import send_notification_email_task
                ctx = dict(email_context or {})
                if 'user' not in ctx:
                    ctx['user'] = user
                kwargs = dict(
                    recipient_email=user.email,
                    subject=email_subject or title,
                    template_path=template_path,
                    context=ctx,
                    attachments=attachments,
                )
                if getattr(settings, 'CELERY_ENABLED', False):
                    send_notification_email_task.delay(**kwargs)
                else:
                    send_notification_email_task(**kwargs)
            except Exception as exc:
                logger.warning("[Notification.notify] Email failed for user %s: %s", user.pk, exc)

        return notification
