# -*- encoding: utf-8 -*-

import uuid

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.utils.translation import gettext_lazy as _


class Department(models.Model):
    title = models.CharField(max_length=150)
    icon = models.CharField(max_length=32, null=True, blank=True)

    def __str__(self):
        return self.title

    def serialize(self) -> dict:
        return {
            "title": self.title,
            "icon": self.icon
        }


class UserManager(BaseUserManager):

    def create_user(self, email: str, forename: str, surname: str, password: str=None, **extra_fields):
        if not email:
            raise ValueError("Please provide an email address")

        email = self.normalize_email(email)
        user = self.model(email=email, forename=forename, surname=surname, **extra_fields)
        user.set_password(password)
        user.save()

        return user

    def create_superuser(self, email: str, forename: str, surname: str, password: str, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        extra_fields.setdefault("is_active", True)

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

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

        return self.create_user(email, forename, surname, password, **extra_fields)


class User(AbstractBaseUser, PermissionsMixin):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    icon = models.ImageField(_("profile picture"), upload_to="users", default="users/default.webp")
    email = models.EmailField(
        _("email address"),
        unique=True,
        error_messages = {
            "unique": _("A user with this email address already exists.")
        }
    )
    forename = models.CharField(
        _("first name"),
        max_length=150,
        help_text=_("This should be your real first name.")
    )
    surname = models.CharField(
        _("last name"),
        max_length=150,
        help_text=_("This should be your real last name.")
    )

    department = models.ForeignKey(
        Department,
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        verbose_name=_("department"),
        help_text=_("Which department does this user belong to?")
    )

    create_timestamp = models.DateTimeField(
        _("Creation Date"),
        editable=True,
        default=timezone.now,
        help_text=_("When the user was created.")
    )
    edit_timestamp = models.DateTimeField(
        _("Last Edited"),
        editable=True,
        default=timezone.now,
        help_text=_("When the user was last edited.")
    )

    is_active = models.BooleanField(
        _("active status"),
        default=True,
        help_text=_('Use as a "soft delete" rather than deleting the user.')
    )
    is_staff = models.BooleanField(
        _("staff status"),
        default=False,
        help_text=_("Designates whether the user can log into this admin site.")
    )
    is_superuser = models.BooleanField(
        _("superuser status"),
        default=False,
        help_text=_("Designates whether the user has unrestricted site control.")
    )

    USERNAME_FIELD = "email"
    EMAIL_FIELD = "email"
    REQUIRED_FIELDS = ["forename", "surname"]

    objects = UserManager()

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def __str__(self):
        return f"{self.id} • {self.email} • {self.formal_fullname}"

    def save(self, *args, **kwargs):
        self.edit_timestamp = timezone.now()
        super().save(*args, **kwargs)

    def clean(self):
        super().clean()
        self.email = self.__class__.objects.normalize_email(self.email)

    @property
    def fullname(self) -> str:
        return f"{self.forename} {self.surname}"

    @property
    def formal_fullname(self) -> str:
        return f"{self.surname}, {self.forename}"

    def serialize(self) -> dict:
        department = self.department.serialize() if self.department else None

        return {
            "id": self.id,
            "icon": self.icon.url,
            "email": self.email,
            "forename": self.forename,
            "surname": self.surname,
            "department": department,
            "create_timestamp": self.create_timestamp,
            "edit_timestamp": self.edit_timestamp
        }
