from django.db import transaction
from django.db.models import signals
from django.dispatch import receiver

from lms.classrooms.models import StudentSlot
from lms.enrollments.models import EnrolledUser, Enrollment

from .models import EnrollmentTrackerQueue, TrackerHook, TrackerHookEvent
from .services import update_is_default
from .tasks import (
    process_tracker_enrolled_user_task, process_tracker_hook_event_task, process_tracker_hook_task,
    process_tracker_student_slot_cancel_task, process_tracker_student_slot_create_task,
)


@receiver(signal=signals.post_save, sender=EnrollmentTrackerQueue)
def enrolled_tracker_queue_post_save_is_default_handler(instance: EnrollmentTrackerQueue, **kwargs):
    update_is_default(instance)


@receiver(signal=signals.post_save, sender=EnrolledUser)
def enrolled_user_post_save_handler(instance: EnrolledUser, created, **kwargs):
    if (
        created and
        instance.enrollment.enroll_type == Enrollment.TYPE_TRACKER and
        instance.status == EnrolledUser.StatusChoices.PENDING
    ):
        transaction.on_commit(lambda: process_tracker_enrolled_user_task.delay(enrolled_user_id=instance.id))


@receiver(signal=signals.post_save, sender=TrackerHookEvent)
def tracker_hook_event_post_save_handler(instance: TrackerHookEvent, **kwargs):
    if instance.status == TrackerHookEvent.STATUS_PENDING:
        transaction.on_commit(lambda: process_tracker_hook_event_task.delay(tracker_hook_event_id=instance.id))


@receiver(signal=signals.post_save, sender=StudentSlot)
def student_slot_post_save_handler(instance: StudentSlot, created: bool, **kwargs):
    statuses = StudentSlot.StatusChoices

    if created:
        transaction.on_commit(lambda: process_tracker_student_slot_create_task.delay(student_slot_id=instance.id))

        return

    # TODO: LMSDEV-1935: [API] Писать в трекер коммент о том, что произошел обмен или перезапись
    if instance.tracker.has_changed('status') and instance.status in [statuses.CANCELED, statuses.EXCHANGED]:
        transaction.on_commit(lambda: process_tracker_student_slot_cancel_task.delay(student_slot_id=instance.id))


@receiver(signal=signals.post_save, sender=TrackerHook)
def tracker_hook_post_save_handler(instance: TrackerHook, **kwargs):
    if instance.status == TrackerHook.Status.PENDING:
        transaction.on_commit(lambda: process_tracker_hook_task.delay(tracker_hook_id=instance.id))
