"""Explicit customer-owned device registration using existing registry services."""
from django import forms
from django.contrib.auth.decorators import login_required
from django.core.exceptions import ValidationError
from django.db import transaction
from django.shortcuts import get_object_or_404,render,redirect
from django.views.decorators.http import require_http_methods
from django.views.decorators.cache import never_cache
from apps.access.authorization import require_permission,is_authorized
from apps.catalog.models import ProductModel,ProductVariant
from apps.devices import services
from .queries import customers

PERMISSIONS=("devices.add_device","devices.add_customerdevicerelationship","devices.view_device")


def permitted(actor,customer):
    return all(is_authorized(user=actor,permission=p,target=customer.company) for p in PERMISSIONS)


class RegistrationForm(forms.Form):
    product_model=forms.ModelChoiceField(queryset=ProductModel.objects.filter(is_active=True,brand__is_active=True,
        category__is_active=True,identification_policy__isnull=False).select_related("brand","category"))
    product_variant=forms.ModelChoiceField(queryset=ProductVariant.objects.filter(is_active=True,
        product_model__is_active=True,product_model__brand__is_active=True,product_model__category__is_active=True),required=False)
    imei1=forms.CharField(max_length=128,required=False)
    imei2=forms.CharField(max_length=128,required=False)
    serial=forms.CharField(max_length=128,required=False)
    ownership_confirmed=forms.BooleanField(label="I verified that this customer owns this device; do not use this form for a presenter who is not the owner")

    def clean(self):
        data=super().clean()
        variant=data.get("product_variant")
        # locked_catalog already rejects a variant of another model; report the
        # mismatch on the field instead of after an opaque service failure.
        if variant and data.get("product_model") and variant.product_model_id!=data["product_model"].pk:
            self.add_error("product_variant","Choose a variant of the selected product model.")
        return data


@never_cache
@login_required(login_url="operations:login")
@require_http_methods(["GET","POST"])
def register(request,pk):
    customer=get_object_or_404(customers(request.user),pk=pk,is_active=True)
    for permission in PERMISSIONS:
        require_permission(user=request.user,permission=permission,target=customer.company)
    form=RegistrationForm(request.POST if request.method=="POST" else None)
    if request.method=="POST" and form.is_valid():
        try:
            with transaction.atomic():
                data=dict(form.cleaned_data)
                data.pop("ownership_confirmed")
                device=services.register_device(**data)
                services.assign_device_owner(device=device,customer=customer)
        except ValidationError as error:
            form.add_error(None,ValidationError(error.messages))
        else:
            return redirect("operations:detail",kind="devices",pk=device.pk)
    return render(request,"operations/device_registration.html",dict(title="Register customer's device",customer=customer,form=form),
        status=400 if request.method=="POST" else 200)
