from __future__ import annotations

from django.core.exceptions import ValidationError
from django.db.models import (
    CharField,
    DateTimeField,
    EmailField,
    ForeignKey,
    Index,
    JSONField,
    TextChoices,
    TextField,
    SET_NULL,
    CASCADE,
)
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from core.abstract import NiceModel
from vibes_auth.models import User


class ThreadStatus(TextChoices):
    OPEN = "open", _("Open")
    CLOSED = "closed", _("Closed")


class SenderType(TextChoices):
    USER = "user", _("User")
    STAFF = "staff", _("Staff")
    SYSTEM = "system", _("System")


class ChatThread(NiceModel):
    user = ForeignKey(User, null=True, blank=True, on_delete=SET_NULL, related_name="chat_threads")
    email = EmailField(blank=True, default="", help_text=_("For anonymous threads"))
    assigned_to = ForeignKey(User, null=True, blank=True, on_delete=SET_NULL, related_name="assigned_chat_threads")
    status = CharField(max_length=16, choices=ThreadStatus.choices, default=ThreadStatus.OPEN)
    last_message_at = DateTimeField(default=timezone.now)
    attributes = JSONField(default=dict, blank=True)

    class Meta:
        indexes = [
            Index(fields=["status", "modified"], name="chatthread_status_mod_idx"),
            Index(fields=["assigned_to", "status"], name="chatthread_assigned_status_idx"),
            Index(fields=["user"], name="chatthread_user_idx"),
            Index(fields=["email"], name="chatthread_email_idx"),
        ]
        ordering = ("-modified",)
        verbose_name = _("Chat thread")
        verbose_name_plural = _("Chat threads")

    def clean(self) -> None:
        super().clean()
        if not self.user and not self.email:
            raise ValidationError({"email": _("Provide user or email for anonymous thread.")})
        if self.assigned_to and not self.assigned_to.is_staff:
            raise ValidationError({"assigned_to": _("Assignee must be a staff user.")})


class ChatMessage(NiceModel):
    thread = ForeignKey(ChatThread, on_delete=CASCADE, related_name="messages")
    sender_type = CharField(max_length=16, choices=SenderType.choices)
    sender_user = ForeignKey(User, null=True, blank=True, on_delete=SET_NULL, related_name="chat_messages")
    text = TextField()
    sent_at = DateTimeField(default=timezone.now)
    attributes = JSONField(default=dict, blank=True)

    class Meta:
        indexes = [
            Index(fields=["thread", "sent_at"], name="chatmessage_thread_sent_idx"),
        ]
        ordering = ("sent_at", "uuid")
        verbose_name = _("Chat message")
        verbose_name_plural = _("Chat messages")
