from django.db.models.signals import m2m_changed, post_delete, post_save, pre_delete, pre_save
from django.dispatch import receiver

from api.models import TtActivity, TtLocation, TtStaff, TtWeekPattern
from api.services.integration.tracking import (
    current_tracker,
    track_activity,
    track_activity_created,
    track_activity_ids,
    track_resource,
    track_resource_created,
)


@receiver(pre_save, sender=TtStaff)
@receiver(pre_save, sender=TtLocation)
def resource_pre_save(sender, instance, **kwargs):
    if current_tracker() is None or instance.pk is None:
        return
    existing = sender.objects.filter(pk=instance.pk).first()
    if existing:
        track_resource(existing)


@receiver(post_save, sender=TtStaff)
@receiver(post_save, sender=TtLocation)
def resource_post_save(sender, instance, created, **kwargs):
    if created:
        track_resource_created(instance)


@receiver(pre_delete, sender=TtStaff)
@receiver(pre_delete, sender=TtLocation)
def resource_pre_delete(sender, instance, **kwargs):
    if current_tracker() is None:
        return
    track_resource(instance, deleted=True)
    track_activity_ids(instance.ttactivity_set.values_list("id", flat=True))


@receiver(pre_save, sender=TtActivity)
def activity_pre_save(sender, instance, **kwargs):
    if current_tracker() is None or instance.pk is None:
        return
    existing = (
        sender.objects.filter(pk=instance.pk)
        .select_related("week_pattern")
        .prefetch_related("week", "week_pattern__week", "staff", "location", "student_set")
        .first()
    )
    if existing:
        track_activity(existing)


@receiver(post_save, sender=TtActivity)
def activity_post_save(sender, instance, created, **kwargs):
    if created:
        track_activity_created(instance)


@receiver(pre_delete, sender=TtActivity)
def activity_pre_delete(sender, instance, **kwargs):
    if current_tracker() is not None:
        track_activity(instance, deleted=True)


@receiver(pre_delete, sender=TtWeekPattern)
def week_pattern_pre_delete(sender, instance, **kwargs):
    if current_tracker() is not None:
        track_activity_ids(instance.ttactivity_set.values_list("id", flat=True))


def _track_activity_relation(sender, instance, action, reverse, model, pk_set, **kwargs):
    if current_tracker() is None or action not in {"pre_add", "pre_remove", "pre_clear"}:
        return
    if reverse:
        ids = pk_set or instance.ttactivity_set.values_list("id", flat=True)
        track_activity_ids(ids)
    else:
        track_activity(instance)


m2m_changed.connect(
    _track_activity_relation,
    sender=TtActivity.staff.through,
    dispatch_uid="integration_track_activity_staff",
)
m2m_changed.connect(
    _track_activity_relation,
    sender=TtActivity.location.through,
    dispatch_uid="integration_track_activity_location",
)
m2m_changed.connect(
    _track_activity_relation,
    sender=TtActivity.week.through,
    dispatch_uid="integration_track_activity_week",
)
