"""
Models module for the chat app.
"""
from django.db import models
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

from django_extensions.db.models import TimeStampedModel


class Inbox(models.Model):
    """
    Inbox model. This model contains the messages sent between users.
    """

    owner = models.ForeignKey(
        "users.User",
        on_delete=models.CASCADE,
        related_name="inbox",
    )
    sender = models.ForeignKey(
        "users.User",
        on_delete=models.CASCADE,
        related_name="sent_inbox",
    )
    has_unread = models.BooleanField(default=False)
    messages = models.ManyToManyField("chat.Message", related_name="inbox")


class Message(TimeStampedModel, models.Model):
    """
    A private direct message.
    """

    content = models.TextField(_("Content"))
    sender = models.ForeignKey(
        "users.User",
        on_delete=models.CASCADE,
        related_name="sent_dm",
        verbose_name=_("Sender"),
    )
    recipient = models.ForeignKey(
        "users.User",
        on_delete=models.CASCADE,
        related_name="received_dm",
        verbose_name=_("Recipient"),
    )
    read_at = models.DateTimeField(_("read at"), null=True, blank=True)

    @property
    def unread(self):
        """returns whether the message was read or not"""
        return self.read_at is None

    def save(self, *args, **kwargs):
        if self.sender == self.recipient:
            raise ValidationError("You can't send messages to yourself")

        new = not self.id

        super().save(*args, **kwargs)

        if new:
            self.set_unread_inbox()
            self.add_message_to_inbox()

    def set_unread_inbox(self):
        """
        Mark recipient inbox as unread.
        """
        recipient_inbox, _ = Inbox.objects.get_or_create(
            owner=self.recipient,
            sender=self.sender,
        )
        recipient_inbox.has_unread = True
        recipient_inbox.save()

    def get_recipient_inbox(self):
        recipient_inbox, _ = Inbox.objects.get_or_create(
            owner=self.recipient,
            sender=self.sender,
        )
        return recipient_inbox

    def get_sender_inbox(self):
        sender_inbox, _ = Inbox.objects.get_or_create(
            owner=self.sender,
            sender=self.recipient,
        )
        return sender_inbox

    def add_message_to_inbox(self):
        """
        Add message to sender and recipient inbox.
        """
        self.inbox.add(
            self.get_recipient_inbox(),
            self.get_sender_inbox(),
        )  # pylint: disable=E1101
