from django.contrib.auth.base_user import BaseUserManager


class CustomUserManager(BaseUserManager):
    """
    Creates users keyed on email rather than username.

    Django's own UserManager takes `username` as its first positional argument
    and passes it to the model, which no longer has that field. Every entry
    point goes through here: `createsuperuser` reads USERNAME_FIELD off the
    model and calls `create_superuser(email=..., password=...)`.

    THE WHOLE ADDRESS IS LOWERCASED, not just the domain half that
    `normalize_email` handles. The unique constraint is a plain column
    constraint, so `Sam@example.com` and `sam@example.com` would otherwise be
    two accounts — and only one of them could ever be signed into, since
    ModelBackend looks the address up with an exact match. Anything that
    resolves a user from typed input must lowercase it the same way; the
    waitlist and newsletter forms already do.
    """

    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError('Users must have an email address.')
        email = self.normalize_email(email).strip().lower()
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)
