from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _


class NoActiveTermsOfService(ValidationError):
    pass


class BaseModel(models.Model):
    created = models.DateTimeField(auto_now_add=True, editable=False)
    modified = models.DateTimeField(auto_now=True, editable=False)

    class Meta:
        abstract = True


class TermsOfServiceManager(models.Manager):
    def get_current_tos(self):
        try:
            return self.get(active=True)
        except self.model.DoesNotExist:
            raise NoActiveTermsOfService(
                'Please create an active Terms-of-Service'
            )


class TermsOfService(BaseModel):
    active = models.BooleanField(
                default=False,
                verbose_name=_('active'),
                help_text=_(
                    'Only one terms of service is allowed to be active'
                )
    )
    content = models.TextField(verbose_name=_('content'), blank=True)
    objects = TermsOfServiceManager()

    class Meta:
        get_latest_by = 'created'
        ordering = ('-created',)
        verbose_name = _('Terms of Service')
        verbose_name_plural = _('Terms of Service')

    def __str__(self):
        active = 'inactive'
        if self.active:
            active = 'active'
        return f'{self.created}: {active}'

    def save(self, *args, **kwargs):
        """ Ensure we're being saved properly """

        if self.active:
            TermsOfService.objects.exclude(id=self.id).update(active=False)

        else:
            if not TermsOfService.objects\
                    .exclude(id=self.id)\
                    .filter(active=True)\
                    .exists():
                raise NoActiveTermsOfService(
                    'One of the terms of service must be marked active'
                )

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


class UserAgreement(BaseModel):
    terms_of_service = models.ForeignKey(TermsOfService, related_name='terms', on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='user_agreement', on_delete=models.CASCADE)

    def __str__(self):
        return f'{self.user.username} agreed to TOS: {self.terms_of_service}'


def has_user_agreed_latest_tos(user):
    return UserAgreement.objects.filter(
        terms_of_service=TermsOfService.objects.get_current_tos(),
        user=user,
    ).exists()
