"""Explicit ownership operations; historical rows are audit-only."""
from django import forms
from django.contrib import admin, messages
from django.core.exceptions import ValidationError
from django.http import HttpResponseRedirect

from apps.customers.models import Customer
from . import services
from .evidence_admin import RevisionForm
from .models import CustomerDeviceRelationship as Relationship, Device


class CustomerChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, obj):
        return f"{obj.company} / {obj.customer_number} / {obj.display_name}"


class OwnershipCreateForm(forms.ModelForm):
    started_at = forms.DateTimeField(required=False)
    customer = CustomerChoiceField(queryset=Customer.objects.select_related("company"))
    device = forms.ModelChoiceField(queryset=Device.objects.select_related("product_model__brand"))

    class Meta:
        model = Relationship
        fields = ("device", "customer", "started_at", "note")


class OwnershipOperationForm(RevisionForm):
    operation = forms.ChoiceField(choices=[("", "---------"), ("transfer", "Transfer ownership"), ("end", "End ownership")])
    new_customer = CustomerChoiceField(queryset=Customer.objects.select_related("company"), required=False)
    event_at = forms.DateTimeField(required=False, help_text="Blank uses the time the operation acquires its locks.")
    reason = forms.CharField(max_length=2000, required=False, widget=forms.Textarea)
    new_note = forms.CharField(max_length=2000, required=False, widget=forms.Textarea)

    class Meta:
        model = Relationship
        fields = ()

    def clean(self):
        data = super().clean()
        if data.get("operation") == "transfer" and not data.get("new_customer"):
            raise ValidationError("Choose the new customer for transfer.")
        if data.get("operation") == "end" and (data.get("new_customer") or data.get("new_note")):
            raise ValidationError("Ending ownership accepts a reason, not a new customer or note.")
        return data


class CurrentFilter(admin.SimpleListFilter):
    title = "ownership state"
    parameter_name = "current"

    def lookups(self, request, model_admin):
        return [("yes", "Current"), ("no", "Historical")]

    def queryset(self, request, queryset):
        if self.value() in ("yes", "no"):
            return queryset.filter(ended_at__isnull=self.value() == "yes")
        return queryset


@admin.register(Relationship)
class CustomerDeviceRelationshipAdmin(admin.ModelAdmin):
    list_display = ("device", "customer", "customer_company", "relationship_type", "started_at", "ended_at", "is_current")
    list_filter = (CurrentFilter, "customer__company", "relationship_type")
    search_fields = ("customer__customer_number", "customer__full_name", "customer__organization_name", "=device__identifiers__normalized_value")
    list_select_related = ("customer__company", "device__product_model__brand")
    actions = None

    @admin.display(description="Company", ordering="customer__company")
    def customer_company(self, obj):
        return obj.customer.company

    @admin.display(boolean=True, description="Current")
    def is_current(self, obj):
        return obj.ended_at is None

    def has_delete_permission(self, request, obj=None):
        return False

    def has_change_permission(self, request, obj=None):
        return super().has_change_permission(request, obj) and (obj is None or obj.ended_at is None)

    def get_form(self, request, obj=None, **kwargs):
        kwargs["form"] = OwnershipOperationForm if obj else OwnershipCreateForm
        return super().get_form(request, obj, **kwargs)

    def get_readonly_fields(self, request, obj=None):
        fields = ("id", "relationship_type", "ended_at", "end_reason", "created_at", "updated_at")
        return fields + (("device", "customer", "started_at", "note") if obj else ())

    def get_fields(self, request, obj=None):
        fields = ("device", "customer", "relationship_type", "started_at", "ended_at", "end_reason", "note", "id", "created_at", "updated_at")
        if obj and obj.ended_at is None:
            fields += ("revision", "operation", "new_customer", "event_at", "reason", "new_note")
        return fields

    def save_model(self, request, obj, form, change):
        data = form.cleaned_data
        if not change:
            current = services.assign_device_owner(device=obj.device, customer=obj.customer, started_at=data.get("started_at"), note=data["note"])
        else:
            kwargs = dict(device=obj.device, reason=data["reason"], expected_current_relationship_id=obj.pk)
            if data["operation"] == "transfer":
                services.transfer_device_ownership(**kwargs, new_customer=data["new_customer"], transferred_at=data["event_at"], note=data["new_note"])
            else:
                services.end_device_ownership(**kwargs, ended_at=data["event_at"])
            current = Relationship.objects.get(pk=obj.pk)
        for field in obj._meta.concrete_fields:
            setattr(obj, field.attname, getattr(current, field.attname))
        obj._state = current._state

    def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
        try:
            return super().changeform_view(request, object_id, form_url, extra_context)
        except ValidationError:
            self.message_user(request, "Ownership operation rejected. Reload and review current ownership and lifecycle state.", messages.ERROR)
            return HttpResponseRedirect(request.path)

    def construct_change_message(self, request, form, formsets, add=False):
        return "Assigned, transferred or ended recorded ownership."
