import functools
import logging

from django.db import models
from django.contrib.auth.models import User, Group
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings

from rest_framework.authtoken.models import Token

from .mixins import TimesStampMixin, SoftDeleteMixin, DefaultPrivateMixin

from .utils import generate_thumbnail, content_file_name

logger = logging.getLogger(__name__)


@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    """
    Gives each newly created user an auth token by default
    """

    if created:
        Token.objects.create(user=instance)


class MemberPreferences(models.Model):

    notifications = models.JSONField(null=True)


class Member(User, TimesStampMixin, SoftDeleteMixin, DefaultPrivateMixin):
    phone = models.CharField(max_length=100, blank=True, null=True)
    profile = models.ImageField(
        null=True, blank=True, upload_to=functools.partial(content_file_name, "profile")
    )
    profile_thumbnail = models.ImageField(null=True, blank=True)

    verified = models.BooleanField(
        default=False,
        help_text="Used to indicate that a user is regarded as 'verified' - for example"
        "  by verifying their email address. This allows the concept of"
        "  users who have been invited to a portal - but can't yet interact"
        "  with it in most ways. A user coming from an OIDC provider"
        " might be assumed verified - based on properties of that provider.",
    )

    preferences = models.ForeignKey(
        MemberPreferences, null=True, on_delete=models.SET_NULL, related_name="member"
    )

    class Meta:
        verbose_name = "Portal Member"
        verbose_name_plural = "Portal Members"

    def __str__(self):
        return self.username

    @classmethod
    def post_create(cls, sender, instance, created, *args, **kwargs):

        if not created:
            return

        if settings.AUTO_VERIFY_USERS:
            logger.info("Auto-verifying user")
            instance.verified = True

        if settings.AUTO_ASSIGNED_USER_GROUP:
            # If there's an auto-assign group assign them
            group = Group.objects.filter(name=settings.AUTO_ASSIGNED_USER_GROUP).first()
            if group:
                logger.info("Auto-assigning member to group")
                instance.groups.add(group)

        instance.preferences = MemberPreferences.objects.create()

    def save(self, *args, **kwargs):
        if not self.profile:
            self.profile_thumbnail = None
        else:
            self.profile_thumbnail.name = generate_thumbnail(
                self, "profile", self.profile
            )
        super().save(*args, **kwargs)


post_save.connect(Member.post_create, sender=Member)


@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_member(sender, instance=None, created=False, **kwargs):
    """
    When we create users also create a corresponding member
    Exclude first user (as admin)
    """

    if created and instance.pk > 1:
        logger.info("Upgrading User to Member")
        # Create an associated Member
        member = Member(user_ptr_id=instance.pk)
        member.__dict__.update(instance.__dict__)
        member.save()


MEMBER_ID_CHOICES = [("ORCID", "ORCID"), ("FREEFORM", "Freeform")]


class MemberIdentifier(models.Model):
    id_type = models.CharField(max_length=8, choices=MEMBER_ID_CHOICES)
    value = models.CharField(max_length=48)
    member = models.ForeignKey(
        Member, on_delete=models.CASCADE, related_name="identifiers"
    )
