from django.db import models
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.contrib.auth.models import PermissionsMixin
from django.core.mail import send_mail


class User(AbstractBaseUser, PermissionsMixin):
    USERNAME_FIELD = "email"
    EMAIL_FIELD = "email"
    REQUIRED_FIELDS = ["public_name"]
    MAX_NAME_LENGTH = 150

    email = models.EmailField(verbose_name="adresse email", unique=True)
    public_name = models.CharField(
        verbose_name="nom ou pseudo",
        max_length=MAX_NAME_LENGTH,
        unique=True,
        help_text="Ce nom est utilisé pour toutes les interactions publiques sur GestioJeux. Il doit être unique.",
    )
    is_staff = models.BooleanField(
        "statut équipe",
        default=False,
        help_text="Précise si l’utilisateur peut se connecter à ce site d'administration.",
    )
    is_active = models.BooleanField(
        "actif",
        default=True,
        help_text="Précise si l’utilisateur doit être considéré comme actif. Décochez ceci plutôt que de supprimer le compte.",
    )

    objects = BaseUserManager()

    class Meta:
        verbose_name = "utilisateur·ice"
        verbose_name_plural = "utilisateur·ice·s"

    @classmethod
    def generate_unique_public_name(cls, base_name):
        index = 0
        public_name = base_name
        while cls.objects.filter(public_name=public_name).exists():
            index += 1

            # ensure the resulting string is not too long
            tail_length = len(str(index))
            combined_length = len(base_name) + tail_length
            if cls.MAX_NAME_LENGTH < combined_length:
                base_name = base_name[: cls.MAX_NAME_LENGTH - tail_length]

            public_name = base_name + str(index)

        return public_name

    def save(self, *args, **kwargs):
        if not self.public_name:
            # Fill the public name with a generated one from email address
            base_name = self.email.split("@")[0]
            self.public_name = User.generate_unique_public_name(base_name)
        super().save(*args, **kwargs)

    def get_full_name(self):
        return self.public_name

    def get_short_name(self):
        return self.public_name

    def email_user(self, subject, message, from_email=None, **kwargs):
        """Send an email to this user."""
        send_mail(subject, message, from_email, [self.email], **kwargs)

    @classmethod
    def normalize_username(cls, username):
        return super().normalize_username(username.lower())

    def __str__(self):
        return self.public_name
