"""Explicit atomic catalog lifecycle operations on persisted records."""
from django.db import transaction
from django.utils import timezone

from .models import Brand, ProductCategory, ProductModel, ProductVariant


def _deactivate(instance):
    with transaction.atomic():
        model = type(instance)
        record = model.objects.select_for_update().get(pk=instance.pk)
        now = timezone.now()
        if model in (Brand, ProductCategory):
            # Include inactive models defensively, and lock in one common order
            # for overlapping Brand/Category cascades before touching variants.
            ids = list(record.product_models.order_by("pk").select_for_update().values_list("pk", flat=True))
            ProductVariant.objects.filter(product_model_id__in=ids, is_active=True).update(is_active=False, updated_at=now)
            ProductModel.objects.filter(pk__in=ids, is_active=True).update(is_active=False, updated_at=now)
        elif model is ProductModel:
            ProductVariant.objects.filter(product_model=record, is_active=True).update(is_active=False, updated_at=now)
        model.objects.filter(pk=record.pk, is_active=True).update(is_active=False, updated_at=now)
        record.refresh_from_db()
        return record


def _reactivate(instance):
    # Save acquires dependency locks before the target lock and reloads validation
    # state. Only the active field changes; pending edits on input are ignored.
    with transaction.atomic():
        record = type(instance).objects.get(pk=instance.pk)
        record.is_active = True
        record.save(update_fields=["is_active"])
        record.refresh_from_db()
        return record


def deactivate_brand(*, brand):
    return _deactivate(brand)


def reactivate_brand(*, brand):
    return _reactivate(brand)


def deactivate_category(*, category):
    return _deactivate(category)


def reactivate_category(*, category):
    return _reactivate(category)


def deactivate_product_model(*, product_model):
    return _deactivate(product_model)


def reactivate_product_model(*, product_model):
    return _reactivate(product_model)


def deactivate_variant(*, variant):
    return _deactivate(variant)


def reactivate_variant(*, variant):
    return _reactivate(variant)
