from django.contrib.auth import get_user_model
from django.db import models, transaction
from django.dispatch import receiver

from mentor.users.signals import user_logged_in
from mentor.utils.defer import defer_or_sync
from mentor.utils.ltree import update_node_path

from .models import StaffGroup, StaffProfile
from .services import is_profile_updated, load_staff_profile

User = get_user_model()


@receiver(
    signal=models.signals.post_save, sender=User, dispatch_uid="user_post_save_handler"
)
def user_post_save_handler(instance: User, created, **kwargs):
    if created or not getattr(instance, "staff_profile", None):
        StaffProfile.objects.get_or_create(user=instance)
        transaction.on_commit(
            lambda: defer_or_sync(load_staff_profile, {"args": [instance.pk]})
        )


@receiver(signal=models.signals.post_save, sender=StaffGroup)
def staff_group_post_save_handler(instance: StaffGroup, **kwargs):
    update_node_path(instance)


@receiver(signal=user_logged_in, dispatch_uid="update_staff_profile")
def user_logged_in_handler(user: User, **kwargs):
    if not is_profile_updated(user.pk):
        defer_or_sync(load_staff_profile, {"args": [user.pk]})
