"""Public configuration write/read API; this does not validate device values."""
from django.db import transaction

from .models import DeviceIdentificationPolicy, ProductModel


def _model_id(product_model):
    if (not isinstance(product_model, ProductModel) or product_model.pk is None
            or product_model._state.adding or product_model._state.db != "default"):
        raise ValueError("Supply a saved ProductModel from the default database.")
    return product_model.pk


def set_identification_policy(*, product_model, imei1_requirement, imei2_requirement, serial_requirement):
    """Atomically create/replace requirements; concurrent calls serialize on model."""
    with transaction.atomic():
        parent = ProductModel.objects.select_for_update().get(pk=_model_id(product_model))
        policy = DeviceIdentificationPolicy.objects.filter(product_model=parent).first()
        if policy is None:
            policy = DeviceIdentificationPolicy(product_model=parent)
        policy.imei1_requirement = imei1_requirement
        policy.imei2_requirement = imei2_requirement
        policy.serial_requirement = serial_requirement
        policy.save()
        return policy


def get_identification_policy(product_model):
    """Return current configuration, or None for UNCONFIGURED; ignore relation caches.

    A saved model is required; a deleted model raises ProductModel.DoesNotExist.
    An all-NOT_APPLICABLE policy is a real configured object, never None.
    """
    parent = ProductModel.objects.get(pk=_model_id(product_model))
    return DeviceIdentificationPolicy.objects.filter(product_model=parent).first()
