from django.db import models
from django.conf import settings
from django.core.exceptions import ValidationError
from django.utils import timezone
from vontor_cz.custom_fields import WebPImageField
from vontor_cz.models import SoftDeleteModel

class Chat(SoftDeleteModel):
    AUTHOR_FIELD = 'owner'

    class ChatType(models.TextChoices):
        DM = 'DM', 'Direct Message'
        GROUP = 'GROUP', 'Group'

    chat_type = models.CharField(
        max_length=10,
        choices=ChatType.choices,
        default=ChatType.GROUP,
    )

    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        related_name='owned_chats'
    )

    name = models.CharField(max_length=255, blank=True)

    icon = WebPImageField(upload_to='chat_icons/', null=True, blank=True)
    banner = WebPImageField(upload_to='chat_banners/', null=True, blank=True)
    
    members = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='chats',
        blank=True
    )

    moderators = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='moderated_chats',
        blank=True
    )

    hub = models.ForeignKey(
        'hubs.Hub',
        on_delete=models.CASCADE,
        null=True,
        blank=True
    )

    

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def save(self, *args, **kwargs):
        is_new = self._state.adding
        super().save(*args, **kwargs)
        
        # LOGIC: Ensure owner is always a member and moderator
        if is_new and self.owner:
            self.members.add(self.owner)
            self.moderators.add(self.owner)

    def clean(self):
        if self.chat_type == self.ChatType.DM:
            member_count = self.members.count() if self.pk else 0
            if member_count > 2:
                raise ValidationError("A DM chat cannot have more than 2 members.")

    def __str__(self):
        return f"Chat {self.id}"


class Message(SoftDeleteModel):
    AUTHOR_FIELD = 'sender'

    chat = models.ForeignKey(Chat, related_name='messages', on_delete=models.CASCADE)
    
    sender = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        related_name='sent_messages'
    )

    #odpověď na jinou zprávu
    reply_to = models.ForeignKey(
        'self',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='replies'
    )
    
    content = models.TextField(blank=True) 

    # --- TRACKING EDIT STATUS ---
    # We add these so the frontend doesn't need to check MessageHistory table
    is_edited = models.BooleanField(default=False)
    edited_at = models.DateTimeField(null=True, blank=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def clean(self):
        if self.chat_id and self.sender_id:
            if not self.chat.members.filter(id=self.sender_id).exists():
                raise ValidationError("Sender is not a member of this chat.")

    # --- HELPER METHODS FOR WEBSOCKETS / VIEWS ---

    def edit_content(self, new_text):
        """
        Handles the complex logic of editing:
        1. Checks if text actually changed.
        2. Saves old text to History.
        3. Updates current text and timestamps.
        """
        if self.content == new_text:
            return False  # No change happened

        # 1. Save History
        MessageHistory.objects.create(
            message=self,
            old_content=self.content
        )

        # 2. Update Self
        self.content = new_text
        self.is_edited = True
        self.edited_at = timezone.now()
        self.save()
        return True

    def toggle_reaction(self, user, emoji):
        """
        Handles Add/Remove/Switch logic.
        Returns a tuple: (action, reaction_object)
        action can be: 'added', 'removed', 'switched'
        """
        try:
            reaction = MessageReaction.objects.get(message=self, user=user)

            if reaction.emoji == emoji:
                reaction.delete()
                return 'removed', None
            else:
                reaction.emoji = emoji
                reaction.save()
                return 'switched', reaction

        except MessageReaction.DoesNotExist:
            # Restore a stale soft-deleted record if one exists (avoids unique_together violation).
            stale = MessageReaction.all_objects.filter(message=self, user=user).first()
            if stale:
                stale.emoji = emoji
                stale.is_deleted = False
                stale.deleted_at = None
                stale.save()
                return 'added', stale

            reaction = MessageReaction.objects.create(message=self, user=user, emoji=emoji)
            return 'added', reaction

    def __str__(self):
        return f"Message {self.id} from {self.sender}"


class MessageHistory(SoftDeleteModel):
    message = models.ForeignKey(
        Message, 
        on_delete=models.CASCADE, 
        related_name='edit_history'
    )
    old_content = models.TextField()
    archived_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['-archived_at']


class MessageReaction(SoftDeleteModel):
    message = models.ForeignKey(
        Message, 
        on_delete=models.CASCADE, 
        related_name='reactions'
    )
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    emoji = models.CharField(max_length=10) 
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["message", "user"],
                condition=models.Q(is_deleted=False),
                name="unique_active_reaction_per_user_message",
            )
        ]
    
    def __str__(self):
        return f"{self.user} reacted {self.emoji}"


class MessageFile(SoftDeleteModel):
    message = models.ForeignKey(
        Message, 
        on_delete=models.CASCADE, 
        related_name='media_files' 
    )
    file = models.FileField(upload_to='chat_uploads/%Y/%m/%d/')

    media_type = models.CharField(max_length=20, choices=[
        ('IMAGE', 'Image'), 
        ('VIDEO', 'Video'), 
        ('FILE', 'File')
    ], default='FILE')

    uploaded_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"Media {self.id} for Message {self.message.id}"


class ChatReadStatus(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='chat_read_statuses',
    )
    chat = models.ForeignKey(
        Chat,
        on_delete=models.CASCADE,
        related_name='read_statuses',
    )
    last_read_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ('user', 'chat')

    def __str__(self):
        return f"{self.user} read {self.chat} at {self.last_read_at}"